/* Subroutine */ int dspsvx_(char *fact, char *uplo, integer *n, integer * nrhs, doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, integer *info) { /* System generated locals */ integer b_dim1, b_offset, x_dim1, x_offset, i__1; /* Local variables */ extern logical lsame_(char *, char *); doublereal anorm; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); extern doublereal dlamch_(char *); logical nofact; extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), xerbla_(char *, integer *); extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); extern /* Subroutine */ int dspcon_(char *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *), dsprfs_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *), dsptrf_(char *, integer *, doublereal *, integer *, integer *), dsptrs_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *); /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPSVX uses the diagonal pivoting factorization A = U*D*U**T or */ /* A = L*D*L**T to compute the solution to a real system of linear */ /* equations A * X = B, where A is an N-by-N symmetric matrix stored */ /* in packed format and X and B are N-by-NRHS matrices. */ /* Error bounds on the solution and a condition estimate are also */ /* provided. */ /* Description */ /* =========== */ /* The following steps are performed: */ /* 1. If FACT = 'N', the diagonal pivoting method is used to factor A as */ /* A = U * D * U**T, if UPLO = 'U', or */ /* A = L * D * L**T, if UPLO = 'L', */ /* where U (or L) is a product of permutation and unit upper (lower) */ /* triangular matrices and D is symmetric and block diagonal with */ /* 1-by-1 and 2-by-2 diagonal blocks. */ /* 2. If some D(i,i)=0, so that D is exactly singular, then the routine */ /* returns with INFO = i. Otherwise, the factored form of A is used */ /* to estimate the condition number of the matrix A. If the */ /* reciprocal of the condition number is less than machine precision, */ /* INFO = N+1 is returned as a warning, but the routine still goes on */ /* to solve for X and compute error bounds as described below. */ /* 3. The system of equations is solved for X using the factored form */ /* of A. */ /* 4. Iterative refinement is applied to improve the computed solution */ /* matrix and calculate error bounds and backward error estimates */ /* for it. */ /* Arguments */ /* ========= */ /* FACT (input) CHARACTER*1 */ /* Specifies whether or not the factored form of A has been */ /* supplied on entry. */ /* = 'F': On entry, AFP and IPIV contain the factored form of */ /* A. AP, AFP and IPIV will not be modified. */ /* = 'N': The matrix A will be copied to AFP and factored. */ /* UPLO (input) CHARACTER*1 */ /* = 'U': Upper triangle of A is stored; */ /* = 'L': Lower triangle of A is stored. */ /* N (input) INTEGER */ /* The number of linear equations, i.e., the order of the */ /* matrix A. N >= 0. */ /* NRHS (input) INTEGER */ /* The number of right hand sides, i.e., the number of columns */ /* of the matrices B and X. NRHS >= 0. */ /* AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* The upper or lower triangle of the symmetric matrix A, packed */ /* columnwise in a linear array. The j-th column of A is stored */ /* in the array AP as follows: */ /* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; */ /* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n. */ /* See below for further details. */ /* AFP (input or output) DOUBLE PRECISION array, dimension */ /* (N*(N+1)/2) */ /* If FACT = 'F', then AFP is an input argument and on entry */ /* contains the block diagonal matrix D and the multipliers used */ /* to obtain the factor U or L from the factorization */ /* A = U*D*U**T or A = L*D*L**T as computed by DSPTRF, stored as */ /* a packed triangular matrix in the same storage format as A. */ /* If FACT = 'N', then AFP is an output argument and on exit */ /* contains the block diagonal matrix D and the multipliers used */ /* to obtain the factor U or L from the factorization */ /* A = U*D*U**T or A = L*D*L**T as computed by DSPTRF, stored as */ /* a packed triangular matrix in the same storage format as A. */ /* IPIV (input or output) INTEGER array, dimension (N) */ /* If FACT = 'F', then IPIV is an input argument and on entry */ /* contains details of the interchanges and the block structure */ /* of D, as determined by DSPTRF. */ /* If IPIV(k) > 0, then rows and columns k and IPIV(k) were */ /* interchanged and D(k,k) is a 1-by-1 diagonal block. */ /* If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and */ /* columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k) */ /* is a 2-by-2 diagonal block. If UPLO = 'L' and IPIV(k) = */ /* IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were */ /* interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block. */ /* If FACT = 'N', then IPIV is an output argument and on exit */ /* contains details of the interchanges and the block structure */ /* of D, as determined by DSPTRF. */ /* B (input) DOUBLE PRECISION array, dimension (LDB,NRHS) */ /* The N-by-NRHS right hand side matrix B. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,N). */ /* X (output) DOUBLE PRECISION array, dimension (LDX,NRHS) */ /* If INFO = 0 or INFO = N+1, the N-by-NRHS solution matrix X. */ /* LDX (input) INTEGER */ /* The leading dimension of the array X. LDX >= max(1,N). */ /* RCOND (output) DOUBLE PRECISION */ /* The estimate of the reciprocal condition number of the matrix */ /* A. If RCOND is less than the machine precision (in */ /* particular, if RCOND = 0), the matrix is singular to working */ /* precision. This condition is indicated by a return code of */ /* INFO > 0. */ /* FERR (output) DOUBLE PRECISION array, dimension (NRHS) */ /* The estimated forward error bound for each solution vector */ /* X(j) (the j-th column of the solution matrix X). */ /* If XTRUE is the true solution corresponding to X(j), FERR(j) */ /* is an estimated upper bound for the magnitude of the largest */ /* element in (X(j) - XTRUE) divided by the magnitude of the */ /* largest element in X(j). The estimate is as reliable as */ /* the estimate for RCOND, and is almost always a slight */ /* overestimate of the true error. */ /* BERR (output) DOUBLE PRECISION array, dimension (NRHS) */ /* The componentwise relative backward error of each solution */ /* vector X(j) (i.e., the smallest relative change in */ /* any element of A or B that makes X(j) an exact solution). */ /* WORK (workspace) DOUBLE PRECISION array, dimension (3*N) */ /* IWORK (workspace) INTEGER array, dimension (N) */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* > 0: if INFO = i, and i is */ /* <= N: D(i,i) is exactly zero. The factorization */ /* has been completed but the factor D is exactly */ /* singular, so the solution and error bounds could */ /* not be computed. RCOND = 0 is returned. */ /* = N+1: D is nonsingular, but RCOND is less than machine */ /* precision, meaning that the matrix is singular */ /* to working precision. Nevertheless, the */ /* solution and error bounds are computed because */ /* there are a number of situations where the */ /* computed solution can be more accurate than the */ /* value of RCOND would suggest. */ /* Further Details */ /* =============== */ /* The packed storage scheme is illustrated by the following example */ /* when N = 4, UPLO = 'U': */ /* Two-dimensional storage of the symmetric matrix A: */ /* a11 a12 a13 a14 */ /* a22 a23 a24 */ /* a33 a34 (aij = aji) */ /* a44 */ /* Packed storage of the upper triangle of A: */ /* AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ] */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --afp; --ipiv; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; x_dim1 = *ldx; x_offset = 1 + x_dim1; x -= x_offset; --ferr; --berr; --work; --iwork; /* Function Body */ *info = 0; nofact = lsame_(fact, "N"); if (! nofact && ! lsame_(fact, "F")) { *info = -1; } else if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*nrhs < 0) { *info = -4; } else if (*ldb < max(1,*n)) { *info = -9; } else if (*ldx < max(1,*n)) { *info = -11; } if (*info != 0) { i__1 = -(*info); xerbla_("DSPSVX", &i__1); return 0; } if (nofact) { /* Compute the factorization A = U*D*U' or A = L*D*L'. */ i__1 = *n * (*n + 1) / 2; dcopy_(&i__1, &ap[1], &c__1, &afp[1], &c__1); dsptrf_(uplo, n, &afp[1], &ipiv[1], info); /* Return if INFO is non-zero. */ if (*info > 0) { *rcond = 0.; return 0; } } /* Compute the norm of the matrix A. */ anorm = dlansp_("I", uplo, n, &ap[1], &work[1]); /* Compute the reciprocal of the condition number of A. */ dspcon_(uplo, n, &afp[1], &ipiv[1], &anorm, rcond, &work[1], &iwork[1], info); /* Compute the solution vectors X. */ dlacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx); dsptrs_(uplo, n, nrhs, &afp[1], &ipiv[1], &x[x_offset], ldx, info); /* Use iterative refinement to improve the computed solutions and */ /* compute error bounds and backward error estimates for them. */ dsprfs_(uplo, n, nrhs, &ap[1], &afp[1], &ipiv[1], &b[b_offset], ldb, &x[ x_offset], ldx, &ferr[1], &berr[1], &work[1], &iwork[1], info); /* Set INFO = N+1 if the matrix is singular to working precision. */ if (*rcond < dlamch_("Epsilon")) { *info = *n + 1; } return 0; /* End of DSPSVX */ } /* dspsvx_ */
/* Subroutine */ int dppt01_(char *uplo, integer *n, doublereal *a, doublereal *afac, doublereal *rwork, doublereal *resid) { /* System generated locals */ integer i__1; /* Local variables */ extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); extern /* Subroutine */ int dspr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *); static integer i__, k; static doublereal t; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); extern logical lsame_(char *, char *); static doublereal anorm; extern /* Subroutine */ int dtpmv_(char *, char *, char *, integer *, doublereal *, doublereal *, integer *); static integer kc; extern doublereal dlamch_(char *), dlansp_(char *, char *, integer *, doublereal *, doublereal *); static doublereal eps; static integer npp; /* -- LAPACK test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University February 29, 1992 Purpose ======= DPPT01 reconstructs a symmetric positive definite packed matrix A from its L*L' or U'*U factorization and computes the residual norm( L*L' - A ) / ( N * norm(A) * EPS ) or norm( U'*U - A ) / ( N * norm(A) * EPS ), where EPS is the machine epsilon. Arguments ========== UPLO (input) CHARACTER*1 Specifies whether the upper or lower triangular part of the symmetric matrix A is stored: = 'U': Upper triangular = 'L': Lower triangular N (input) INTEGER The number of rows and columns of the matrix A. N >= 0. A (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) The original symmetric matrix A, stored as a packed triangular matrix. AFAC (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) On entry, the factor L or U from the L*L' or U'*U factorization of A, stored as a packed triangular matrix. Overwritten with the reconstructed matrix, and then with the difference L*L' - A (or U'*U - A). RWORK (workspace) DOUBLE PRECISION array, dimension (N) RESID (output) DOUBLE PRECISION If UPLO = 'L', norm(L*L' - A) / ( N * norm(A) * EPS ) If UPLO = 'U', norm(U'*U - A) / ( N * norm(A) * EPS ) ===================================================================== Quick exit if N = 0 Parameter adjustments */ --rwork; --afac; --a; /* Function Body */ if (*n <= 0) { *resid = 0.; return 0; } /* Exit with RESID = 1/EPS if ANORM = 0. */ eps = dlamch_("Epsilon"); anorm = dlansp_("1", uplo, n, &a[1], &rwork[1]); if (anorm <= 0.) { *resid = 1. / eps; return 0; } /* Compute the product U'*U, overwriting U. */ if (lsame_(uplo, "U")) { kc = *n * (*n - 1) / 2 + 1; for (k = *n; k >= 1; --k) { /* Compute the (K,K) element of the result. */ t = ddot_(&k, &afac[kc], &c__1, &afac[kc], &c__1); afac[kc + k - 1] = t; /* Compute the rest of column K. */ if (k > 1) { i__1 = k - 1; dtpmv_("Upper", "Transpose", "Non-unit", &i__1, &afac[1], & afac[kc], &c__1); kc -= k - 1; } /* L10: */ } /* Compute the product L*L', overwriting L. */ } else { kc = *n * (*n + 1) / 2; for (k = *n; k >= 1; --k) { /* Add a multiple of column K of the factor L to each of columns K+1 through N. */ if (k < *n) { i__1 = *n - k; dspr_("Lower", &i__1, &c_b14, &afac[kc + 1], &c__1, &afac[kc + *n - k + 1]); } /* Scale column K by the diagonal element. */ t = afac[kc]; i__1 = *n - k + 1; dscal_(&i__1, &t, &afac[kc], &c__1); kc -= *n - k + 2; /* L20: */ } } /* Compute the difference L*L' - A (or U'*U - A). */ npp = *n * (*n + 1) / 2; i__1 = npp; for (i__ = 1; i__ <= i__1; ++i__) { afac[i__] -= a[i__]; /* L30: */ } /* Compute norm( L*U - A ) / ( N * norm(A) * EPS ) */ *resid = dlansp_("1", uplo, n, &afac[1], &rwork[1]); *resid = *resid / (doublereal) (*n) / anorm / eps; return 0; /* End of DPPT01 */ } /* dppt01_ */
/* Subroutine */ int dlatmr_(integer *m, integer *n, char *dist, integer * iseed, char *sym, doublereal *d__, integer *mode, doublereal *cond, doublereal *dmax__, char *rsign, char *grade, doublereal *dl, integer *model, doublereal *condl, doublereal *dr, integer *moder, doublereal *condr, char *pivtng, integer *ipivot, integer *kl, integer *ku, doublereal *sparse, doublereal *anorm, char *pack, doublereal *a, integer *lda, integer *iwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; doublereal d__1, d__2, d__3; /* Local variables */ static integer isub, jsub; static doublereal temp; static integer isym, i__, j, k; static doublereal alpha; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); static integer ipack; extern logical lsame_(char *, char *); static doublereal tempa[1]; static integer iisub, idist, jjsub, mnmin; static logical dzero; static integer mnsub; static doublereal onorm; static integer mxsub, npvts; extern /* Subroutine */ int dlatm1_(integer *, doublereal *, integer *, integer *, integer *, doublereal *, integer *, integer *); extern doublereal dlatm2_(integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *) , dlatm3_(integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *), dlangb_(char *, integer *, integer *, integer *, doublereal *, integer *, doublereal *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); static integer igrade; extern doublereal dlansb_(char *, char *, integer *, integer *, doublereal *, integer *, doublereal *); static logical fulbnd; extern /* Subroutine */ int xerbla_(char *, integer *); static logical badpvt; extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *), dlansy_(char *, char *, integer *, doublereal *, integer *, doublereal *); static integer irsign, ipvtng, kll, kuu; #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 February 29, 1992 Purpose ======= DLATMR generates random matrices of various types for testing LAPACK programs. DLATMR operates by applying the following sequence of operations: Generate a matrix A with random entries of distribution DIST which is symmetric if SYM='S', and nonsymmetric if SYM='N'. Set the diagonal to D, where D may be input or computed according to MODE, COND, DMAX and RSIGN as described below. Grade the matrix, if desired, from the left and/or right as specified by GRADE. The inputs DL, MODEL, CONDL, DR, MODER and CONDR also determine the grading as described below. Permute, if desired, the rows and/or columns as specified by PIVTNG and IPIVOT. Set random entries to zero, if desired, to get a random sparse matrix as specified by SPARSE. Make A a band matrix, if desired, by zeroing out the matrix outside a band of lower bandwidth KL and upper bandwidth KU. Scale A, if desired, to have maximum entry ANORM. Pack the matrix if desired. Options specified by PACK are: no packing zero out upper half (if symmetric) zero out lower half (if symmetric) store the upper half columnwise (if symmetric or square upper triangular) store the lower half columnwise (if symmetric or square lower triangular) same as upper half rowwise if symmetric store the lower triangle in banded format (if symmetric) store the upper triangle in banded format (if symmetric) store the entire matrix in banded format Note: If two calls to DLATMR differ only in the PACK parameter, they will generate mathematically equivalent matrices. If two calls to DLATMR both have full bandwidth (KL = M-1 and KU = N-1), and differ only in the PIVTNG and PACK parameters, then the matrices generated will differ only in the order of the rows and/or columns, and otherwise contain the same data. This consistency cannot be and is not maintained with less than full bandwidth. Arguments ========= M - INTEGER Number of rows of A. Not modified. N - INTEGER Number of columns of A. Not modified. DIST - CHARACTER*1 On entry, DIST specifies the type of distribution to be used to generate a random matrix . 'U' => UNIFORM( 0, 1 ) ( 'U' for uniform ) 'S' => UNIFORM( -1, 1 ) ( 'S' for symmetric ) 'N' => NORMAL( 0, 1 ) ( 'N' for normal ) Not modified. ISEED - INTEGER array, dimension (4) On entry ISEED specifies the seed of the random number generator. They should lie between 0 and 4095 inclusive, and ISEED(4) should 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 DLATMR to continue the same random number sequence. Changed on exit. SYM - CHARACTER*1 If SYM='S' or 'H', generated matrix is symmetric. If SYM='N', generated matrix is nonsymmetric. Not modified. D - DOUBLE PRECISION array, dimension (min(M,N)) On entry this array specifies the diagonal entries of the diagonal of A. D may either be specified on entry, or set according to MODE and COND as described below. May be changed on exit if MODE is nonzero. MODE - INTEGER On entry describes how D is to be used: MODE = 0 means use D as input MODE = 1 sets D(1)=1 and D(2:N)=1.0/COND MODE = 2 sets D(1:N-1)=1 and D(N)=1.0/COND MODE = 3 sets D(I)=COND**(-(I-1)/(N-1)) MODE = 4 sets D(i)=1 - (i-1)/(N-1)*(1 - 1/COND) MODE = 5 sets D to random numbers in the range ( 1/COND , 1 ) such that their logarithms are uniformly distributed. MODE = 6 set D to random numbers from same distribution as the rest of the matrix. MODE < 0 has the same meaning as ABS(MODE), except that the order of the elements of D is reversed. Thus if MODE is positive, D has entries ranging from 1 to 1/COND, if negative, from 1/COND to 1, Not modified. COND - DOUBLE PRECISION On entry, used as described under MODE above. If used, it must be >= 1. Not modified. DMAX - DOUBLE PRECISION If MODE neither -6, 0 nor 6, the diagonal is scaled by DMAX / max(abs(D(i))), so that maximum absolute entry of diagonal is abs(DMAX). If DMAX is negative (or zero), diagonal will be scaled by a negative number (or zero). RSIGN - CHARACTER*1 If MODE neither -6, 0 nor 6, specifies sign of diagonal as follows: 'T' => diagonal entries are multiplied by 1 or -1 with probability .5 'F' => diagonal unchanged Not modified. GRADE - CHARACTER*1 Specifies grading of matrix as follows: 'N' => no grading 'L' => matrix premultiplied by diag( DL ) (only if matrix nonsymmetric) 'R' => matrix postmultiplied by diag( DR ) (only if matrix nonsymmetric) 'B' => matrix premultiplied by diag( DL ) and postmultiplied by diag( DR ) (only if matrix nonsymmetric) 'S' or 'H' => matrix premultiplied by diag( DL ) and postmultiplied by diag( DL ) ('S' for symmetric, or 'H' for Hermitian) 'E' => matrix premultiplied by diag( DL ) and postmultiplied by inv( diag( DL ) ) ( 'E' for eigenvalue invariance) (only if matrix nonsymmetric) Note: if GRADE='E', then M must equal N. Not modified. DL - DOUBLE PRECISION array, dimension (M) If MODEL=0, then on entry this array specifies the diagonal entries of a diagonal matrix used as described under GRADE above. If MODEL is not zero, then DL will be set according to MODEL and CONDL, analogous to the way D is set according to MODE and COND (except there is no DMAX parameter for DL). If GRADE='E', then DL cannot have zero entries. Not referenced if GRADE = 'N' or 'R'. Changed on exit. MODEL - INTEGER This specifies how the diagonal array DL is to be computed, just as MODE specifies how D is to be computed. Not modified. CONDL - DOUBLE PRECISION When MODEL is not zero, this specifies the condition number of the computed DL. Not modified. DR - DOUBLE PRECISION array, dimension (N) If MODER=0, then on entry this array specifies the diagonal entries of a diagonal matrix used as described under GRADE above. If MODER is not zero, then DR will be set according to MODER and CONDR, analogous to the way D is set according to MODE and COND (except there is no DMAX parameter for DR). Not referenced if GRADE = 'N', 'L', 'H', 'S' or 'E'. Changed on exit. MODER - INTEGER This specifies how the diagonal array DR is to be computed, just as MODE specifies how D is to be computed. Not modified. CONDR - DOUBLE PRECISION When MODER is not zero, this specifies the condition number of the computed DR. Not modified. PIVTNG - CHARACTER*1 On entry specifies pivoting permutations as follows: 'N' or ' ' => none. 'L' => left or row pivoting (matrix must be nonsymmetric). 'R' => right or column pivoting (matrix must be nonsymmetric). 'B' or 'F' => both or full pivoting, i.e., on both sides. In this case, M must equal N If two calls to DLATMR both have full bandwidth (KL = M-1 and KU = N-1), and differ only in the PIVTNG and PACK parameters, then the matrices generated will differ only in the order of the rows and/or columns, and otherwise contain the same data. This consistency cannot be maintained with less than full bandwidth. IPIVOT - INTEGER array, dimension (N or M) This array specifies the permutation used. After the basic matrix is generated, the rows, columns, or both are permuted. If, say, row pivoting is selected, DLATMR starts with the *last* row and interchanges the M-th and IPIVOT(M)-th rows, then moves to the next-to-last row, interchanging the (M-1)-th and the IPIVOT(M-1)-th rows, and so on. In terms of "2-cycles", the permutation is (1 IPIVOT(1)) (2 IPIVOT(2)) ... (M IPIVOT(M)) where the rightmost cycle is applied first. This is the *inverse* of the effect of pivoting in LINPACK. The idea is that factoring (with pivoting) an identity matrix which has been inverse-pivoted in this way should result in a pivot vector identical to IPIVOT. Not referenced if PIVTNG = 'N'. Not modified. SPARSE - DOUBLE PRECISION On entry specifies the sparsity of the matrix if a sparse matrix is to be generated. SPARSE should lie between 0 and 1. To generate a sparse matrix, for each matrix entry a uniform ( 0, 1 ) random number x is generated and compared to SPARSE; if x is larger the matrix entry is unchanged and if x is smaller the entry is set to zero. Thus on the average a fraction SPARSE of the entries will be set to zero. Not modified. KL - INTEGER On entry specifies the lower bandwidth of the matrix. For example, KL=0 implies upper triangular, KL=1 implies upper Hessenberg, and KL at least M-1 implies the matrix is not banded. Must equal KU if matrix is symmetric. Not modified. KU - INTEGER On entry specifies the upper bandwidth of the matrix. For example, KU=0 implies lower triangular, KU=1 implies lower Hessenberg, and KU at least N-1 implies the matrix is not banded. Must equal KL if matrix is symmetric. Not modified. ANORM - DOUBLE PRECISION On entry specifies maximum entry of output matrix (output matrix will by multiplied by a constant so that its largest absolute entry equal ANORM) if ANORM is nonnegative. If ANORM is negative no scaling is done. Not modified. PACK - CHARACTER*1 On entry specifies packing of matrix as follows: 'N' => no packing 'U' => zero out all subdiagonal entries (if symmetric) 'L' => zero out all superdiagonal entries (if symmetric) 'C' => store the upper triangle columnwise (only if matrix symmetric or square upper triangular) 'R' => store the lower triangle columnwise (only if matrix symmetric or square lower triangular) (same as upper half rowwise if symmetric) 'B' => store the lower triangle in band storage scheme (only if matrix symmetric) 'Q' => store the upper triangle in band storage scheme (only if matrix symmetric) 'Z' => store the entire matrix in band storage scheme (pivoting can be provided for by using this option to store A in the trailing rows of the allocated storage) Using these options, the various LAPACK packed and banded storage schemes can be obtained: GB - use 'Z' PB, SB or TB - use 'B' or 'Q' PP, SP or TP - use 'C' or 'R' If two calls to DLATMR differ only in the PACK parameter, they will generate mathematically equivalent matrices. Not modified. A - DOUBLE PRECISION array, dimension (LDA,N) On exit A is the desired test matrix. Only those entries of A which are significant on output will be referenced (even if A is in packed or band storage format). The 'unoccupied corners' of A in band format will be zeroed out. LDA - INTEGER on entry LDA specifies the first dimension of A as declared in the calling program. If PACK='N', 'U' or 'L', LDA must be at least max ( 1, M ). If PACK='C' or 'R', LDA must be at least 1. If PACK='B', or 'Q', LDA must be MIN ( KU+1, N ) If PACK='Z', LDA must be at least KUU+KLL+1, where KUU = MIN ( KU, N-1 ) and KLL = MIN ( KL, N-1 ) Not modified. IWORK - INTEGER array, dimension ( N or M) Workspace. Not referenced if PIVTNG = 'N'. Changed on exit. INFO - INTEGER Error parameter on exit: 0 => normal return -1 => M negative or unequal to N and SYM='S' or 'H' -2 => N negative -3 => DIST illegal string -5 => SYM illegal string -7 => MODE not in range -6 to 6 -8 => COND less than 1.0, and MODE neither -6, 0 nor 6 -10 => MODE neither -6, 0 nor 6 and RSIGN illegal string -11 => GRADE illegal string, or GRADE='E' and M not equal to N, or GRADE='L', 'R', 'B' or 'E' and SYM = 'S' or 'H' -12 => GRADE = 'E' and DL contains zero -13 => MODEL not in range -6 to 6 and GRADE= 'L', 'B', 'H', 'S' or 'E' -14 => CONDL less than 1.0, GRADE='L', 'B', 'H', 'S' or 'E', and MODEL neither -6, 0 nor 6 -16 => MODER not in range -6 to 6 and GRADE= 'R' or 'B' -17 => CONDR less than 1.0, GRADE='R' or 'B', and MODER neither -6, 0 nor 6 -18 => PIVTNG illegal string, or PIVTNG='B' or 'F' and M not equal to N, or PIVTNG='L' or 'R' and SYM='S' or 'H' -19 => IPIVOT contains out of range number and PIVTNG not equal to 'N' -20 => KL negative -21 => KU negative, or SYM='S' or 'H' and KU not equal to KL -22 => SPARSE not in range 0. to 1. -24 => PACK illegal string, or PACK='U', 'L', 'B' or 'Q' and SYM='N', or PACK='C' and SYM='N' and either KL not equal to 0 or N not equal to M, or PACK='R' and SYM='N', and either KU not equal to 0 or N not equal to M -26 => LDA too small 1 => Error return from DLATM1 (computing D) 2 => Cannot scale diagonal to DMAX (max. entry is 0) 3 => Error return from DLATM1 (computing DL) 4 => Error return from DLATM1 (computing DR) 5 => ANORM is positive, but matrix constructed prior to attempting to scale it to have norm ANORM, is zero ===================================================================== 1) Decode and Test the input parameters. Initialize flags & seed. Parameter adjustments */ --iseed; --d__; --dl; --dr; --ipivot; a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --iwork; /* Function Body */ *info = 0; /* Quick return if possible */ if (*m == 0 || *n == 0) { return 0; } /* Decode DIST */ if (lsame_(dist, "U")) { idist = 1; } else if (lsame_(dist, "S")) { idist = 2; } else if (lsame_(dist, "N")) { idist = 3; } else { idist = -1; } /* Decode SYM */ if (lsame_(sym, "S")) { isym = 0; } else if (lsame_(sym, "N")) { isym = 1; } else if (lsame_(sym, "H")) { isym = 0; } else { isym = -1; } /* Decode RSIGN */ if (lsame_(rsign, "F")) { irsign = 0; } else if (lsame_(rsign, "T")) { irsign = 1; } else { irsign = -1; } /* Decode PIVTNG */ if (lsame_(pivtng, "N")) { ipvtng = 0; } else if (lsame_(pivtng, " ")) { ipvtng = 0; } else if (lsame_(pivtng, "L")) { ipvtng = 1; npvts = *m; } else if (lsame_(pivtng, "R")) { ipvtng = 2; npvts = *n; } else if (lsame_(pivtng, "B")) { ipvtng = 3; npvts = min(*n,*m); } else if (lsame_(pivtng, "F")) { ipvtng = 3; npvts = min(*n,*m); } else { ipvtng = -1; } /* Decode GRADE */ if (lsame_(grade, "N")) { igrade = 0; } else if (lsame_(grade, "L")) { igrade = 1; } else if (lsame_(grade, "R")) { igrade = 2; } else if (lsame_(grade, "B")) { igrade = 3; } else if (lsame_(grade, "E")) { igrade = 4; } else if (lsame_(grade, "H") || lsame_(grade, "S")) { igrade = 5; } else { igrade = -1; } /* Decode PACK */ if (lsame_(pack, "N")) { ipack = 0; } else if (lsame_(pack, "U")) { ipack = 1; } else if (lsame_(pack, "L")) { ipack = 2; } else if (lsame_(pack, "C")) { ipack = 3; } else if (lsame_(pack, "R")) { ipack = 4; } else if (lsame_(pack, "B")) { ipack = 5; } else if (lsame_(pack, "Q")) { ipack = 6; } else if (lsame_(pack, "Z")) { ipack = 7; } else { ipack = -1; } /* Set certain internal parameters */ mnmin = min(*m,*n); /* Computing MIN */ i__1 = *kl, i__2 = *m - 1; kll = min(i__1,i__2); /* Computing MIN */ i__1 = *ku, i__2 = *n - 1; kuu = min(i__1,i__2); /* If inv(DL) is used, check to see if DL has a zero entry. */ dzero = FALSE_; if (igrade == 4 && *model == 0) { i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { if (dl[i__] == 0.) { dzero = TRUE_; } /* L10: */ } } /* Check values in IPIVOT */ badpvt = FALSE_; if (ipvtng > 0) { i__1 = npvts; for (j = 1; j <= i__1; ++j) { if (ipivot[j] <= 0 || ipivot[j] > npvts) { badpvt = TRUE_; } /* L20: */ } } /* Set INFO if an error */ if (*m < 0) { *info = -1; } else if (*m != *n && isym == 0) { *info = -1; } else if (*n < 0) { *info = -2; } else if (idist == -1) { *info = -3; } else if (isym == -1) { *info = -5; } else if (*mode < -6 || *mode > 6) { *info = -7; } else if (*mode != -6 && *mode != 0 && *mode != 6 && *cond < 1.) { *info = -8; } else if (*mode != -6 && *mode != 0 && *mode != 6 && irsign == -1) { *info = -10; } else if (igrade == -1 || igrade == 4 && *m != *n || igrade >= 1 && igrade <= 4 && isym == 0) { *info = -11; } else if (igrade == 4 && dzero) { *info = -12; } else if ((igrade == 1 || igrade == 3 || igrade == 4 || igrade == 5) && ( *model < -6 || *model > 6)) { *info = -13; } else if ((igrade == 1 || igrade == 3 || igrade == 4 || igrade == 5) && ( *model != -6 && *model != 0 && *model != 6) && *condl < 1.) { *info = -14; } else if ((igrade == 2 || igrade == 3) && (*moder < -6 || *moder > 6)) { *info = -16; } else if ((igrade == 2 || igrade == 3) && (*moder != -6 && *moder != 0 && *moder != 6) && *condr < 1.) { *info = -17; } else if (ipvtng == -1 || ipvtng == 3 && *m != *n || (ipvtng == 1 || ipvtng == 2) && isym == 0) { *info = -18; } else if (ipvtng != 0 && badpvt) { *info = -19; } else if (*kl < 0) { *info = -20; } else if (*ku < 0 || isym == 0 && *kl != *ku) { *info = -21; } else if (*sparse < 0. || *sparse > 1.) { *info = -22; } else if (ipack == -1 || (ipack == 1 || ipack == 2 || ipack == 5 || ipack == 6) && isym == 1 || ipack == 3 && isym == 1 && (*kl != 0 || *m != *n) || ipack == 4 && isym == 1 && (*ku != 0 || *m != *n)) { *info = -24; } else if ((ipack == 0 || ipack == 1 || ipack == 2) && *lda < max(1,*m) || (ipack == 3 || ipack == 4) && *lda < 1 || (ipack == 5 || ipack == 6) && *lda < kuu + 1 || ipack == 7 && *lda < kll + kuu + 1) { *info = -26; } if (*info != 0) { i__1 = -(*info); xerbla_("DLATMR", &i__1); return 0; } /* Decide if we can pivot consistently */ fulbnd = FALSE_; if (kuu == *n - 1 && kll == *m - 1) { fulbnd = TRUE_; } /* Initialize random number generator */ for (i__ = 1; i__ <= 4; ++i__) { iseed[i__] = (i__1 = iseed[i__], abs(i__1)) % 4096; /* L30: */ } iseed[4] = (iseed[4] / 2 << 1) + 1; /* 2) Set up D, DL, and DR, if indicated. Compute D according to COND and MODE */ dlatm1_(mode, cond, &irsign, &idist, &iseed[1], &d__[1], &mnmin, info); if (*info != 0) { *info = 1; return 0; } if (*mode != 0 && *mode != -6 && *mode != 6) { /* Scale by DMAX */ temp = abs(d__[1]); i__1 = mnmin; for (i__ = 2; i__ <= i__1; ++i__) { /* Computing MAX */ d__2 = temp, d__3 = (d__1 = d__[i__], abs(d__1)); temp = max(d__2,d__3); /* L40: */ } if (temp == 0. && *dmax__ != 0.) { *info = 2; return 0; } if (temp != 0.) { alpha = *dmax__ / temp; } else { alpha = 1.; } i__1 = mnmin; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = alpha * d__[i__]; /* L50: */ } } /* Compute DL if grading set */ if (igrade == 1 || igrade == 3 || igrade == 4 || igrade == 5) { dlatm1_(model, condl, &c__0, &idist, &iseed[1], &dl[1], m, info); if (*info != 0) { *info = 3; return 0; } } /* Compute DR if grading set */ if (igrade == 2 || igrade == 3) { dlatm1_(moder, condr, &c__0, &idist, &iseed[1], &dr[1], n, info); if (*info != 0) { *info = 4; return 0; } } /* 3) Generate IWORK if pivoting */ if (ipvtng > 0) { i__1 = npvts; for (i__ = 1; i__ <= i__1; ++i__) { iwork[i__] = i__; /* L60: */ } if (fulbnd) { i__1 = npvts; for (i__ = 1; i__ <= i__1; ++i__) { k = ipivot[i__]; j = iwork[i__]; iwork[i__] = iwork[k]; iwork[k] = j; /* L70: */ } } else { for (i__ = npvts; i__ >= 1; --i__) { k = ipivot[i__]; j = iwork[i__]; iwork[i__] = iwork[k]; iwork[k] = j; /* L80: */ } } } /* 4) Generate matrices for each kind of PACKing Always sweep matrix columnwise (if symmetric, upper half only) so that matrix generated does not depend on PACK */ if (fulbnd) { /* Use DLATM3 so matrices generated with differing PIVOTing only differ only in the order of their rows and/or columns. */ if (ipack == 0) { if (isym == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); a_ref(isub, jsub) = temp; a_ref(jsub, isub) = temp; /* L90: */ } /* L100: */ } } else if (isym == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); a_ref(isub, jsub) = temp; /* L110: */ } /* L120: */ } } } else if (ipack == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); mnsub = min(isub,jsub); mxsub = max(isub,jsub); a_ref(mnsub, mxsub) = temp; if (mnsub != mxsub) { a_ref(mxsub, mnsub) = 0.; } /* L130: */ } /* L140: */ } } else if (ipack == 2) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); mnsub = min(isub,jsub); mxsub = max(isub,jsub); a_ref(mxsub, mnsub) = temp; if (mnsub != mxsub) { a_ref(mnsub, mxsub) = 0.; } /* L150: */ } /* L160: */ } } else if (ipack == 3) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); /* Compute K = location of (ISUB,JSUB) entry in packed array */ mnsub = min(isub,jsub); mxsub = max(isub,jsub); k = mxsub * (mxsub - 1) / 2 + mnsub; /* Convert K to (IISUB,JJSUB) location */ jjsub = (k - 1) / *lda + 1; iisub = k - *lda * (jjsub - 1); a_ref(iisub, jjsub) = temp; /* L170: */ } /* L180: */ } } else if (ipack == 4) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); /* Compute K = location of (I,J) entry in packed array */ mnsub = min(isub,jsub); mxsub = max(isub,jsub); if (mnsub == 1) { k = mxsub; } else { k = *n * (*n + 1) / 2 - (*n - mnsub + 1) * (*n - mnsub + 2) / 2 + mxsub - mnsub + 1; } /* Convert K to (IISUB,JJSUB) location */ jjsub = (k - 1) / *lda + 1; iisub = k - *lda * (jjsub - 1); a_ref(iisub, jjsub) = temp; /* L190: */ } /* L200: */ } } else if (ipack == 5) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { if (i__ < 1) { a_ref(j - i__ + 1, i__ + *n) = 0.; } else { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); mnsub = min(isub,jsub); mxsub = max(isub,jsub); a_ref(mxsub - mnsub + 1, mnsub) = temp; } /* L210: */ } /* L220: */ } } else if (ipack == 6) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); mnsub = min(isub,jsub); mxsub = max(isub,jsub); a_ref(mnsub - mxsub + kuu + 1, mxsub) = temp; /* L230: */ } /* L240: */ } } else if (ipack == 7) { if (isym == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); mnsub = min(isub,jsub); mxsub = max(isub,jsub); a_ref(mnsub - mxsub + kuu + 1, mxsub) = temp; if (i__ < 1) { a_ref(j - i__ + 1 + kuu, i__ + *n) = 0.; } if (i__ >= 1 && mnsub != mxsub) { a_ref(mxsub - mnsub + 1 + kuu, mnsub) = temp; } /* L250: */ } /* L260: */ } } else if (isym == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j + kll; for (i__ = j - kuu; i__ <= i__2; ++i__) { temp = dlatm3_(m, n, &i__, &j, &isub, &jsub, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); a_ref(isub - jsub + kuu + 1, jsub) = temp; /* L270: */ } /* L280: */ } } } } else { /* Use DLATM2 */ if (ipack == 0) { if (isym == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { a_ref(i__, j) = dlatm2_(m, n, &i__, &j, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); a_ref(j, i__) = a_ref(i__, j); /* L290: */ } /* L300: */ } } else if (isym == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { a_ref(i__, j) = dlatm2_(m, n, &i__, &j, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); /* L310: */ } /* L320: */ } } } else if (ipack == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { a_ref(i__, j) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, & iseed[1], &d__[1], &igrade, &dl[1], &dr[1], & ipvtng, &iwork[1], sparse); if (i__ != j) { a_ref(j, i__) = 0.; } /* L330: */ } /* L340: */ } } else if (ipack == 2) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { a_ref(j, i__) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, & iseed[1], &d__[1], &igrade, &dl[1], &dr[1], & ipvtng, &iwork[1], sparse); if (i__ != j) { a_ref(i__, j) = 0.; } /* L350: */ } /* L360: */ } } else if (ipack == 3) { isub = 0; jsub = 1; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { ++isub; if (isub > *lda) { isub = 1; ++jsub; } a_ref(isub, jsub) = dlatm2_(m, n, &i__, &j, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], &dr[1] , &ipvtng, &iwork[1], sparse); /* L370: */ } /* L380: */ } } else if (ipack == 4) { if (isym == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { /* Compute K = location of (I,J) entry in packed array */ if (i__ == 1) { k = j; } else { k = *n * (*n + 1) / 2 - (*n - i__ + 1) * (*n - i__ + 2) / 2 + j - i__ + 1; } /* Convert K to (ISUB,JSUB) location */ jsub = (k - 1) / *lda + 1; isub = k - *lda * (jsub - 1); a_ref(isub, jsub) = dlatm2_(m, n, &i__, &j, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); /* L390: */ } /* L400: */ } } else { isub = 0; jsub = 1; i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *m; for (i__ = j; i__ <= i__2; ++i__) { ++isub; if (isub > *lda) { isub = 1; ++jsub; } a_ref(isub, jsub) = dlatm2_(m, n, &i__, &j, kl, ku, & idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); /* L410: */ } /* L420: */ } } } else if (ipack == 5) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { if (i__ < 1) { a_ref(j - i__ + 1, i__ + *n) = 0.; } else { a_ref(j - i__ + 1, i__) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, &iseed[1], &d__[1], &igrade, &dl[ 1], &dr[1], &ipvtng, &iwork[1], sparse); } /* L430: */ } /* L440: */ } } else if (ipack == 6) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { a_ref(i__ - j + kuu + 1, j) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, &iseed[1], &d__[1], &igrade, &dl[1], & dr[1], &ipvtng, &iwork[1], sparse); /* L450: */ } /* L460: */ } } else if (ipack == 7) { if (isym == 0) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j; for (i__ = j - kuu; i__ <= i__2; ++i__) { a_ref(i__ - j + kuu + 1, j) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, &iseed[1], &d__[1], &igrade, & dl[1], &dr[1], &ipvtng, &iwork[1], sparse); if (i__ < 1) { a_ref(j - i__ + 1 + kuu, i__ + *n) = 0.; } if (i__ >= 1 && i__ != j) { a_ref(j - i__ + 1 + kuu, i__) = a_ref(i__ - j + kuu + 1, j); } /* L470: */ } /* L480: */ } } else if (isym == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j + kll; for (i__ = j - kuu; i__ <= i__2; ++i__) { a_ref(i__ - j + kuu + 1, j) = dlatm2_(m, n, &i__, &j, kl, ku, &idist, &iseed[1], &d__[1], &igrade, & dl[1], &dr[1], &ipvtng, &iwork[1], sparse); /* L490: */ } /* L500: */ } } } } /* 5) Scaling the norm */ if (ipack == 0) { onorm = dlange_("M", m, n, &a[a_offset], lda, tempa); } else if (ipack == 1) { onorm = dlansy_("M", "U", n, &a[a_offset], lda, tempa); } else if (ipack == 2) { onorm = dlansy_("M", "L", n, &a[a_offset], lda, tempa); } else if (ipack == 3) { onorm = dlansp_("M", "U", n, &a[a_offset], tempa); } else if (ipack == 4) { onorm = dlansp_("M", "L", n, &a[a_offset], tempa); } else if (ipack == 5) { onorm = dlansb_("M", "L", n, &kll, &a[a_offset], lda, tempa); } else if (ipack == 6) { onorm = dlansb_("M", "U", n, &kuu, &a[a_offset], lda, tempa); } else if (ipack == 7) { onorm = dlangb_("M", n, &kll, &kuu, &a[a_offset], lda, tempa); } if (*anorm >= 0.) { if (*anorm > 0. && onorm == 0.) { /* Desired scaling impossible */ *info = 5; return 0; } else if (*anorm > 1. && onorm < 1. || *anorm < 1. && onorm > 1.) { /* Scale carefully to avoid over / underflow */ if (ipack <= 2) { i__1 = *n; for (j = 1; j <= i__1; ++j) { d__1 = 1. / onorm; dscal_(m, &d__1, &a_ref(1, j), &c__1); dscal_(m, anorm, &a_ref(1, j), &c__1); /* L510: */ } } else if (ipack == 3 || ipack == 4) { i__1 = *n * (*n + 1) / 2; d__1 = 1. / onorm; dscal_(&i__1, &d__1, &a[a_offset], &c__1); i__1 = *n * (*n + 1) / 2; dscal_(&i__1, anorm, &a[a_offset], &c__1); } else if (ipack >= 5) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = kll + kuu + 1; d__1 = 1. / onorm; dscal_(&i__2, &d__1, &a_ref(1, j), &c__1); i__2 = kll + kuu + 1; dscal_(&i__2, anorm, &a_ref(1, j), &c__1); /* L520: */ } } } else { /* Scale straightforwardly */ if (ipack <= 2) { i__1 = *n; for (j = 1; j <= i__1; ++j) { d__1 = *anorm / onorm; dscal_(m, &d__1, &a_ref(1, j), &c__1); /* L530: */ } } else if (ipack == 3 || ipack == 4) { i__1 = *n * (*n + 1) / 2; d__1 = *anorm / onorm; dscal_(&i__1, &d__1, &a[a_offset], &c__1); } else if (ipack >= 5) { i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = kll + kuu + 1; d__1 = *anorm / onorm; dscal_(&i__2, &d__1, &a_ref(1, j), &c__1); /* L540: */ } } } } /* End of DLATMR */ return 0; } /* dlatmr_ */
/* Subroutine */ int dspevd_(char *jobz, char *uplo, integer *n, doublereal * ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, integer *lwork, integer *iwork, integer *liwork, integer *info) { /* -- LAPACK driver 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 ======= DSPEVD computes all the eigenvalues and, optionally, eigenvectors of a real symmetric matrix A in packed storage. If eigenvectors are desired, it uses a divide and conquer algorithm. The divide and conquer algorithm 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 ========= JOBZ (input) CHARACTER*1 = 'N': Compute eigenvalues only; = 'V': Compute eigenvalues and eigenvectors. UPLO (input) CHARACTER*1 = 'U': Upper triangle of A is stored; = 'L': Lower triangle of A is stored. N (input) INTEGER The order of the matrix A. N >= 0. AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) On entry, the upper or lower triangle of the symmetric matrix A, packed columnwise in a linear array. The j-th column of A is stored in the array AP as follows: if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n. On exit, AP is overwritten by values generated during the reduction to tridiagonal form. If UPLO = 'U', the diagonal and first superdiagonal of the tridiagonal matrix T overwrite the corresponding elements of A, and if UPLO = 'L', the diagonal and first subdiagonal of T overwrite the corresponding elements of A. W (output) DOUBLE PRECISION array, dimension (N) If INFO = 0, the eigenvalues in ascending order. Z (output) DOUBLE PRECISION array, dimension (LDZ, N) If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal eigenvectors of the matrix A, with the i-th column of Z holding the eigenvector associated with W(i). If JOBZ = 'N', then Z is not referenced. LDZ (input) INTEGER The leading dimension of the array Z. LDZ >= 1, and if JOBZ = 'V', LDZ >= max(1,N). WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK) On exit, if INFO = 0, WORK(1) returns the optimal LWORK. LWORK (input) INTEGER The dimension of the array WORK. If N <= 1, LWORK must be at least 1. If JOBZ = 'N' and N > 1, LWORK must be at least 2*N. If JOBZ = 'V' and N > 1, LWORK must be at least 1 + 6*N + N**2. If LWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the WORK array, returns this value as the first entry of the WORK array, and no error message related to LWORK is issued by XERBLA. IWORK (workspace/output) INTEGER array, dimension (LIWORK) On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. LIWORK (input) INTEGER The dimension of the array IWORK. If JOBZ = 'N' or N <= 1, LIWORK must be at least 1. If JOBZ = 'V' and N > 1, LIWORK must be at least 3 + 5*N. If LIWORK = -1, then a workspace query is assumed; the routine only calculates the optimal size of the IWORK array, returns this value as the first entry of the IWORK array, and no error message related to LIWORK is issued by XERBLA. INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value. > 0: if INFO = i, the algorithm failed to converge; i off-diagonal elements of an intermediate tridiagonal form did not converge to zero. ===================================================================== Test the input parameters. Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; /* System generated locals */ integer z_dim1, z_offset, i__1; doublereal d__1; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static integer inde; static doublereal anrm, rmin, rmax; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); static doublereal sigma; extern logical lsame_(char *, char *); static integer iinfo, lwmin; static logical wantz; extern doublereal dlamch_(char *); static integer iscale; extern /* Subroutine */ int dstedc_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *, integer *, integer *); static doublereal safmin; extern /* Subroutine */ int xerbla_(char *, integer *); static doublereal bignum; extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); static integer indtau; extern /* Subroutine */ int dsterf_(integer *, doublereal *, doublereal *, integer *); static integer indwrk, liwmin; extern /* Subroutine */ int dsptrd_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *), dopmtr_(char *, char *, char *, integer *, integer *, doublereal * , doublereal *, doublereal *, integer *, doublereal *, integer *); static integer llwork; static doublereal smlnum; static logical lquery; static doublereal eps; #define z___ref(a_1,a_2) z__[(a_2)*z_dim1 + a_1] --ap; --w; z_dim1 = *ldz; z_offset = 1 + z_dim1 * 1; z__ -= z_offset; --work; --iwork; /* Function Body */ wantz = lsame_(jobz, "V"); lquery = *lwork == -1 || *liwork == -1; *info = 0; if (*n <= 1) { liwmin = 1; lwmin = 1; } else { if (wantz) { liwmin = *n * 5 + 3; /* Computing 2nd power */ i__1 = *n; lwmin = *n * 6 + 1 + i__1 * i__1; } else { liwmin = 1; lwmin = *n << 1; } } if (! (wantz || lsame_(jobz, "N"))) { *info = -1; } else if (! (lsame_(uplo, "U") || lsame_(uplo, "L"))) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*ldz < 1 || wantz && *ldz < *n) { *info = -7; } else if (*lwork < lwmin && ! lquery) { *info = -9; } else if (*liwork < liwmin && ! lquery) { *info = -11; } if (*info == 0) { work[1] = (doublereal) lwmin; iwork[1] = liwmin; } if (*info != 0) { i__1 = -(*info); xerbla_("DSPEVD", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } if (*n == 1) { w[1] = ap[1]; if (wantz) { z___ref(1, 1) = 1.; } return 0; } /* Get machine constants. */ safmin = dlamch_("Safe minimum"); eps = dlamch_("Precision"); smlnum = safmin / eps; bignum = 1. / smlnum; rmin = sqrt(smlnum); rmax = sqrt(bignum); /* Scale matrix to allowable range, if necessary. */ anrm = dlansp_("M", uplo, n, &ap[1], &work[1]); iscale = 0; if (anrm > 0. && anrm < rmin) { iscale = 1; sigma = rmin / anrm; } else if (anrm > rmax) { iscale = 1; sigma = rmax / anrm; } if (iscale == 1) { i__1 = *n * (*n + 1) / 2; dscal_(&i__1, &sigma, &ap[1], &c__1); } /* Call DSPTRD to reduce symmetric packed matrix to tridiagonal form. */ inde = 1; indtau = inde + *n; dsptrd_(uplo, n, &ap[1], &w[1], &work[inde], &work[indtau], &iinfo); /* For eigenvalues only, call DSTERF. For eigenvectors, first call DSTEDC to generate the eigenvector matrix, WORK(INDWRK), of the tridiagonal matrix, then call DOPMTR to multiply it by the Householder transformations represented in AP. */ if (! wantz) { dsterf_(n, &w[1], &work[inde], info); } else { indwrk = indtau + *n; llwork = *lwork - indwrk + 1; dstedc_("I", n, &w[1], &work[inde], &z__[z_offset], ldz, &work[indwrk] , &llwork, &iwork[1], liwork, info); dopmtr_("L", uplo, "N", n, n, &ap[1], &work[indtau], &z__[z_offset], ldz, &work[indwrk], &iinfo); } /* If matrix was scaled, then rescale eigenvalues appropriately. */ if (iscale == 1) { d__1 = 1. / sigma; dscal_(n, &d__1, &w[1], &c__1); } work[1] = (doublereal) lwmin; iwork[1] = liwmin; return 0; /* End of DSPEVD */ } /* dspevd_ */
/* Subroutine */ int dspevx_(char *jobz, char *range, char *uplo, integer *n, doublereal *ap, doublereal *vl, doublereal *vu, integer *il, integer * iu, doublereal *abstol, integer *m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, integer *iwork, integer *ifail, integer *info) { /* System generated locals */ integer z_dim1, z_offset, i__1, i__2; doublereal d__1, d__2; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__, j, jj; doublereal eps, vll, vuu, tmp1; integer indd, inde; doublereal anrm; integer imax; doublereal rmin, rmax; logical test; integer itmp1, indee; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); doublereal sigma; extern logical lsame_(char *, char *); integer iinfo; char order[1]; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *), dswap_(integer *, doublereal *, integer *, doublereal *, integer *); logical wantz; extern doublereal dlamch_(char *); logical alleig, indeig; integer iscale, indibl; logical valeig; doublereal safmin; extern /* Subroutine */ int xerbla_(char *, integer *); doublereal abstll, bignum; extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); integer indtau, indisp; extern /* Subroutine */ int dstein_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *), dsterf_(integer *, doublereal *, doublereal *, integer *); integer indiwo; extern /* Subroutine */ int dstebz_(char *, char *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); integer indwrk; extern /* Subroutine */ int dopgtr_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *), dsptrd_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *), dsteqr_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *), dopmtr_(char *, char *, char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *); integer nsplit; doublereal smlnum; /* -- LAPACK driver routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPEVX computes selected eigenvalues and, optionally, eigenvectors */ /* of a real symmetric matrix A in packed storage. Eigenvalues/vectors */ /* can be selected by specifying either a range of values or a range of */ /* indices for the desired eigenvalues. */ /* Arguments */ /* ========= */ /* JOBZ (input) CHARACTER*1 */ /* = 'N': Compute eigenvalues only; */ /* = 'V': Compute eigenvalues and eigenvectors. */ /* RANGE (input) CHARACTER*1 */ /* = 'A': all eigenvalues will be found; */ /* = 'V': all eigenvalues in the half-open interval (VL,VU] */ /* will be found; */ /* = 'I': the IL-th through IU-th eigenvalues will be found. */ /* UPLO (input) CHARACTER*1 */ /* = 'U': Upper triangle of A is stored; */ /* = 'L': Lower triangle of A is stored. */ /* N (input) INTEGER */ /* The order of the matrix A. N >= 0. */ /* AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* On entry, the upper or lower triangle of the symmetric matrix */ /* A, packed columnwise in a linear array. The j-th column of A */ /* is stored in the array AP as follows: */ /* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; */ /* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n. */ /* On exit, AP is overwritten by values generated during the */ /* reduction to tridiagonal form. If UPLO = 'U', the diagonal */ /* and first superdiagonal of the tridiagonal matrix T overwrite */ /* the corresponding elements of A, and if UPLO = 'L', the */ /* diagonal and first subdiagonal of T overwrite the */ /* corresponding elements of A. */ /* VL (input) DOUBLE PRECISION */ /* VU (input) DOUBLE PRECISION */ /* If RANGE='V', the lower and upper bounds of the interval to */ /* be searched for eigenvalues. VL < VU. */ /* Not referenced if RANGE = 'A' or 'I'. */ /* IL (input) INTEGER */ /* IU (input) INTEGER */ /* If RANGE='I', the indices (in ascending order) of the */ /* smallest and largest eigenvalues to be returned. */ /* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. */ /* Not referenced if RANGE = 'A' or 'V'. */ /* ABSTOL (input) DOUBLE PRECISION */ /* The absolute error tolerance for the eigenvalues. */ /* An approximate eigenvalue is accepted as converged */ /* when it is determined to lie in an interval [a,b] */ /* of width less than or equal to */ /* ABSTOL + EPS * max( |a|,|b| ) , */ /* where EPS is the machine precision. If ABSTOL is less than */ /* or equal to zero, then EPS*|T| will be used in its place, */ /* where |T| is the 1-norm of the tridiagonal matrix obtained */ /* by reducing AP to tridiagonal form. */ /* Eigenvalues will be computed most accurately when ABSTOL is */ /* set to twice the underflow threshold 2*DLAMCH('S'), not zero. */ /* If this routine returns with INFO>0, indicating that some */ /* eigenvectors did not converge, try setting ABSTOL to */ /* 2*DLAMCH('S'). */ /* See "Computing Small Singular Values of Bidiagonal Matrices */ /* with Guaranteed High Relative Accuracy," by Demmel and */ /* Kahan, LAPACK Working Note #3. */ /* M (output) INTEGER */ /* The total number of eigenvalues found. 0 <= M <= N. */ /* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. */ /* W (output) DOUBLE PRECISION array, dimension (N) */ /* If INFO = 0, the selected eigenvalues in ascending order. */ /* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M)) */ /* If JOBZ = 'V', then if INFO = 0, the first M columns of Z */ /* contain the orthonormal eigenvectors of the matrix A */ /* corresponding to the selected eigenvalues, with the i-th */ /* column of Z holding the eigenvector associated with W(i). */ /* If an eigenvector fails to converge, then that column of Z */ /* contains the latest approximation to the eigenvector, and the */ /* index of the eigenvector is returned in IFAIL. */ /* If JOBZ = 'N', then Z is not referenced. */ /* Note: the user must ensure that at least max(1,M) columns are */ /* supplied in the array Z; if RANGE = 'V', the exact value of M */ /* is not known in advance and an upper bound must be used. */ /* LDZ (input) INTEGER */ /* The leading dimension of the array Z. LDZ >= 1, and if */ /* JOBZ = 'V', LDZ >= max(1,N). */ /* WORK (workspace) DOUBLE PRECISION array, dimension (8*N) */ /* IWORK (workspace) INTEGER array, dimension (5*N) */ /* IFAIL (output) INTEGER array, dimension (N) */ /* If JOBZ = 'V', then if INFO = 0, the first M elements of */ /* IFAIL are zero. If INFO > 0, then IFAIL contains the */ /* indices of the eigenvectors that failed to converge. */ /* If JOBZ = 'N', then IFAIL is not referenced. */ /* 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. */ /* Their indices are stored in array IFAIL. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --w; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --work; --iwork; --ifail; /* Function Body */ wantz = lsame_(jobz, "V"); alleig = lsame_(range, "A"); valeig = lsame_(range, "V"); indeig = lsame_(range, "I"); *info = 0; if (! (wantz || lsame_(jobz, "N"))) { *info = -1; } else if (! (alleig || valeig || indeig)) { *info = -2; } else if (! (lsame_(uplo, "L") || lsame_(uplo, "U"))) { *info = -3; } else if (*n < 0) { *info = -4; } else { if (valeig) { if (*n > 0 && *vu <= *vl) { *info = -7; } } else if (indeig) { if (*il < 1 || *il > max(1,*n)) { *info = -8; } else if (*iu < min(*n,*il) || *iu > *n) { *info = -9; } } } if (*info == 0) { if (*ldz < 1 || wantz && *ldz < *n) { *info = -14; } } if (*info != 0) { i__1 = -(*info); xerbla_("DSPEVX", &i__1); return 0; } /* Quick return if possible */ *m = 0; if (*n == 0) { return 0; } if (*n == 1) { if (alleig || indeig) { *m = 1; w[1] = ap[1]; } else { if (*vl < ap[1] && *vu >= ap[1]) { *m = 1; w[1] = ap[1]; } } if (wantz) { z__[z_dim1 + 1] = 1.; } return 0; } /* Get machine constants. */ safmin = dlamch_("Safe minimum"); eps = dlamch_("Precision"); smlnum = safmin / eps; bignum = 1. / smlnum; rmin = sqrt(smlnum); /* Computing MIN */ d__1 = sqrt(bignum), d__2 = 1. / sqrt(sqrt(safmin)); rmax = min(d__1,d__2); /* Scale matrix to allowable range, if necessary. */ iscale = 0; abstll = *abstol; if (valeig) { vll = *vl; vuu = *vu; } else { vll = 0.; vuu = 0.; } anrm = dlansp_("M", uplo, n, &ap[1], &work[1]); if (anrm > 0. && anrm < rmin) { iscale = 1; sigma = rmin / anrm; } else if (anrm > rmax) { iscale = 1; sigma = rmax / anrm; } if (iscale == 1) { i__1 = *n * (*n + 1) / 2; dscal_(&i__1, &sigma, &ap[1], &c__1); if (*abstol > 0.) { abstll = *abstol * sigma; } if (valeig) { vll = *vl * sigma; vuu = *vu * sigma; } } /* Call DSPTRD to reduce symmetric packed matrix to tridiagonal form. */ indtau = 1; inde = indtau + *n; indd = inde + *n; indwrk = indd + *n; dsptrd_(uplo, n, &ap[1], &work[indd], &work[inde], &work[indtau], &iinfo); /* If all eigenvalues are desired and ABSTOL is less than or equal */ /* to zero, then call DSTERF or DOPGTR and SSTEQR. If this fails */ /* for some eigenvalue, then try DSTEBZ. */ test = FALSE_; if (indeig) { if (*il == 1 && *iu == *n) { test = TRUE_; } } if ((alleig || test) && *abstol <= 0.) { dcopy_(n, &work[indd], &c__1, &w[1], &c__1); indee = indwrk + (*n << 1); if (! wantz) { i__1 = *n - 1; dcopy_(&i__1, &work[inde], &c__1, &work[indee], &c__1); dsterf_(n, &w[1], &work[indee], info); } else { dopgtr_(uplo, n, &ap[1], &work[indtau], &z__[z_offset], ldz, & work[indwrk], &iinfo); i__1 = *n - 1; dcopy_(&i__1, &work[inde], &c__1, &work[indee], &c__1); dsteqr_(jobz, n, &w[1], &work[indee], &z__[z_offset], ldz, &work[ indwrk], info); if (*info == 0) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { ifail[i__] = 0; /* L10: */ } } } if (*info == 0) { *m = *n; goto L20; } *info = 0; } /* Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN. */ if (wantz) { *(unsigned char *)order = 'B'; } else { *(unsigned char *)order = 'E'; } indibl = 1; indisp = indibl + *n; indiwo = indisp + *n; dstebz_(range, order, n, &vll, &vuu, il, iu, &abstll, &work[indd], &work[ inde], m, &nsplit, &w[1], &iwork[indibl], &iwork[indisp], &work[ indwrk], &iwork[indiwo], info); if (wantz) { dstein_(n, &work[indd], &work[inde], m, &w[1], &iwork[indibl], &iwork[ indisp], &z__[z_offset], ldz, &work[indwrk], &iwork[indiwo], & ifail[1], info); /* Apply orthogonal matrix used in reduction to tridiagonal */ /* form to eigenvectors returned by DSTEIN. */ dopmtr_("L", uplo, "N", n, m, &ap[1], &work[indtau], &z__[z_offset], ldz, &work[indwrk], &iinfo); } /* If matrix was scaled, then rescale eigenvalues appropriately. */ L20: if (iscale == 1) { if (*info == 0) { imax = *m; } else { imax = *info - 1; } d__1 = 1. / sigma; dscal_(&imax, &d__1, &w[1], &c__1); } /* If eigenvalues are not in order, then sort them, along with */ /* eigenvectors. */ if (wantz) { i__1 = *m - 1; for (j = 1; j <= i__1; ++j) { i__ = 0; tmp1 = w[j]; i__2 = *m; for (jj = j + 1; jj <= i__2; ++jj) { if (w[jj] < tmp1) { i__ = jj; tmp1 = w[jj]; } /* L30: */ } if (i__ != 0) { itmp1 = iwork[indibl + i__ - 1]; w[i__] = w[j]; iwork[indibl + i__ - 1] = iwork[indibl + j - 1]; w[j] = tmp1; iwork[indibl + j - 1] = itmp1; dswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * z_dim1 + 1], &c__1); if (*info != 0) { itmp1 = ifail[i__]; ifail[i__] = ifail[j]; ifail[j] = itmp1; } } /* L40: */ } } return 0; /* End of DSPEVX */ } /* dspevx_ */
/* Subroutine */ int dppt01_(char *uplo, integer *n, doublereal *a, doublereal *afac, doublereal *rwork, doublereal *resid) { /* System generated locals */ integer i__1; /* Local variables */ integer i__, k; doublereal t; integer kc; doublereal eps; integer npp; doublereal anorm; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DPPT01 reconstructs a symmetric positive definite packed matrix A */ /* from its L*L' or U'*U factorization and computes the residual */ /* norm( L*L' - A ) / ( N * norm(A) * EPS ) or */ /* norm( U'*U - A ) / ( N * norm(A) * EPS ), */ /* where EPS is the machine epsilon. */ /* Arguments */ /* ========== */ /* UPLO (input) CHARACTER*1 */ /* Specifies whether the upper or lower triangular part of the */ /* symmetric matrix A is stored: */ /* = 'U': Upper triangular */ /* = 'L': Lower triangular */ /* N (input) INTEGER */ /* The number of rows and columns of the matrix A. N >= 0. */ /* A (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* The original symmetric matrix A, stored as a packed */ /* triangular matrix. */ /* AFAC (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* On entry, the factor L or U from the L*L' or U'*U */ /* factorization of A, stored as a packed triangular matrix. */ /* Overwritten with the reconstructed matrix, and then with the */ /* difference L*L' - A (or U'*U - A). */ /* RWORK (workspace) DOUBLE PRECISION array, dimension (N) */ /* RESID (output) DOUBLE PRECISION */ /* If UPLO = 'L', norm(L*L' - A) / ( N * norm(A) * EPS ) */ /* If UPLO = 'U', norm(U'*U - A) / ( N * norm(A) * EPS ) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Quick exit if N = 0 */ /* Parameter adjustments */ --rwork; --afac; --a; /* Function Body */ if (*n <= 0) { *resid = 0.; return 0; } /* Exit with RESID = 1/EPS if ANORM = 0. */ eps = dlamch_("Epsilon"); anorm = dlansp_("1", uplo, n, &a[1], &rwork[1]); if (anorm <= 0.) { *resid = 1. / eps; return 0; } /* Compute the product U'*U, overwriting U. */ if (lsame_(uplo, "U")) { kc = *n * (*n - 1) / 2 + 1; for (k = *n; k >= 1; --k) { /* Compute the (K,K) element of the result. */ t = ddot_(&k, &afac[kc], &c__1, &afac[kc], &c__1); afac[kc + k - 1] = t; /* Compute the rest of column K. */ if (k > 1) { i__1 = k - 1; dtpmv_("Upper", "Transpose", "Non-unit", &i__1, &afac[1], & afac[kc], &c__1); kc -= k - 1; } /* L10: */ } /* Compute the product L*L', overwriting L. */ } else { kc = *n * (*n + 1) / 2; for (k = *n; k >= 1; --k) { /* Add a multiple of column K of the factor L to each of */ /* columns K+1 through N. */ if (k < *n) { i__1 = *n - k; dspr_("Lower", &i__1, &c_b14, &afac[kc + 1], &c__1, &afac[kc + *n - k + 1]); } /* Scale column K by the diagonal element. */ t = afac[kc]; i__1 = *n - k + 1; dscal_(&i__1, &t, &afac[kc], &c__1); kc -= *n - k + 2; /* L20: */ } } /* Compute the difference L*L' - A (or U'*U - A). */ npp = *n * (*n + 1) / 2; i__1 = npp; for (i__ = 1; i__ <= i__1; ++i__) { afac[i__] -= a[i__]; /* L30: */ } /* Compute norm( L*U - A ) / ( N * norm(A) * EPS ) */ *resid = dlansp_("1", uplo, n, &afac[1], &rwork[1]); *resid = *resid / (doublereal) (*n) / anorm / eps; return 0; /* End of DPPT01 */ } /* dppt01_ */
/* Subroutine */ int ddrvsp_(logical *dotype, integer *nn, integer *nval, integer *nrhs, doublereal *thresh, logical *tsterr, integer *nmax, doublereal *a, doublereal *afac, doublereal *ainv, doublereal *b, doublereal *x, doublereal *xact, doublereal *work, doublereal *rwork, integer *iwork, integer *nout) { /* Initialized data */ static integer iseedy[4] = { 1988,1989,1990,1991 }; static char facts[1*2] = "F" "N"; /* Format strings */ static char fmt_9999[] = "(1x,a6,\002, UPLO='\002,a1,\002', N =\002,i5" ",\002, type \002,i2,\002, test \002,i2,\002, ratio =\002,g12.5)"; static char fmt_9998[] = "(1x,a6,\002, FACT='\002,a1,\002', UPLO='\002,a" "1,\002', N =\002,i5,\002, type \002,i2,\002, test \002,i2,\002, " "ratio =\002,g12.5)"; /* System generated locals */ address a__1[2]; integer i__1, i__2, i__3, i__4, i__5[2]; char ch__1[2]; /* Builtin functions */ /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Subroutine */ int s_cat(char *, char **, integer *, integer *, ftnlen); /* Local variables */ integer i__, j, k, n, i1, i2, k1, in, kl, ku, nt, lda, npp; char fact[1]; integer ioff, mode, imat, info; char path[3], dist[1], uplo[1], type__[1]; integer nrun, ifact; extern /* Subroutine */ int dget04_(integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); integer nfail, iseed[4]; extern doublereal dget06_(doublereal *, doublereal *); doublereal rcond; integer nimat; extern /* Subroutine */ int dppt02_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *), dspt01_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); doublereal anorm; extern /* Subroutine */ int dppt05_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *), dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); integer iuplo, izero, nerrs, lwork; extern /* Subroutine */ int dspsv_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, integer *); logical zerot; char xtype[1]; extern /* Subroutine */ int dlatb4_(char *, integer *, integer *, integer *, char *, integer *, integer *, doublereal *, integer *, doublereal *, char *), aladhd_(integer *, char *), alaerh_(char *, char *, integer *, integer *, char *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *); doublereal rcondc; char packit[1]; extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlarhs_(char *, char *, char *, char *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); extern /* Subroutine */ int alasvm_(char *, integer *, integer *, integer *, integer *); doublereal cndnum; extern /* Subroutine */ int dlatms_(integer *, integer *, char *, integer *, char *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, char *, doublereal *, integer *, doublereal *, integer *); doublereal ainvnm; extern /* Subroutine */ int dsptrf_(char *, integer *, doublereal *, integer *, integer *), dsptri_(char *, integer *, doublereal *, integer *, doublereal *, integer *), derrvx_(char *, integer *); doublereal result[6]; extern /* Subroutine */ int dspsvx_(char *, char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, integer *); /* Fortran I/O blocks */ static cilist io___41 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___44 = { 0, 0, 0, fmt_9998, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DDRVSP tests the driver routines DSPSV and -SVX. */ /* Arguments */ /* ========= */ /* DOTYPE (input) LOGICAL array, dimension (NTYPES) */ /* The matrix types to be used for testing. Matrices of type j */ /* (for 1 <= j <= NTYPES) are used for testing if DOTYPE(j) = */ /* .TRUE.; if DOTYPE(j) = .FALSE., then type j is not used. */ /* NN (input) INTEGER */ /* The number of values of N contained in the vector NVAL. */ /* NVAL (input) INTEGER array, dimension (NN) */ /* The values of the matrix dimension N. */ /* NRHS (input) INTEGER */ /* The number of right hand side vectors to be generated for */ /* each linear system. */ /* THRESH (input) DOUBLE PRECISION */ /* The threshold value for the test ratios. A result is */ /* included in the output file if RESULT >= THRESH. To have */ /* every test ratio printed, use THRESH = 0. */ /* TSTERR (input) LOGICAL */ /* Flag that indicates whether error exits are to be tested. */ /* NMAX (input) INTEGER */ /* The maximum value permitted for N, used in dimensioning the */ /* work arrays. */ /* A (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AFAC (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AINV (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* B (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* X (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* XACT (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* WORK (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*max(2,NRHS)) */ /* RWORK (workspace) DOUBLE PRECISION array, dimension (NMAX+2*NRHS) */ /* IWORK (workspace) INTEGER array, dimension (2*NMAX) */ /* NOUT (input) INTEGER */ /* The unit number for output. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Data statements .. */ /* Parameter adjustments */ --iwork; --rwork; --work; --xact; --x; --b; --ainv; --afac; --a; --nval; --dotype; /* Function Body */ /* .. */ /* .. Executable Statements .. */ /* Initialize constants and the random number seed. */ s_copy(path, "Double precision", (ftnlen)1, (ftnlen)16); s_copy(path + 1, "SP", (ftnlen)2, (ftnlen)2); nrun = 0; nfail = 0; nerrs = 0; for (i__ = 1; i__ <= 4; ++i__) { iseed[i__ - 1] = iseedy[i__ - 1]; /* L10: */ } /* Computing MAX */ i__1 = *nmax << 1, i__2 = *nmax * *nrhs; lwork = max(i__1,i__2); /* Test the error exits */ if (*tsterr) { derrvx_(path, nout); } infoc_1.infot = 0; /* Do for each value of N in NVAL */ i__1 = *nn; for (in = 1; in <= i__1; ++in) { n = nval[in]; lda = max(n,1); npp = n * (n + 1) / 2; *(unsigned char *)xtype = 'N'; nimat = 10; if (n <= 0) { nimat = 1; } i__2 = nimat; for (imat = 1; imat <= i__2; ++imat) { /* Do the tests only if DOTYPE( IMAT ) is true. */ if (! dotype[imat]) { goto L170; } /* Skip types 3, 4, 5, or 6 if the matrix size is too small. */ zerot = imat >= 3 && imat <= 6; if (zerot && n < imat - 2) { goto L170; } /* Do first for UPLO = 'U', then for UPLO = 'L' */ for (iuplo = 1; iuplo <= 2; ++iuplo) { if (iuplo == 1) { *(unsigned char *)uplo = 'U'; *(unsigned char *)packit = 'C'; } else { *(unsigned char *)uplo = 'L'; *(unsigned char *)packit = 'R'; } /* Set up parameters with DLATB4 and generate a test matrix */ /* with DLATMS. */ dlatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode, &cndnum, dist); s_copy(srnamc_1.srnamt, "DLATMS", (ftnlen)6, (ftnlen)6); dlatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, & cndnum, &anorm, &kl, &ku, packit, &a[1], &lda, &work[ 1], &info); /* Check error code from DLATMS. */ if (info != 0) { alaerh_(path, "DLATMS", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); goto L160; } /* For types 3-6, zero one or more rows and columns of the */ /* matrix to test that INFO is returned correctly. */ if (zerot) { if (imat == 3) { izero = 1; } else if (imat == 4) { izero = n; } else { izero = n / 2 + 1; } if (imat < 6) { /* Set row and column IZERO to zero. */ if (iuplo == 1) { ioff = (izero - 1) * izero / 2; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L20: */ } ioff += izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff += i__; /* L30: */ } } else { ioff = izero; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff = ioff + n - i__; /* L40: */ } ioff -= izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L50: */ } } } else { ioff = 0; if (iuplo == 1) { /* Set the first IZERO rows and columns to zero. */ i__3 = n; for (j = 1; j <= i__3; ++j) { i2 = min(j,izero); i__4 = i2; for (i__ = 1; i__ <= i__4; ++i__) { a[ioff + i__] = 0.; /* L60: */ } ioff += j; /* L70: */ } } else { /* Set the last IZERO rows and columns to zero. */ i__3 = n; for (j = 1; j <= i__3; ++j) { i1 = max(j,izero); i__4 = n; for (i__ = i1; i__ <= i__4; ++i__) { a[ioff + i__] = 0.; /* L80: */ } ioff = ioff + n - j; /* L90: */ } } } } else { izero = 0; } for (ifact = 1; ifact <= 2; ++ifact) { /* Do first for FACT = 'F', then for other values. */ *(unsigned char *)fact = *(unsigned char *)&facts[ifact - 1]; /* Compute the condition number for comparison with */ /* the value returned by DSPSVX. */ if (zerot) { if (ifact == 1) { goto L150; } rcondc = 0.; } else if (ifact == 1) { /* Compute the 1-norm of A. */ anorm = dlansp_("1", uplo, &n, &a[1], &rwork[1]); /* Factor the matrix A. */ dcopy_(&npp, &a[1], &c__1, &afac[1], &c__1); dsptrf_(uplo, &n, &afac[1], &iwork[1], &info); /* Compute inv(A) and take its norm. */ dcopy_(&npp, &afac[1], &c__1, &ainv[1], &c__1); dsptri_(uplo, &n, &ainv[1], &iwork[1], &work[1], & info); ainvnm = dlansp_("1", uplo, &n, &ainv[1], &rwork[1]); /* Compute the 1-norm condition number of A. */ if (anorm <= 0. || ainvnm <= 0.) { rcondc = 1.; } else { rcondc = 1. / anorm / ainvnm; } } /* Form an exact solution and set the right hand side. */ s_copy(srnamc_1.srnamt, "DLARHS", (ftnlen)6, (ftnlen)6); dlarhs_(path, xtype, uplo, " ", &n, &n, &kl, &ku, nrhs, & a[1], &lda, &xact[1], &lda, &b[1], &lda, iseed, & info); *(unsigned char *)xtype = 'C'; /* --- Test DSPSV --- */ if (ifact == 2) { dcopy_(&npp, &a[1], &c__1, &afac[1], &c__1); dlacpy_("Full", &n, nrhs, &b[1], &lda, &x[1], &lda); /* Factor the matrix and solve the system using DSPSV. */ s_copy(srnamc_1.srnamt, "DSPSV ", (ftnlen)6, (ftnlen) 6); dspsv_(uplo, &n, nrhs, &afac[1], &iwork[1], &x[1], & lda, &info); /* Adjust the expected value of INFO to account for */ /* pivoting. */ k = izero; if (k > 0) { L100: if (iwork[k] < 0) { if (iwork[k] != -k) { k = -iwork[k]; goto L100; } } else if (iwork[k] != k) { k = iwork[k]; goto L100; } } /* Check error code from DSPSV . */ if (info != k) { alaerh_(path, "DSPSV ", &info, &k, uplo, &n, &n, & c_n1, &c_n1, nrhs, &imat, &nfail, &nerrs, nout); goto L120; } else if (info != 0) { goto L120; } /* Reconstruct matrix from factors and compute */ /* residual. */ dspt01_(uplo, &n, &a[1], &afac[1], &iwork[1], &ainv[1] , &lda, &rwork[1], result); /* Compute residual of the computed solution. */ dlacpy_("Full", &n, nrhs, &b[1], &lda, &work[1], &lda); dppt02_(uplo, &n, nrhs, &a[1], &x[1], &lda, &work[1], &lda, &rwork[1], &result[1]); /* Check solution from generated exact solution. */ dget04_(&n, nrhs, &x[1], &lda, &xact[1], &lda, & rcondc, &result[2]); nt = 3; /* Print information about the tests that did not pass */ /* the threshold. */ i__3 = nt; for (k = 1; k <= i__3; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { aladhd_(nout, path); } io___41.ciunit = *nout; s_wsfe(&io___41); do_fio(&c__1, "DSPSV ", (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&imat, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&result[k - 1], (ftnlen) sizeof(doublereal)); e_wsfe(); ++nfail; } /* L110: */ } nrun += nt; L120: ; } /* --- Test DSPSVX --- */ if (ifact == 2 && npp > 0) { dlaset_("Full", &npp, &c__1, &c_b59, &c_b59, &afac[1], &npp); } dlaset_("Full", &n, nrhs, &c_b59, &c_b59, &x[1], &lda); /* Solve the system and compute the condition number and */ /* error bounds using DSPSVX. */ s_copy(srnamc_1.srnamt, "DSPSVX", (ftnlen)6, (ftnlen)6); dspsvx_(fact, uplo, &n, nrhs, &a[1], &afac[1], &iwork[1], &b[1], &lda, &x[1], &lda, &rcond, &rwork[1], & rwork[*nrhs + 1], &work[1], &iwork[n + 1], &info); /* Adjust the expected value of INFO to account for */ /* pivoting. */ k = izero; if (k > 0) { L130: if (iwork[k] < 0) { if (iwork[k] != -k) { k = -iwork[k]; goto L130; } } else if (iwork[k] != k) { k = iwork[k]; goto L130; } } /* Check the error code from DSPSVX. */ if (info != k) { /* Writing concatenation */ i__5[0] = 1, a__1[0] = fact; i__5[1] = 1, a__1[1] = uplo; s_cat(ch__1, a__1, i__5, &c__2, (ftnlen)2); alaerh_(path, "DSPSVX", &info, &k, ch__1, &n, &n, & c_n1, &c_n1, nrhs, &imat, &nfail, &nerrs, nout); goto L150; } if (info == 0) { if (ifact >= 2) { /* Reconstruct matrix from factors and compute */ /* residual. */ dspt01_(uplo, &n, &a[1], &afac[1], &iwork[1], & ainv[1], &lda, &rwork[(*nrhs << 1) + 1], result); k1 = 1; } else { k1 = 2; } /* Compute residual of the computed solution. */ dlacpy_("Full", &n, nrhs, &b[1], &lda, &work[1], &lda); dppt02_(uplo, &n, nrhs, &a[1], &x[1], &lda, &work[1], &lda, &rwork[(*nrhs << 1) + 1], &result[1]); /* Check solution from generated exact solution. */ dget04_(&n, nrhs, &x[1], &lda, &xact[1], &lda, & rcondc, &result[2]); /* Check the error bounds from iterative refinement. */ dppt05_(uplo, &n, nrhs, &a[1], &b[1], &lda, &x[1], & lda, &xact[1], &lda, &rwork[1], &rwork[*nrhs + 1], &result[3]); } else { k1 = 6; } /* Compare RCOND from DSPSVX with the computed value */ /* in RCONDC. */ result[5] = dget06_(&rcond, &rcondc); /* Print information about the tests that did not pass */ /* the threshold. */ for (k = k1; k <= 6; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { aladhd_(nout, path); } io___44.ciunit = *nout; s_wsfe(&io___44); do_fio(&c__1, "DSPSVX", (ftnlen)6); do_fio(&c__1, fact, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&imat, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&result[k - 1], (ftnlen) sizeof(doublereal)); e_wsfe(); ++nfail; } /* L140: */ } nrun = nrun + 7 - k1; L150: ; } L160: ; } L170: ; } /* L180: */ } /* Print a summary of the results. */ alasvm_(path, nout, &nfail, &nrun, &nerrs); return 0; /* End of DDRVSP */ } /* ddrvsp_ */
/* Subroutine */ int dppsvx_(char *fact, char *uplo, integer *n, integer * nrhs, doublereal *ap, doublereal *afp, char *equed, doublereal *s, doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal * rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer * iwork, integer *info) { /* -- LAPACK driver 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 ======= DPPSVX uses the Cholesky factorization A = U**T*U or A = L*L**T to compute the solution to a real system of linear equations A * X = B, where A is an N-by-N symmetric positive definite matrix stored in packed format and X and B are N-by-NRHS matrices. Error bounds on the solution and a condition estimate are also provided. Description =========== The following steps are performed: 1. If FACT = 'E', real scaling factors are computed to equilibrate the system: diag(S) * A * diag(S) * inv(diag(S)) * X = diag(S) * B Whether or not the system will be equilibrated depends on the scaling of the matrix A, but if equilibration is used, A is overwritten by diag(S)*A*diag(S) and B by diag(S)*B. 2. If FACT = 'N' or 'E', the Cholesky decomposition is used to factor the matrix A (after equilibration if FACT = 'E') as A = U**T* U, if UPLO = 'U', or A = L * L**T, if UPLO = 'L', where U is an upper triangular matrix and L is a lower triangular matrix. 3. If the leading i-by-i principal minor is not positive definite, then the routine returns with INFO = i. Otherwise, the factored form of A is used to estimate the condition number of the matrix A. If the reciprocal of the condition number is less than machine precision, INFO = N+1 is returned as a warning, but the routine still goes on to solve for X and compute error bounds as described below. 4. The system of equations is solved for X using the factored form of A. 5. Iterative refinement is applied to improve the computed solution matrix and calculate error bounds and backward error estimates for it. 6. If equilibration was used, the matrix X is premultiplied by diag(S) so that it solves the original system before equilibration. Arguments ========= FACT (input) CHARACTER*1 Specifies whether or not the factored form of the matrix A is supplied on entry, and if not, whether the matrix A should be equilibrated before it is factored. = 'F': On entry, AFP contains the factored form of A. If EQUED = 'Y', the matrix A has been equilibrated with scaling factors given by S. AP and AFP will not be modified. = 'N': The matrix A will be copied to AFP and factored. = 'E': The matrix A will be equilibrated if necessary, then copied to AFP and factored. UPLO (input) CHARACTER*1 = 'U': Upper triangle of A is stored; = 'L': Lower triangle of A is stored. N (input) INTEGER The number of linear equations, i.e., the order of the matrix A. N >= 0. NRHS (input) INTEGER The number of right hand sides, i.e., the number of columns of the matrices B and X. NRHS >= 0. AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) On entry, the upper or lower triangle of the symmetric matrix A, packed columnwise in a linear array, except if FACT = 'F' and EQUED = 'Y', then A must contain the equilibrated matrix diag(S)*A*diag(S). The j-th column of A is stored in the array AP as follows: if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n. See below for further details. A is not modified if FACT = 'F' or 'N', or if FACT = 'E' and EQUED = 'N' on exit. On exit, if FACT = 'E' and EQUED = 'Y', A is overwritten by diag(S)*A*diag(S). AFP (input or output) DOUBLE PRECISION array, dimension (N*(N+1)/2) If FACT = 'F', then AFP is an input argument and on entry contains the triangular factor U or L from the Cholesky factorization A = U'*U or A = L*L', in the same storage format as A. If EQUED .ne. 'N', then AFP is the factored form of the equilibrated matrix A. If FACT = 'N', then AFP is an output argument and on exit returns the triangular factor U or L from the Cholesky factorization A = U'*U or A = L*L' of the original matrix A. If FACT = 'E', then AFP is an output argument and on exit returns the triangular factor U or L from the Cholesky factorization A = U'*U or A = L*L' of the equilibrated matrix A (see the description of AP for the form of the equilibrated matrix). EQUED (input or output) CHARACTER*1 Specifies the form of equilibration that was done. = 'N': No equilibration (always true if FACT = 'N'). = 'Y': Equilibration was done, i.e., A has been replaced by diag(S) * A * diag(S). EQUED is an input argument if FACT = 'F'; otherwise, it is an output argument. S (input or output) DOUBLE PRECISION array, dimension (N) The scale factors for A; not accessed if EQUED = 'N'. S is an input argument if FACT = 'F'; otherwise, S is an output argument. If FACT = 'F' and EQUED = 'Y', each element of S must be positive. B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) On entry, the N-by-NRHS right hand side matrix B. On exit, if EQUED = 'N', B is not modified; if EQUED = 'Y', B is overwritten by diag(S) * B. LDB (input) INTEGER The leading dimension of the array B. LDB >= max(1,N). X (output) DOUBLE PRECISION array, dimension (LDX,NRHS) If INFO = 0 or INFO = N+1, the N-by-NRHS solution matrix X to the original system of equations. Note that if EQUED = 'Y', A and B are modified on exit, and the solution to the equilibrated system is inv(diag(S))*X. LDX (input) INTEGER The leading dimension of the array X. LDX >= max(1,N). RCOND (output) DOUBLE PRECISION The estimate of the reciprocal condition number of the matrix A after equilibration (if done). If RCOND is less than the machine precision (in particular, if RCOND = 0), the matrix is singular to working precision. This condition is indicated by a return code of INFO > 0. FERR (output) DOUBLE PRECISION array, dimension (NRHS) The estimated forward error bound for each solution vector X(j) (the j-th column of the solution matrix X). If XTRUE is the true solution corresponding to X(j), FERR(j) is an estimated upper bound for the magnitude of the largest element in (X(j) - XTRUE) divided by the magnitude of the largest element in X(j). The estimate is as reliable as the estimate for RCOND, and is almost always a slight overestimate of the true error. BERR (output) DOUBLE PRECISION array, dimension (NRHS) The componentwise relative backward error of each solution vector X(j) (i.e., the smallest relative change in any element of A or B that makes X(j) an exact solution). WORK (workspace) DOUBLE PRECISION array, dimension (3*N) IWORK (workspace) INTEGER array, dimension (N) INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value > 0: if INFO = i, and i is <= N: the leading minor of order i of A is not positive definite, so the factorization could not be completed, and the solution has not been computed. RCOND = 0 is returned. = N+1: U is nonsingular, but RCOND is less than machine precision, meaning that the matrix is singular to working precision. Nevertheless, the solution and error bounds are computed because there are a number of situations where the computed solution can be more accurate than the value of RCOND would suggest. Further Details =============== The packed storage scheme is illustrated by the following example when N = 4, UPLO = 'U': Two-dimensional storage of the symmetric matrix A: a11 a12 a13 a14 a22 a23 a24 a33 a34 (aij = conjg(aji)) a44 Packed storage of the upper triangle of A: AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ] ===================================================================== Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; /* System generated locals */ integer b_dim1, b_offset, x_dim1, x_offset, i__1, i__2; doublereal d__1, d__2; /* Local variables */ static doublereal amax, smin, smax; static integer i__, j; extern logical lsame_(char *, char *); static doublereal scond, anorm; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); static logical equil, rcequ; extern doublereal dlamch_(char *); static logical nofact; extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), xerbla_(char *, integer *); static doublereal bignum; extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); extern /* Subroutine */ int dppcon_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, integer *), dlaqsp_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, char *); static integer infequ; extern /* Subroutine */ int dppequ_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *), dpprfs_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *), dpptrf_(char *, integer *, doublereal *, integer *); static doublereal smlnum; extern /* Subroutine */ int dpptrs_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *); #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1] #define x_ref(a_1,a_2) x[(a_2)*x_dim1 + a_1] --ap; --afp; --s; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; x_dim1 = *ldx; x_offset = 1 + x_dim1 * 1; x -= x_offset; --ferr; --berr; --work; --iwork; /* Function Body */ *info = 0; nofact = lsame_(fact, "N"); equil = lsame_(fact, "E"); if (nofact || equil) { *(unsigned char *)equed = 'N'; rcequ = FALSE_; } else { rcequ = lsame_(equed, "Y"); smlnum = dlamch_("Safe minimum"); bignum = 1. / smlnum; } /* Test the input parameters. */ if (! nofact && ! equil && ! lsame_(fact, "F")) { *info = -1; } else if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*nrhs < 0) { *info = -4; } else if (lsame_(fact, "F") && ! (rcequ || lsame_( equed, "N"))) { *info = -7; } else { if (rcequ) { smin = bignum; smax = 0.; i__1 = *n; for (j = 1; j <= i__1; ++j) { /* Computing MIN */ d__1 = smin, d__2 = s[j]; smin = min(d__1,d__2); /* Computing MAX */ d__1 = smax, d__2 = s[j]; smax = max(d__1,d__2); /* L10: */ } if (smin <= 0.) { *info = -8; } else if (*n > 0) { scond = max(smin,smlnum) / min(smax,bignum); } else { scond = 1.; } } if (*info == 0) { if (*ldb < max(1,*n)) { *info = -10; } else if (*ldx < max(1,*n)) { *info = -12; } } } if (*info != 0) { i__1 = -(*info); xerbla_("DPPSVX", &i__1); return 0; } if (equil) { /* Compute row and column scalings to equilibrate the matrix A. */ dppequ_(uplo, n, &ap[1], &s[1], &scond, &amax, &infequ); if (infequ == 0) { /* Equilibrate the matrix. */ dlaqsp_(uplo, n, &ap[1], &s[1], &scond, &amax, equed); rcequ = lsame_(equed, "Y"); } } /* Scale the right-hand side. */ if (rcequ) { i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { b_ref(i__, j) = s[i__] * b_ref(i__, j); /* L20: */ } /* L30: */ } } if (nofact || equil) { /* Compute the Cholesky factorization A = U'*U or A = L*L'. */ i__1 = *n * (*n + 1) / 2; dcopy_(&i__1, &ap[1], &c__1, &afp[1], &c__1); dpptrf_(uplo, n, &afp[1], info); /* Return if INFO is non-zero. */ if (*info != 0) { if (*info > 0) { *rcond = 0.; } return 0; } } /* Compute the norm of the matrix A. */ anorm = dlansp_("I", uplo, n, &ap[1], &work[1]); /* Compute the reciprocal of the condition number of A. */ dppcon_(uplo, n, &afp[1], &anorm, rcond, &work[1], &iwork[1], info); /* Set INFO = N+1 if the matrix is singular to working precision. */ if (*rcond < dlamch_("Epsilon")) { *info = *n + 1; } /* Compute the solution matrix X. */ dlacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx); dpptrs_(uplo, n, nrhs, &afp[1], &x[x_offset], ldx, info); /* Use iterative refinement to improve the computed solution and compute error bounds and backward error estimates for it. */ dpprfs_(uplo, n, nrhs, &ap[1], &afp[1], &b[b_offset], ldb, &x[x_offset], ldx, &ferr[1], &berr[1], &work[1], &iwork[1], info); /* Transform the solution matrix X to a solution of the original system. */ if (rcequ) { i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { x_ref(i__, j) = s[i__] * x_ref(i__, j); /* L40: */ } /* L50: */ } i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { ferr[j] /= scond; /* L60: */ } } return 0; /* End of DPPSVX */ } /* dppsvx_ */
/* Subroutine */ int dsbt21_(char *uplo, integer *n, integer *ka, integer *ks, doublereal *a, integer *lda, doublereal *d__, doublereal *e, doublereal *u, integer *ldu, doublereal *work, doublereal *result) { /* System generated locals */ integer a_dim1, a_offset, u_dim1, u_offset, i__1, i__2, i__3, i__4; doublereal d__1, d__2; /* Local variables */ integer j, jc, jr, lw, ika; doublereal ulp, unfl; extern /* Subroutine */ int dspr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *), dspr2_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *), dgemm_(char *, char *, integer * , integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); extern logical lsame_(char *, char *); doublereal anorm; char cuplo[1]; logical lower; doublereal wnorm; extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *), dlansb_(char *, char *, integer *, integer *, doublereal *, integer *, doublereal *), dlansp_(char *, char *, integer *, doublereal *, doublereal *); /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSBT21 generally checks a decomposition of the form */ /* A = U S U' */ /* where ' means transpose, A is symmetric banded, U is */ /* orthogonal, and S is diagonal (if KS=0) or symmetric */ /* tridiagonal (if KS=1). */ /* Specifically: */ /* RESULT(1) = | A - U S U' | / ( |A| n ulp ) *and* */ /* RESULT(2) = | I - UU' | / ( n ulp ) */ /* Arguments */ /* ========= */ /* UPLO (input) CHARACTER */ /* If UPLO='U', the upper triangle of A and V will be used and */ /* the (strictly) lower triangle will not be referenced. */ /* If UPLO='L', the lower triangle of A and V will be used and */ /* the (strictly) upper triangle will not be referenced. */ /* N (input) INTEGER */ /* The size of the matrix. If it is zero, DSBT21 does nothing. */ /* It must be at least zero. */ /* KA (input) INTEGER */ /* The bandwidth of the matrix A. It must be at least zero. If */ /* it is larger than N-1, then max( 0, N-1 ) will be used. */ /* KS (input) INTEGER */ /* The bandwidth of the matrix S. It may only be zero or one. */ /* If zero, then S is diagonal, and E is not referenced. If */ /* one, then S is symmetric tri-diagonal. */ /* A (input) DOUBLE PRECISION array, dimension (LDA, N) */ /* The original (unfactored) matrix. It is assumed to be */ /* symmetric, and only the upper (UPLO='U') or only the lower */ /* (UPLO='L') will be referenced. */ /* LDA (input) INTEGER */ /* The leading dimension of A. It must be at least 1 */ /* and at least min( KA, N-1 ). */ /* D (input) DOUBLE PRECISION array, dimension (N) */ /* The diagonal of the (symmetric tri-) diagonal matrix S. */ /* E (input) DOUBLE PRECISION array, dimension (N-1) */ /* The off-diagonal of the (symmetric tri-) diagonal matrix S. */ /* E(1) is the (1,2) and (2,1) element, E(2) is the (2,3) and */ /* (3,2) element, etc. */ /* Not referenced if KS=0. */ /* U (input) DOUBLE PRECISION array, dimension (LDU, N) */ /* The orthogonal matrix in the decomposition, expressed as a */ /* dense matrix (i.e., not as a product of Householder */ /* transformations, Givens transformations, etc.) */ /* LDU (input) INTEGER */ /* The leading dimension of U. LDU must be at least N and */ /* at least 1. */ /* WORK (workspace) DOUBLE PRECISION array, dimension (N**2+N) */ /* RESULT (output) DOUBLE PRECISION array, dimension (2) */ /* The values computed by the two tests described above. The */ /* values are currently limited to 1/ulp, to avoid overflow. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Constants */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --d__; --e; u_dim1 = *ldu; u_offset = 1 + u_dim1; u -= u_offset; --work; --result; /* Function Body */ result[1] = 0.; result[2] = 0.; if (*n <= 0) { return 0; } /* Computing MAX */ /* Computing MIN */ i__3 = *n - 1; i__1 = 0, i__2 = min(i__3,*ka); ika = max(i__1,i__2); lw = *n * (*n + 1) / 2; if (lsame_(uplo, "U")) { lower = FALSE_; *(unsigned char *)cuplo = 'U'; } else { lower = TRUE_; *(unsigned char *)cuplo = 'L'; } unfl = dlamch_("Safe minimum"); ulp = dlamch_("Epsilon") * dlamch_("Base"); /* Some Error Checks */ /* Do Test 1 */ /* Norm of A: */ /* Computing MAX */ d__1 = dlansb_("1", cuplo, n, &ika, &a[a_offset], lda, &work[1]); anorm = max(d__1,unfl); /* Compute error matrix: Error = A - U S U' */ /* Copy A from SB to SP storage format. */ j = 0; i__1 = *n; for (jc = 1; jc <= i__1; ++jc) { if (lower) { /* Computing MIN */ i__3 = ika + 1, i__4 = *n + 1 - jc; i__2 = min(i__3,i__4); for (jr = 1; jr <= i__2; ++jr) { ++j; work[j] = a[jr + jc * a_dim1]; /* L10: */ } i__2 = *n + 1 - jc; for (jr = ika + 2; jr <= i__2; ++jr) { ++j; work[j] = 0.; /* L20: */ } } else { i__2 = jc; for (jr = ika + 2; jr <= i__2; ++jr) { ++j; work[j] = 0.; /* L30: */ } /* Computing MIN */ i__2 = ika, i__3 = jc - 1; for (jr = min(i__2,i__3); jr >= 0; --jr) { ++j; work[j] = a[ika + 1 - jr + jc * a_dim1]; /* L40: */ } } /* L50: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { d__1 = -d__[j]; dspr_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &work[1]) ; /* L60: */ } if (*n > 1 && *ks == 1) { i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { d__1 = -e[j]; dspr2_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &u[(j + 1) * u_dim1 + 1], &c__1, &work[1]); /* L70: */ } } wnorm = dlansp_("1", cuplo, n, &work[1], &work[lw + 1]); if (anorm > wnorm) { result[1] = wnorm / anorm / (*n * ulp); } else { if (anorm < 1.) { /* Computing MIN */ d__1 = wnorm, d__2 = *n * anorm; result[1] = min(d__1,d__2) / anorm / (*n * ulp); } else { /* Computing MIN */ d__1 = wnorm / anorm, d__2 = (doublereal) (*n); result[1] = min(d__1,d__2) / (*n * ulp); } } /* Do Test 2 */ /* Compute UU' - I */ dgemm_("N", "C", n, n, n, &c_b22, &u[u_offset], ldu, &u[u_offset], ldu, & c_b23, &work[1], n); i__1 = *n; for (j = 1; j <= i__1; ++j) { work[(*n + 1) * (j - 1) + 1] += -1.; /* L80: */ } /* Computing MIN */ /* Computing 2nd power */ i__1 = *n; d__1 = dlange_("1", n, n, &work[1], n, &work[i__1 * i__1 + 1]), d__2 = (doublereal) (*n); result[2] = min(d__1,d__2) / (*n * ulp); return 0; /* End of DSBT21 */ } /* dsbt21_ */
/* Subroutine */ int dspev_(char *jobz, char *uplo, integer *n, doublereal * ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, integer *info) { /* System generated locals */ integer z_dim1, z_offset, i__1; doublereal d__1; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ doublereal eps; integer inde; doublereal anrm; integer imax; doublereal rmin, rmax; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); doublereal sigma; extern logical lsame_(char *, char *); integer iinfo; logical wantz; extern doublereal dlamch_(char *); integer iscale; doublereal safmin; extern /* Subroutine */ int xerbla_(char *, integer *); doublereal bignum; extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); integer indtau; extern /* Subroutine */ int dsterf_(integer *, doublereal *, doublereal *, integer *); integer indwrk; extern /* Subroutine */ int dopgtr_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *), dsptrd_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *), dsteqr_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *); doublereal smlnum; /* -- LAPACK driver routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPEV computes all the eigenvalues and, optionally, eigenvectors of a */ /* real symmetric matrix A in packed storage. */ /* Arguments */ /* ========= */ /* JOBZ (input) CHARACTER*1 */ /* = 'N': Compute eigenvalues only; */ /* = 'V': Compute eigenvalues and eigenvectors. */ /* UPLO (input) CHARACTER*1 */ /* = 'U': Upper triangle of A is stored; */ /* = 'L': Lower triangle of A is stored. */ /* N (input) INTEGER */ /* The order of the matrix A. N >= 0. */ /* AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* On entry, the upper or lower triangle of the symmetric matrix */ /* A, packed columnwise in a linear array. The j-th column of A */ /* is stored in the array AP as follows: */ /* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j; */ /* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n. */ /* On exit, AP is overwritten by values generated during the */ /* reduction to tridiagonal form. If UPLO = 'U', the diagonal */ /* and first superdiagonal of the tridiagonal matrix T overwrite */ /* the corresponding elements of A, and if UPLO = 'L', the */ /* diagonal and first subdiagonal of T overwrite the */ /* corresponding elements of A. */ /* W (output) DOUBLE PRECISION array, dimension (N) */ /* If INFO = 0, the eigenvalues in ascending order. */ /* Z (output) DOUBLE PRECISION array, dimension (LDZ, N) */ /* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal */ /* eigenvectors of the matrix A, with the i-th column of Z */ /* holding the eigenvector associated with W(i). */ /* If JOBZ = 'N', then Z is not referenced. */ /* LDZ (input) INTEGER */ /* The leading dimension of the array Z. LDZ >= 1, and if */ /* JOBZ = 'V', LDZ >= max(1,N). */ /* WORK (workspace) DOUBLE PRECISION array, dimension (3*N) */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* > 0: if INFO = i, the algorithm failed to converge; i */ /* off-diagonal elements of an intermediate tridiagonal */ /* form did not converge to zero. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --w; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --work; /* Function Body */ wantz = lsame_(jobz, "V"); *info = 0; if (! (wantz || lsame_(jobz, "N"))) { *info = -1; } else if (! (lsame_(uplo, "U") || lsame_(uplo, "L"))) { *info = -2; } else if (*n < 0) { *info = -3; } else if (*ldz < 1 || wantz && *ldz < *n) { *info = -7; } if (*info != 0) { i__1 = -(*info); xerbla_("DSPEV ", &i__1); return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } if (*n == 1) { w[1] = ap[1]; if (wantz) { z__[z_dim1 + 1] = 1.; } return 0; } /* Get machine constants. */ safmin = dlamch_("Safe minimum"); eps = dlamch_("Precision"); smlnum = safmin / eps; bignum = 1. / smlnum; rmin = sqrt(smlnum); rmax = sqrt(bignum); /* Scale matrix to allowable range, if necessary. */ anrm = dlansp_("M", uplo, n, &ap[1], &work[1]); iscale = 0; if (anrm > 0. && anrm < rmin) { iscale = 1; sigma = rmin / anrm; } else if (anrm > rmax) { iscale = 1; sigma = rmax / anrm; } if (iscale == 1) { i__1 = *n * (*n + 1) / 2; dscal_(&i__1, &sigma, &ap[1], &c__1); } /* Call DSPTRD to reduce symmetric packed matrix to tridiagonal form. */ inde = 1; indtau = inde + *n; dsptrd_(uplo, n, &ap[1], &w[1], &work[inde], &work[indtau], &iinfo); /* For eigenvalues only, call DSTERF. For eigenvectors, first call */ /* DOPGTR to generate the orthogonal matrix, then call DSTEQR. */ if (! wantz) { dsterf_(n, &w[1], &work[inde], info); } else { indwrk = indtau + *n; dopgtr_(uplo, n, &ap[1], &work[indtau], &z__[z_offset], ldz, &work[ indwrk], &iinfo); dsteqr_(jobz, n, &w[1], &work[inde], &z__[z_offset], ldz, &work[ indtau], info); } /* If matrix was scaled, then rescale eigenvalues appropriately. */ if (iscale == 1) { if (*info == 0) { imax = *n; } else { imax = *info - 1; } d__1 = 1. / sigma; dscal_(&imax, &d__1, &w[1], &c__1); } return 0; /* End of DSPEV */ } /* dspev_ */
int log_lkhd(GP *gp, double *phi, double *fn, double *gr) { int i, j, k; int offset; int one = 1; int ind; int err; char U = 'U'; char N = 'N'; char T = 'T'; char onec = '1'; double det = 0.0; double *deriv; double *re; double tmp; double tmptmp = 0.0; double anorm; double rcond; double *dwork; int *iwork; int ii; double nug; double t; deriv = malloc(sizeof(double) * gp->ud); re = malloc(sizeof(double) * gp->ud); R_packed_U(gp->R, gp->phi, gp->ux, gp->ud, gp->dim); nugget(gp->R, gp->ud, &nug); printf("nugget %e\n", nug); for(i=0, ii=0;i<gp->ud;i++) { gp->R[ii+i] += nug; ii += i + 1; } /* for(i=0,offset=0;i<gp->ud;i++) { for(j=0;j<=i;j++) { printf("%e ", gp->R[offset+j]); } printf("\n"); offset+=i+1; } */ #ifdef SAT_DEBUG dwork = malloc(sizeof(double) * gp->ud * 3); iwork = malloc(sizeof(double) * gp->ud); anorm = dlansp_(&onec, &U, &gp->ud, gp->R, dwork); printf("anorm %e\n", rcond); #endif dpptrf_(&U, &gp->ud, gp->R, &err); // R^-1 if(err!=0){printf("CHOLESKY ERROR: %d\n", err);return(err);} #ifdef SAT_DEBUG dppcon_(&U, &gp->ud, gp->R, &anorm, &rcond, dwork, iwork, &err); printf("rcond %e\n", rcond); if(err!=0){printf("RCOND ERROR: %d\n", err);return(err);} free(dwork); free(iwork); #endif /* for(i=0,offset=0;i<gp->ud;i++) { for(j=0;j<=i;j++) { printf("%e ", gp->R[offset+j]); } printf("\n"); offset+=i+1; } */ for(i=0;i<gp->ud;i++) { gp->e[i] = gp->uy[i]; gp->F[i] = 1.0; } //dpptrs_(&U, &gp->ud, &one, gp->R, gp->e, &gp->dd, &err); // R^-1 * y dtpsv_(&U, &T, &N, &gp->ud, gp->R, gp->e, &one); // R^-1 * y //if(err!=0){printf("error: %d\n", err);} //dpptrs_(&U, &gp->ud, &one, gp->R, gp->F, &gp->dd, &err); // R^-1 * 1 dtpsv_(&U, &T, &N, &gp->ud, gp->R, gp->F, &one); // R^-1 * 1 //if(err!=0){printf("error: %d\n", err);} *gp->FRF = ddot_(&gp->ud, gp->F, &one, gp->F, &one); //1^t * R^-1 * 1 //printf("FRF %e\n", *gp->FRF); *gp->beta = (1.0/(*gp->FRF)) * ddot_(&gp->ud, gp->F, &one, gp->e, &one); //beta = (1^t * R^-1 * 1)^-1 * 1^t * R^-1 * y //printf("beta %e\n", *gp->beta); for(i=0;i<gp->ud;i++) { gp->e[i] = gp->uy[i] - *gp->beta; } for(i=0;i<gp->ud;i++) { //printf("R1 %e\n", gp->F[i]); } //dpptrs_(&U, &gp->ud, &one, gp->R, gp->e, &gp->dd, &err); // R^-1 * e dtpsv_(&U, &T, &N, &gp->ud, gp->R, gp->e, &one); // R^-1 * e //if(err!=0){printf("error: %d\n", err);} gp->sigma = (1.0/(double)gp->ud) * ddot_(&gp->ud, gp->e, &one, gp->e, &one); // sigma = 1/N * e^t * R^-1 * e for(i=0,ind=0;i<gp->ud;i++) { det += log(gp->R[ind+i]); ind += i+1; } det *= 2.0; *fn = det + gp->ud * gp->sigma; // CALCULATION OF GRADIENT t = omp_get_wtime(); for(i=0;i<gp->dim;i++) { gr[i] = 0.0; } for(i=0;i<gp->ud;i++) { re[i] = gp->e[i]; } dtpsv_(&U, &N, &N, &gp->ud, gp->R, re, &one); // R^-1 * e for(k=0;k<gp->ud;k++) { for(i=0;i<gp->ud;i++) { deriv[i] = -re[k] * (gp->uy[i] - *gp->beta); } deriv[k] += 1.0; dpptrs_(&U, &gp->ud, &one, gp->R, deriv, &gp->dd, &err); for(j=0;j<gp->ud;j++) { for(i=0;i<gp->dim;i++) { kernel_deriv(i, &gp->ux[j*gp->dim], &gp->ux[k*gp->dim], gp->phi, gp->dim, &tmp); gr[i] += deriv[j] * tmp; } } } t = omp_get_wtime() - t; printf("ITER %d time-grad %e\n", gp->ud, t); free(deriv); free(re); return(0); }
/* Subroutine */ int dspt21_(integer *itype, char *uplo, integer *n, integer * kband, doublereal *ap, doublereal *d__, doublereal *e, doublereal *u, integer *ldu, doublereal *vp, doublereal *tau, doublereal *work, doublereal *result) { /* System generated locals */ integer u_dim1, u_offset, i__1, i__2; doublereal d__1, d__2; /* Local variables */ integer j, jp, jr, jp1, lap; doublereal ulp; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); doublereal unfl, temp; extern /* Subroutine */ int dspr_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *), dspr2_(char *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *), dgemm_(char *, char *, integer * , integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); extern logical lsame_(char *, char *); integer iinfo; doublereal anorm; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); char cuplo[1]; doublereal vsave; extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *); logical lower; extern /* Subroutine */ int dspmv_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *); doublereal wnorm; extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); extern /* Subroutine */ int dopmtr_(char *, char *, char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *); /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSPT21 generally checks a decomposition of the form */ /* A = U S U' */ /* where ' means transpose, A is symmetric (stored in packed format), U */ /* is orthogonal, and S is diagonal (if KBAND=0) or symmetric */ /* tridiagonal (if KBAND=1). If ITYPE=1, then U is represented as a */ /* dense matrix, otherwise the U is expressed as a product of */ /* Householder transformations, whose vectors are stored in the array */ /* "V" and whose scaling constants are in "TAU"; we shall use the */ /* letter "V" to refer to the product of Householder transformations */ /* (which should be equal to U). */ /* Specifically, if ITYPE=1, then: */ /* RESULT(1) = | A - U S U' | / ( |A| n ulp ) *and* */ /* RESULT(2) = | I - UU' | / ( n ulp ) */ /* If ITYPE=2, then: */ /* RESULT(1) = | A - V S V' | / ( |A| n ulp ) */ /* If ITYPE=3, then: */ /* RESULT(1) = | I - VU' | / ( n ulp ) */ /* Packed storage means that, for example, if UPLO='U', then the columns */ /* of the upper triangle of A are stored one after another, so that */ /* A(1,j+1) immediately follows A(j,j) in the array AP. Similarly, if */ /* UPLO='L', then the columns of the lower triangle of A are stored one */ /* after another in AP, so that A(j+1,j+1) immediately follows A(n,j) */ /* in the array AP. This means that A(i,j) is stored in: */ /* AP( i + j*(j-1)/2 ) if UPLO='U' */ /* AP( i + (2*n-j)*(j-1)/2 ) if UPLO='L' */ /* The array VP bears the same relation to the matrix V that A does to */ /* AP. */ /* For ITYPE > 1, the transformation U is expressed as a product */ /* of Householder transformations: */ /* If UPLO='U', then V = H(n-1)...H(1), where */ /* H(j) = I - tau(j) v(j) v(j)' */ /* and the first j-1 elements of v(j) are stored in V(1:j-1,j+1), */ /* (i.e., VP( j*(j+1)/2 + 1 : j*(j+1)/2 + j-1 ) ), */ /* the j-th element is 1, and the last n-j elements are 0. */ /* If UPLO='L', then V = H(1)...H(n-1), where */ /* H(j) = I - tau(j) v(j) v(j)' */ /* and the first j elements of v(j) are 0, the (j+1)-st is 1, and the */ /* (j+2)-nd through n-th elements are stored in V(j+2:n,j) (i.e., */ /* in VP( (2*n-j)*(j-1)/2 + j+2 : (2*n-j)*(j-1)/2 + n ) .) */ /* Arguments */ /* ========= */ /* ITYPE (input) INTEGER */ /* Specifies the type of tests to be performed. */ /* 1: U expressed as a dense orthogonal matrix: */ /* RESULT(1) = | A - U S U' | / ( |A| n ulp ) *and* */ /* RESULT(2) = | I - UU' | / ( n ulp ) */ /* 2: U expressed as a product V of Housholder transformations: */ /* RESULT(1) = | A - V S V' | / ( |A| n ulp ) */ /* 3: U expressed both as a dense orthogonal matrix and */ /* as a product of Housholder transformations: */ /* RESULT(1) = | I - VU' | / ( n ulp ) */ /* UPLO (input) CHARACTER */ /* If UPLO='U', AP and VP are considered to contain the upper */ /* triangle of A and V. */ /* If UPLO='L', AP and VP are considered to contain the lower */ /* triangle of A and V. */ /* N (input) INTEGER */ /* The size of the matrix. If it is zero, DSPT21 does nothing. */ /* It must be at least zero. */ /* KBAND (input) INTEGER */ /* The bandwidth of the matrix. It may only be zero or one. */ /* If zero, then S is diagonal, and E is not referenced. If */ /* one, then S is symmetric tri-diagonal. */ /* AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* The original (unfactored) matrix. It is assumed to be */ /* symmetric, and contains the columns of just the upper */ /* triangle (UPLO='U') or only the lower triangle (UPLO='L'), */ /* packed one after another. */ /* D (input) DOUBLE PRECISION array, dimension (N) */ /* The diagonal of the (symmetric tri-) diagonal matrix. */ /* E (input) DOUBLE PRECISION array, dimension (N-1) */ /* The off-diagonal of the (symmetric tri-) diagonal matrix. */ /* E(1) is the (1,2) and (2,1) element, E(2) is the (2,3) and */ /* (3,2) element, etc. */ /* Not referenced if KBAND=0. */ /* U (input) DOUBLE PRECISION array, dimension (LDU, N) */ /* If ITYPE=1 or 3, this contains the orthogonal matrix in */ /* the decomposition, expressed as a dense matrix. If ITYPE=2, */ /* then it is not referenced. */ /* LDU (input) INTEGER */ /* The leading dimension of U. LDU must be at least N and */ /* at least 1. */ /* VP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* If ITYPE=2 or 3, the columns of this array contain the */ /* Householder vectors used to describe the orthogonal matrix */ /* in the decomposition, as described in purpose. */ /* *NOTE* If ITYPE=2 or 3, V is modified and restored. The */ /* subdiagonal (if UPLO='L') or the superdiagonal (if UPLO='U') */ /* is set to one, and later reset to its original value, during */ /* the course of the calculation. */ /* If ITYPE=1, then it is neither referenced nor modified. */ /* TAU (input) DOUBLE PRECISION array, dimension (N) */ /* If ITYPE >= 2, then TAU(j) is the scalar factor of */ /* v(j) v(j)' in the Householder transformation H(j) of */ /* the product U = H(1)...H(n-2) */ /* If ITYPE < 2, then TAU is not referenced. */ /* WORK (workspace) DOUBLE PRECISION array, dimension (N**2+N) */ /* Workspace. */ /* RESULT (output) DOUBLE PRECISION array, dimension (2) */ /* The values computed by the two tests described above. The */ /* values are currently limited to 1/ulp, to avoid overflow. */ /* RESULT(1) is always modified. RESULT(2) is modified only */ /* if ITYPE=1. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* 1) Constants */ /* Parameter adjustments */ --ap; --d__; --e; u_dim1 = *ldu; u_offset = 1 + u_dim1; u -= u_offset; --vp; --tau; --work; --result; /* Function Body */ result[1] = 0.; if (*itype == 1) { result[2] = 0.; } if (*n <= 0) { return 0; } lap = *n * (*n + 1) / 2; if (lsame_(uplo, "U")) { lower = FALSE_; *(unsigned char *)cuplo = 'U'; } else { lower = TRUE_; *(unsigned char *)cuplo = 'L'; } unfl = dlamch_("Safe minimum"); ulp = dlamch_("Epsilon") * dlamch_("Base"); /* Some Error Checks */ if (*itype < 1 || *itype > 3) { result[1] = 10. / ulp; return 0; } /* Do Test 1 */ /* Norm of A: */ if (*itype == 3) { anorm = 1.; } else { /* Computing MAX */ d__1 = dlansp_("1", cuplo, n, &ap[1], &work[1]); anorm = max(d__1,unfl); } /* Compute error matrix: */ if (*itype == 1) { /* ITYPE=1: error = A - U S U' */ dlaset_("Full", n, n, &c_b10, &c_b10, &work[1], n); dcopy_(&lap, &ap[1], &c__1, &work[1], &c__1); i__1 = *n; for (j = 1; j <= i__1; ++j) { d__1 = -d__[j]; dspr_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &work[1]); /* L10: */ } if (*n > 1 && *kband == 1) { i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { d__1 = -e[j]; dspr2_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &u[(j + 1) * u_dim1 + 1], &c__1, &work[1]); /* L20: */ } } /* Computing 2nd power */ i__1 = *n; wnorm = dlansp_("1", cuplo, n, &work[1], &work[i__1 * i__1 + 1]); } else if (*itype == 2) { /* ITYPE=2: error = V S V' - A */ dlaset_("Full", n, n, &c_b10, &c_b10, &work[1], n); if (lower) { work[lap] = d__[*n]; for (j = *n - 1; j >= 1; --j) { jp = ((*n << 1) - j) * (j - 1) / 2; jp1 = jp + *n - j; if (*kband == 1) { work[jp + j + 1] = (1. - tau[j]) * e[j]; i__1 = *n; for (jr = j + 2; jr <= i__1; ++jr) { work[jp + jr] = -tau[j] * e[j] * vp[jp + jr]; /* L30: */ } } if (tau[j] != 0.) { vsave = vp[jp + j + 1]; vp[jp + j + 1] = 1.; i__1 = *n - j; dspmv_("L", &i__1, &c_b26, &work[jp1 + j + 1], &vp[jp + j + 1], &c__1, &c_b10, &work[lap + 1], &c__1); i__1 = *n - j; temp = tau[j] * -.5 * ddot_(&i__1, &work[lap + 1], &c__1, &vp[jp + j + 1], &c__1); i__1 = *n - j; daxpy_(&i__1, &temp, &vp[jp + j + 1], &c__1, &work[lap + 1], &c__1); i__1 = *n - j; d__1 = -tau[j]; dspr2_("L", &i__1, &d__1, &vp[jp + j + 1], &c__1, &work[ lap + 1], &c__1, &work[jp1 + j + 1]); vp[jp + j + 1] = vsave; } work[jp + j] = d__[j]; /* L40: */ } } else { work[1] = d__[1]; i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { jp = j * (j - 1) / 2; jp1 = jp + j; if (*kband == 1) { work[jp1 + j] = (1. - tau[j]) * e[j]; i__2 = j - 1; for (jr = 1; jr <= i__2; ++jr) { work[jp1 + jr] = -tau[j] * e[j] * vp[jp1 + jr]; /* L50: */ } } if (tau[j] != 0.) { vsave = vp[jp1 + j]; vp[jp1 + j] = 1.; dspmv_("U", &j, &c_b26, &work[1], &vp[jp1 + 1], &c__1, & c_b10, &work[lap + 1], &c__1); temp = tau[j] * -.5 * ddot_(&j, &work[lap + 1], &c__1, & vp[jp1 + 1], &c__1); daxpy_(&j, &temp, &vp[jp1 + 1], &c__1, &work[lap + 1], & c__1); d__1 = -tau[j]; dspr2_("U", &j, &d__1, &vp[jp1 + 1], &c__1, &work[lap + 1] , &c__1, &work[1]); vp[jp1 + j] = vsave; } work[jp1 + j + 1] = d__[j + 1]; /* L60: */ } } i__1 = lap; for (j = 1; j <= i__1; ++j) { work[j] -= ap[j]; /* L70: */ } wnorm = dlansp_("1", cuplo, n, &work[1], &work[lap + 1]); } else if (*itype == 3) { /* ITYPE=3: error = U V' - I */ if (*n < 2) { return 0; } dlacpy_(" ", n, n, &u[u_offset], ldu, &work[1], n); /* Computing 2nd power */ i__1 = *n; dopmtr_("R", cuplo, "T", n, n, &vp[1], &tau[1], &work[1], n, &work[ i__1 * i__1 + 1], &iinfo); if (iinfo != 0) { result[1] = 10. / ulp; return 0; } i__1 = *n; for (j = 1; j <= i__1; ++j) { work[(*n + 1) * (j - 1) + 1] += -1.; /* L80: */ } /* Computing 2nd power */ i__1 = *n; wnorm = dlange_("1", n, n, &work[1], n, &work[i__1 * i__1 + 1]); } if (anorm > wnorm) { result[1] = wnorm / anorm / (*n * ulp); } else { if (anorm < 1.) { /* Computing MIN */ d__1 = wnorm, d__2 = *n * anorm; result[1] = min(d__1,d__2) / anorm / (*n * ulp); } else { /* Computing MIN */ d__1 = wnorm / anorm, d__2 = (doublereal) (*n); result[1] = min(d__1,d__2) / (*n * ulp); } } /* Do Test 2 */ /* Compute UU' - I */ if (*itype == 1) { dgemm_("N", "C", n, n, n, &c_b26, &u[u_offset], ldu, &u[u_offset], ldu, &c_b10, &work[1], n); i__1 = *n; for (j = 1; j <= i__1; ++j) { work[(*n + 1) * (j - 1) + 1] += -1.; /* L90: */ } /* Computing MIN */ /* Computing 2nd power */ i__1 = *n; d__1 = dlange_("1", n, n, &work[1], n, &work[i__1 * i__1 + 1]), d__2 = (doublereal) (*n); result[2] = min(d__1,d__2) / (*n * ulp); } return 0; /* End of DSPT21 */ } /* dspt21_ */
/* Subroutine */ int dchkpp_(logical *dotype, integer *nn, integer *nval, integer *nns, integer *nsval, doublereal *thresh, logical *tsterr, integer *nmax, doublereal *a, doublereal *afac, doublereal *ainv, doublereal *b, doublereal *x, doublereal *xact, doublereal *work, doublereal *rwork, integer *iwork, integer *nout) { /* Initialized data */ static integer iseedy[4] = { 1988,1989,1990,1991 }; static char uplos[1*2] = "U" "L"; static char packs[1*2] = "C" "R"; /* Format strings */ static char fmt_9999[] = "(\002 UPLO = '\002,a1,\002', N =\002,i5,\002, " "type \002,i2,\002, test \002,i2,\002, ratio =\002,g12.5)"; static char fmt_9998[] = "(\002 UPLO = '\002,a1,\002', N =\002,i5,\002, " "NRHS=\002,i3,\002, type \002,i2,\002, test(\002,i2,\002) =\002,g" "12.5)"; /* System generated locals */ integer i__1, i__2, i__3; /* Builtin functions */ /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ integer i__, k, n, in, kl, ku, lda, npp, ioff, mode, imat, info; char path[3], dist[1]; integer irhs, nrhs; char uplo[1], type__[1]; integer nrun; extern /* Subroutine */ int alahd_(integer *, char *), dget04_( integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); integer nfail, iseed[4]; extern doublereal dget06_(doublereal *, doublereal *); doublereal rcond; integer nimat; extern /* Subroutine */ int dppt01_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *), dppt02_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *), dppt03_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, doublereal *); doublereal anorm; extern /* Subroutine */ int dppt05_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *), dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); integer iuplo, izero, nerrs; logical zerot; char xtype[1]; extern /* Subroutine */ int dlatb4_(char *, integer *, integer *, integer *, char *, integer *, integer *, doublereal *, integer *, doublereal *, char *), alaerh_(char *, char *, integer *, integer *, char *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *); doublereal rcondc; char packit[1]; extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlarhs_(char *, char *, char *, char *, integer *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *, integer *); extern doublereal dlansp_(char *, char *, integer *, doublereal *, doublereal *); extern /* Subroutine */ int alasum_(char *, integer *, integer *, integer *, integer *); doublereal cndnum; extern /* Subroutine */ int dlatms_(integer *, integer *, char *, integer *, char *, doublereal *, integer *, doublereal *, doublereal *, integer *, integer *, char *, doublereal *, integer *, doublereal *, integer *), dppcon_(char *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, integer *), derrpo_(char *, integer *), dpprfs_( char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *), dpptrf_(char *, integer *, doublereal *, integer *), dpptri_(char *, integer *, doublereal *, integer *), dpptrs_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *); doublereal result[8]; /* Fortran I/O blocks */ static cilist io___34 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___37 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___39 = { 0, 0, 0, fmt_9999, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DCHKPP tests DPPTRF, -TRI, -TRS, -RFS, and -CON */ /* Arguments */ /* ========= */ /* DOTYPE (input) LOGICAL array, dimension (NTYPES) */ /* The matrix types to be used for testing. Matrices of type j */ /* (for 1 <= j <= NTYPES) are used for testing if DOTYPE(j) = */ /* .TRUE.; if DOTYPE(j) = .FALSE., then type j is not used. */ /* NN (input) INTEGER */ /* The number of values of N contained in the vector NVAL. */ /* NVAL (input) INTEGER array, dimension (NN) */ /* The values of the matrix dimension N. */ /* NNS (input) INTEGER */ /* The number of values of NRHS contained in the vector NSVAL. */ /* NSVAL (input) INTEGER array, dimension (NNS) */ /* The values of the number of right hand sides NRHS. */ /* THRESH (input) DOUBLE PRECISION */ /* The threshold value for the test ratios. A result is */ /* included in the output file if RESULT >= THRESH. To have */ /* every test ratio printed, use THRESH = 0. */ /* TSTERR (input) LOGICAL */ /* Flag that indicates whether error exits are to be tested. */ /* NMAX (input) INTEGER */ /* The maximum value permitted for N, used in dimensioning the */ /* work arrays. */ /* A (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AFAC (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AINV (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* B (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */ /* where NSMAX is the largest entry in NSVAL. */ /* X (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */ /* XACT (workspace) DOUBLE PRECISION array, dimension (NMAX*NSMAX) */ /* WORK (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*max(3,NSMAX)) */ /* RWORK (workspace) DOUBLE PRECISION array, dimension */ /* (max(NMAX,2*NSMAX)) */ /* IWORK (workspace) INTEGER array, dimension (NMAX) */ /* NOUT (input) INTEGER */ /* The unit number for output. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Data statements .. */ /* Parameter adjustments */ --iwork; --rwork; --work; --xact; --x; --b; --ainv; --afac; --a; --nsval; --nval; --dotype; /* Function Body */ /* .. */ /* .. Executable Statements .. */ /* Initialize constants and the random number seed. */ s_copy(path, "Double precision", (ftnlen)1, (ftnlen)16); s_copy(path + 1, "PP", (ftnlen)2, (ftnlen)2); nrun = 0; nfail = 0; nerrs = 0; for (i__ = 1; i__ <= 4; ++i__) { iseed[i__ - 1] = iseedy[i__ - 1]; /* L10: */ } /* Test the error exits */ if (*tsterr) { derrpo_(path, nout); } infoc_1.infot = 0; /* Do for each value of N in NVAL */ i__1 = *nn; for (in = 1; in <= i__1; ++in) { n = nval[in]; lda = max(n,1); *(unsigned char *)xtype = 'N'; nimat = 9; if (n <= 0) { nimat = 1; } i__2 = nimat; for (imat = 1; imat <= i__2; ++imat) { /* Do the tests only if DOTYPE( IMAT ) is true. */ if (! dotype[imat]) { goto L100; } /* Skip types 3, 4, or 5 if the matrix size is too small. */ zerot = imat >= 3 && imat <= 5; if (zerot && n < imat - 2) { goto L100; } /* Do first for UPLO = 'U', then for UPLO = 'L' */ for (iuplo = 1; iuplo <= 2; ++iuplo) { *(unsigned char *)uplo = *(unsigned char *)&uplos[iuplo - 1]; *(unsigned char *)packit = *(unsigned char *)&packs[iuplo - 1] ; /* Set up parameters with DLATB4 and generate a test matrix */ /* with DLATMS. */ dlatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode, &cndnum, dist); s_copy(srnamc_1.srnamt, "DLATMS", (ftnlen)32, (ftnlen)6); dlatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, & cndnum, &anorm, &kl, &ku, packit, &a[1], &lda, &work[ 1], &info); /* Check error code from DLATMS. */ if (info != 0) { alaerh_(path, "DLATMS", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); goto L90; } /* For types 3-5, zero one row and column of the matrix to */ /* test that INFO is returned correctly. */ if (zerot) { if (imat == 3) { izero = 1; } else if (imat == 4) { izero = n; } else { izero = n / 2 + 1; } /* Set row and column IZERO of A to 0. */ if (iuplo == 1) { ioff = (izero - 1) * izero / 2; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L20: */ } ioff += izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff += i__; /* L30: */ } } else { ioff = izero; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff = ioff + n - i__; /* L40: */ } ioff -= izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L50: */ } } } else { izero = 0; } /* Compute the L*L' or U'*U factorization of the matrix. */ npp = n * (n + 1) / 2; dcopy_(&npp, &a[1], &c__1, &afac[1], &c__1); s_copy(srnamc_1.srnamt, "DPPTRF", (ftnlen)32, (ftnlen)6); dpptrf_(uplo, &n, &afac[1], &info); /* Check error code from DPPTRF. */ if (info != izero) { alaerh_(path, "DPPTRF", &info, &izero, uplo, &n, &n, & c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); goto L90; } /* Skip the tests if INFO is not 0. */ if (info != 0) { goto L90; } /* + TEST 1 */ /* Reconstruct matrix from factors and compute residual. */ dcopy_(&npp, &afac[1], &c__1, &ainv[1], &c__1); dppt01_(uplo, &n, &a[1], &ainv[1], &rwork[1], result); /* + TEST 2 */ /* Form the inverse and compute the residual. */ dcopy_(&npp, &afac[1], &c__1, &ainv[1], &c__1); s_copy(srnamc_1.srnamt, "DPPTRI", (ftnlen)32, (ftnlen)6); dpptri_(uplo, &n, &ainv[1], &info); /* Check error code from DPPTRI. */ if (info != 0) { alaerh_(path, "DPPTRI", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); } dppt03_(uplo, &n, &a[1], &ainv[1], &work[1], &lda, &rwork[1], &rcondc, &result[1]); /* Print information about the tests that did not pass */ /* the threshold. */ for (k = 1; k <= 2; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { alahd_(nout, path); } io___34.ciunit = *nout; s_wsfe(&io___34); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&imat, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&result[k - 1], (ftnlen)sizeof( doublereal)); e_wsfe(); ++nfail; } /* L60: */ } nrun += 2; i__3 = *nns; for (irhs = 1; irhs <= i__3; ++irhs) { nrhs = nsval[irhs]; /* + TEST 3 */ /* Solve and compute residual for A * X = B. */ s_copy(srnamc_1.srnamt, "DLARHS", (ftnlen)32, (ftnlen)6); dlarhs_(path, xtype, uplo, " ", &n, &n, &kl, &ku, &nrhs, & a[1], &lda, &xact[1], &lda, &b[1], &lda, iseed, & info); dlacpy_("Full", &n, &nrhs, &b[1], &lda, &x[1], &lda); s_copy(srnamc_1.srnamt, "DPPTRS", (ftnlen)32, (ftnlen)6); dpptrs_(uplo, &n, &nrhs, &afac[1], &x[1], &lda, &info); /* Check error code from DPPTRS. */ if (info != 0) { alaerh_(path, "DPPTRS", &info, &c__0, uplo, &n, &n, & c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, nout); } dlacpy_("Full", &n, &nrhs, &b[1], &lda, &work[1], &lda); dppt02_(uplo, &n, &nrhs, &a[1], &x[1], &lda, &work[1], & lda, &rwork[1], &result[2]); /* + TEST 4 */ /* Check solution from generated exact solution. */ dget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, & result[3]); /* + TESTS 5, 6, and 7 */ /* Use iterative refinement to improve the solution. */ s_copy(srnamc_1.srnamt, "DPPRFS", (ftnlen)32, (ftnlen)6); dpprfs_(uplo, &n, &nrhs, &a[1], &afac[1], &b[1], &lda, &x[ 1], &lda, &rwork[1], &rwork[nrhs + 1], &work[1], & iwork[1], &info); /* Check error code from DPPRFS. */ if (info != 0) { alaerh_(path, "DPPRFS", &info, &c__0, uplo, &n, &n, & c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, nout); } dget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, & result[4]); dppt05_(uplo, &n, &nrhs, &a[1], &b[1], &lda, &x[1], &lda, &xact[1], &lda, &rwork[1], &rwork[nrhs + 1], & result[5]); /* Print information about the tests that did not pass */ /* the threshold. */ for (k = 3; k <= 7; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { alahd_(nout, path); } io___37.ciunit = *nout; s_wsfe(&io___37); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&nrhs, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&imat, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof(integer)) ; do_fio(&c__1, (char *)&result[k - 1], (ftnlen) sizeof(doublereal)); e_wsfe(); ++nfail; } /* L70: */ } nrun += 5; /* L80: */ } /* + TEST 8 */ /* Get an estimate of RCOND = 1/CNDNUM. */ anorm = dlansp_("1", uplo, &n, &a[1], &rwork[1]); s_copy(srnamc_1.srnamt, "DPPCON", (ftnlen)32, (ftnlen)6); dppcon_(uplo, &n, &afac[1], &anorm, &rcond, &work[1], &iwork[ 1], &info); /* Check error code from DPPCON. */ if (info != 0) { alaerh_(path, "DPPCON", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); } result[7] = dget06_(&rcond, &rcondc); /* Print the test ratio if greater than or equal to THRESH. */ if (result[7] >= *thresh) { if (nfail == 0 && nerrs == 0) { alahd_(nout, path); } io___39.ciunit = *nout; s_wsfe(&io___39); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&imat, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&c__8, (ftnlen)sizeof(integer)); do_fio(&c__1, (char *)&result[7], (ftnlen)sizeof( doublereal)); e_wsfe(); ++nfail; } ++nrun; L90: ; } L100: ; } /* L110: */ } /* Print a summary of the results. */ alasum_(path, nout, &nfail, &nrun, &nerrs); return 0; /* End of DCHKPP */ } /* dchkpp_ */
/* Subroutine */ int ddrvpp_(logical *dotype, integer *nn, integer *nval, integer *nrhs, doublereal *thresh, logical *tsterr, integer *nmax, doublereal *a, doublereal *afac, doublereal *asav, doublereal *b, doublereal *bsav, doublereal *x, doublereal *xact, doublereal *s, doublereal *work, doublereal *rwork, integer *iwork, integer *nout) { /* Initialized data */ static integer iseedy[4] = { 1988,1989,1990,1991 }; static char uplos[1*2] = "U" "L"; static char facts[1*3] = "F" "N" "E"; static char packs[1*2] = "C" "R"; static char equeds[1*2] = "N" "Y"; /* Format strings */ static char fmt_9999[] = "(1x,a,\002, UPLO='\002,a1,\002', N =\002,i5" ",\002, type \002,i1,\002, test(\002,i1,\002)=\002,g12.5)"; static char fmt_9997[] = "(1x,a,\002, FACT='\002,a1,\002', UPLO='\002," "a1,\002', N=\002,i5,\002, EQUED='\002,a1,\002', type \002,i1," "\002, test(\002,i1,\002)=\002,g12.5)"; static char fmt_9998[] = "(1x,a,\002, FACT='\002,a1,\002', UPLO='\002," "a1,\002', N=\002,i5,\002, type \002,i1,\002, test(\002,i1,\002)" "=\002,g12.5)"; /* System generated locals */ address a__1[2]; integer i__1, i__2, i__3, i__4, i__5[2]; char ch__1[2]; /* Local variables */ integer i__, k, n, k1, in, kl, ku, nt, lda, npp; char fact[1]; integer ioff, mode; doublereal amax; char path[3]; integer imat, info; char dist[1], uplo[1], type__[1]; integer nrun, ifact; integer nfail, iseed[4], nfact; char equed[1]; doublereal roldc, rcond, scond; integer nimat; doublereal anorm; logical equil; integer iuplo, izero, nerrs; logical zerot; char xtype[1]; logical prefac; doublereal rcondc; logical nofact; char packit[1]; integer iequed; doublereal cndnum; doublereal ainvnm; doublereal result[6]; /* Fortran I/O blocks */ static cilist io___49 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___52 = { 0, 0, 0, fmt_9997, 0 }; static cilist io___53 = { 0, 0, 0, fmt_9998, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DDRVPP tests the driver routines DPPSV and -SVX. */ /* Arguments */ /* ========= */ /* DOTYPE (input) LOGICAL array, dimension (NTYPES) */ /* The matrix types to be used for testing. Matrices of type j */ /* (for 1 <= j <= NTYPES) are used for testing if DOTYPE(j) = */ /* .TRUE.; if DOTYPE(j) = .FALSE., then type j is not used. */ /* NN (input) INTEGER */ /* The number of values of N contained in the vector NVAL. */ /* NVAL (input) INTEGER array, dimension (NN) */ /* The values of the matrix dimension N. */ /* NRHS (input) INTEGER */ /* The number of right hand side vectors to be generated for */ /* each linear system. */ /* THRESH (input) DOUBLE PRECISION */ /* The threshold value for the test ratios. A result is */ /* included in the output file if RESULT >= THRESH. To have */ /* every test ratio printed, use THRESH = 0. */ /* TSTERR (input) LOGICAL */ /* Flag that indicates whether error exits are to be tested. */ /* NMAX (input) INTEGER */ /* The maximum value permitted for N, used in dimensioning the */ /* work arrays. */ /* A (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AFAC (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* ASAV (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* B (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* BSAV (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* X (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* XACT (workspace) DOUBLE PRECISION array, dimension (NMAX*NRHS) */ /* S (workspace) DOUBLE PRECISION array, dimension (NMAX) */ /* WORK (workspace) DOUBLE PRECISION array, dimension */ /* (NMAX*max(3,NRHS)) */ /* RWORK (workspace) DOUBLE PRECISION array, dimension (NMAX+2*NRHS) */ /* IWORK (workspace) INTEGER array, dimension (NMAX) */ /* NOUT (input) INTEGER */ /* The unit number for output. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Data statements .. */ /* Parameter adjustments */ --iwork; --rwork; --work; --s; --xact; --x; --bsav; --b; --asav; --afac; --a; --nval; --dotype; /* Function Body */ /* .. */ /* .. Executable Statements .. */ /* Initialize constants and the random number seed. */ s_copy(path, "Double precision", (ftnlen)1, (ftnlen)16); s_copy(path + 1, "PP", (ftnlen)2, (ftnlen)2); nrun = 0; nfail = 0; nerrs = 0; for (i__ = 1; i__ <= 4; ++i__) { iseed[i__ - 1] = iseedy[i__ - 1]; /* L10: */ } /* Test the error exits */ if (*tsterr) { derrvx_(path, nout); } infoc_1.infot = 0; /* Do for each value of N in NVAL */ i__1 = *nn; for (in = 1; in <= i__1; ++in) { n = nval[in]; lda = max(n,1); npp = n * (n + 1) / 2; *(unsigned char *)xtype = 'N'; nimat = 9; if (n <= 0) { nimat = 1; } i__2 = nimat; for (imat = 1; imat <= i__2; ++imat) { /* Do the tests only if DOTYPE( IMAT ) is true. */ if (! dotype[imat]) { goto L130; } /* Skip types 3, 4, or 5 if the matrix size is too small. */ zerot = imat >= 3 && imat <= 5; if (zerot && n < imat - 2) { goto L130; } /* Do first for UPLO = 'U', then for UPLO = 'L' */ for (iuplo = 1; iuplo <= 2; ++iuplo) { *(unsigned char *)uplo = *(unsigned char *)&uplos[iuplo - 1]; *(unsigned char *)packit = *(unsigned char *)&packs[iuplo - 1] ; /* Set up parameters with DLATB4 and generate a test matrix */ /* with DLATMS. */ dlatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode, &cndnum, dist); rcondc = 1. / cndnum; s_copy(srnamc_1.srnamt, "DLATMS", (ftnlen)32, (ftnlen)6); dlatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, & cndnum, &anorm, &kl, &ku, packit, &a[1], &lda, &work[ 1], &info); /* Check error code from DLATMS. */ if (info != 0) { alaerh_(path, "DLATMS", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); goto L120; } /* For types 3-5, zero one row and column of the matrix to */ /* test that INFO is returned correctly. */ if (zerot) { if (imat == 3) { izero = 1; } else if (imat == 4) { izero = n; } else { izero = n / 2 + 1; } /* Set row and column IZERO of A to 0. */ if (iuplo == 1) { ioff = (izero - 1) * izero / 2; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L20: */ } ioff += izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff += i__; /* L30: */ } } else { ioff = izero; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { a[ioff] = 0.; ioff = ioff + n - i__; /* L40: */ } ioff -= izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { a[ioff + i__] = 0.; /* L50: */ } } } else { izero = 0; } /* Save a copy of the matrix A in ASAV. */ dcopy_(&npp, &a[1], &c__1, &asav[1], &c__1); for (iequed = 1; iequed <= 2; ++iequed) { *(unsigned char *)equed = *(unsigned char *)&equeds[ iequed - 1]; if (iequed == 1) { nfact = 3; } else { nfact = 1; } i__3 = nfact; for (ifact = 1; ifact <= i__3; ++ifact) { *(unsigned char *)fact = *(unsigned char *)&facts[ ifact - 1]; prefac = lsame_(fact, "F"); nofact = lsame_(fact, "N"); equil = lsame_(fact, "E"); if (zerot) { if (prefac) { goto L100; } rcondc = 0.; } else if (! lsame_(fact, "N")) { /* Compute the condition number for comparison with */ /* the value returned by DPPSVX (FACT = 'N' reuses */ /* the condition number from the previous iteration */ /* with FACT = 'F'). */ dcopy_(&npp, &asav[1], &c__1, &afac[1], &c__1); if (equil || iequed > 1) { /* Compute row and column scale factors to */ /* equilibrate the matrix A. */ dppequ_(uplo, &n, &afac[1], &s[1], &scond, & amax, &info); if (info == 0 && n > 0) { if (iequed > 1) { scond = 0.; } /* Equilibrate the matrix. */ dlaqsp_(uplo, &n, &afac[1], &s[1], &scond, &amax, equed); } } /* Save the condition number of the */ /* non-equilibrated system for use in DGET04. */ if (equil) { roldc = rcondc; } /* Compute the 1-norm of A. */ anorm = dlansp_("1", uplo, &n, &afac[1], &rwork[1] ); /* Factor the matrix A. */ dpptrf_(uplo, &n, &afac[1], &info); /* Form the inverse of A. */ dcopy_(&npp, &afac[1], &c__1, &a[1], &c__1); dpptri_(uplo, &n, &a[1], &info); /* Compute the 1-norm condition number of A. */ ainvnm = dlansp_("1", uplo, &n, &a[1], &rwork[1]); if (anorm <= 0. || ainvnm <= 0.) { rcondc = 1.; } else { rcondc = 1. / anorm / ainvnm; } } /* Restore the matrix A. */ dcopy_(&npp, &asav[1], &c__1, &a[1], &c__1); /* Form an exact solution and set the right hand side. */ s_copy(srnamc_1.srnamt, "DLARHS", (ftnlen)32, (ftnlen) 6); dlarhs_(path, xtype, uplo, " ", &n, &n, &kl, &ku, nrhs, &a[1], &lda, &xact[1], &lda, &b[1], & lda, iseed, &info); *(unsigned char *)xtype = 'C'; dlacpy_("Full", &n, nrhs, &b[1], &lda, &bsav[1], &lda); if (nofact) { /* --- Test DPPSV --- */ /* Compute the L*L' or U'*U factorization of the */ /* matrix and solve the system. */ dcopy_(&npp, &a[1], &c__1, &afac[1], &c__1); dlacpy_("Full", &n, nrhs, &b[1], &lda, &x[1], & lda); s_copy(srnamc_1.srnamt, "DPPSV ", (ftnlen)32, ( ftnlen)6); dppsv_(uplo, &n, nrhs, &afac[1], &x[1], &lda, & info); /* Check error code from DPPSV . */ if (info != izero) { alaerh_(path, "DPPSV ", &info, &izero, uplo, & n, &n, &c_n1, &c_n1, nrhs, &imat, & nfail, &nerrs, nout); goto L70; } else if (info != 0) { goto L70; } /* Reconstruct matrix from factors and compute */ /* residual. */ dppt01_(uplo, &n, &a[1], &afac[1], &rwork[1], result); /* Compute residual of the computed solution. */ dlacpy_("Full", &n, nrhs, &b[1], &lda, &work[1], & lda); dppt02_(uplo, &n, nrhs, &a[1], &x[1], &lda, &work[ 1], &lda, &rwork[1], &result[1]); /* Check solution from generated exact solution. */ dget04_(&n, nrhs, &x[1], &lda, &xact[1], &lda, & rcondc, &result[2]); nt = 3; /* Print information about the tests that did not */ /* pass the threshold. */ i__4 = nt; for (k = 1; k <= i__4; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { aladhd_(nout, path); } io___49.ciunit = *nout; s_wsfe(&io___49); do_fio(&c__1, "DPPSV ", (ftnlen)6); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&imat, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&result[k - 1], ( ftnlen)sizeof(doublereal)); e_wsfe(); ++nfail; } /* L60: */ } nrun += nt; L70: ; } /* --- Test DPPSVX --- */ if (! prefac && npp > 0) { dlaset_("Full", &npp, &c__1, &c_b60, &c_b60, & afac[1], &npp); } dlaset_("Full", &n, nrhs, &c_b60, &c_b60, &x[1], &lda); if (iequed > 1 && n > 0) { /* Equilibrate the matrix if FACT='F' and */ /* EQUED='Y'. */ dlaqsp_(uplo, &n, &a[1], &s[1], &scond, &amax, equed); } /* Solve the system and compute the condition number */ /* and error bounds using DPPSVX. */ s_copy(srnamc_1.srnamt, "DPPSVX", (ftnlen)32, (ftnlen) 6); dppsvx_(fact, uplo, &n, nrhs, &a[1], &afac[1], equed, &s[1], &b[1], &lda, &x[1], &lda, &rcond, & rwork[1], &rwork[*nrhs + 1], &work[1], &iwork[ 1], &info); /* Check the error code from DPPSVX. */ if (info != izero) { /* Writing concatenation */ i__5[0] = 1, a__1[0] = fact; i__5[1] = 1, a__1[1] = uplo; s_cat(ch__1, a__1, i__5, &c__2, (ftnlen)2); alaerh_(path, "DPPSVX", &info, &izero, ch__1, &n, &n, &c_n1, &c_n1, nrhs, &imat, &nfail, & nerrs, nout); goto L90; } if (info == 0) { if (! prefac) { /* Reconstruct matrix from factors and compute */ /* residual. */ dppt01_(uplo, &n, &a[1], &afac[1], &rwork[(* nrhs << 1) + 1], result); k1 = 1; } else { k1 = 2; } /* Compute residual of the computed solution. */ dlacpy_("Full", &n, nrhs, &bsav[1], &lda, &work[1] , &lda); dppt02_(uplo, &n, nrhs, &asav[1], &x[1], &lda, & work[1], &lda, &rwork[(*nrhs << 1) + 1], & result[1]); /* Check solution from generated exact solution. */ if (nofact || prefac && lsame_(equed, "N")) { dget04_(&n, nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, &result[2]); } else { dget04_(&n, nrhs, &x[1], &lda, &xact[1], &lda, &roldc, &result[2]); } /* Check the error bounds from iterative */ /* refinement. */ dppt05_(uplo, &n, nrhs, &asav[1], &b[1], &lda, &x[ 1], &lda, &xact[1], &lda, &rwork[1], & rwork[*nrhs + 1], &result[3]); } else { k1 = 6; } /* Compare RCOND from DPPSVX with the computed value */ /* in RCONDC. */ result[5] = dget06_(&rcond, &rcondc); /* Print information about the tests that did not pass */ /* the threshold. */ for (k = k1; k <= 6; ++k) { if (result[k - 1] >= *thresh) { if (nfail == 0 && nerrs == 0) { aladhd_(nout, path); } if (prefac) { io___52.ciunit = *nout; s_wsfe(&io___52); do_fio(&c__1, "DPPSVX", (ftnlen)6); do_fio(&c__1, fact, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, equed, (ftnlen)1); do_fio(&c__1, (char *)&imat, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&result[k - 1], ( ftnlen)sizeof(doublereal)); e_wsfe(); } else { io___53.ciunit = *nout; s_wsfe(&io___53); do_fio(&c__1, "DPPSVX", (ftnlen)6); do_fio(&c__1, fact, (ftnlen)1); do_fio(&c__1, uplo, (ftnlen)1); do_fio(&c__1, (char *)&n, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&imat, (ftnlen) sizeof(integer)); do_fio(&c__1, (char *)&k, (ftnlen)sizeof( integer)); do_fio(&c__1, (char *)&result[k - 1], ( ftnlen)sizeof(doublereal)); e_wsfe(); } ++nfail; } /* L80: */ } nrun = nrun + 7 - k1; L90: L100: ; } /* L110: */ } L120: ; } L130: ; } /* L140: */ } /* Print a summary of the results. */ alasvm_(path, nout, &nfail, &nrun, &nerrs); return 0; /* End of DDRVPP */ } /* ddrvpp_ */
/* Subroutine */ int dppt03_(char *uplo, integer *n, doublereal *a, doublereal *ainv, doublereal *work, integer *ldwork, doublereal * rwork, doublereal *rcond, doublereal *resid) { /* System generated locals */ integer work_dim1, work_offset, i__1, i__2; /* Local variables */ integer i__, j, jj; doublereal eps; extern logical lsame_(char *, char *); doublereal anorm; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *), dspmv_(char *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *); extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *), dlansp_(char *, char *, integer *, doublereal *, doublereal *); doublereal ainvnm; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DPPT03 computes the residual for a symmetric packed matrix times its */ /* inverse: */ /* norm( I - A*AINV ) / ( N * norm(A) * norm(AINV) * EPS ), */ /* where EPS is the machine epsilon. */ /* Arguments */ /* ========== */ /* UPLO (input) CHARACTER*1 */ /* Specifies whether the upper or lower triangular part of the */ /* symmetric matrix A is stored: */ /* = 'U': Upper triangular */ /* = 'L': Lower triangular */ /* N (input) INTEGER */ /* The number of rows and columns of the matrix A. N >= 0. */ /* A (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* The original symmetric matrix A, stored as a packed */ /* triangular matrix. */ /* AINV (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */ /* The (symmetric) inverse of the matrix A, stored as a packed */ /* triangular matrix. */ /* WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,N) */ /* LDWORK (input) INTEGER */ /* The leading dimension of the array WORK. LDWORK >= max(1,N). */ /* RWORK (workspace) DOUBLE PRECISION array, dimension (N) */ /* RCOND (output) DOUBLE PRECISION */ /* The reciprocal of the condition number of A, computed as */ /* ( 1/norm(A) ) / norm(AINV). */ /* RESID (output) DOUBLE PRECISION */ /* norm(I - A*AINV) / ( N * norm(A) * norm(AINV) * EPS ) */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Quick exit if N = 0. */ /* Parameter adjustments */ --a; --ainv; work_dim1 = *ldwork; work_offset = 1 + work_dim1; work -= work_offset; --rwork; /* Function Body */ if (*n <= 0) { *rcond = 1.; *resid = 0.; return 0; } /* Exit with RESID = 1/EPS if ANORM = 0 or AINVNM = 0. */ eps = dlamch_("Epsilon"); anorm = dlansp_("1", uplo, n, &a[1], &rwork[1]); ainvnm = dlansp_("1", uplo, n, &ainv[1], &rwork[1]); if (anorm <= 0. || ainvnm == 0.) { *rcond = 0.; *resid = 1. / eps; return 0; } *rcond = 1. / anorm / ainvnm; /* UPLO = 'U': */ /* Copy the leading N-1 x N-1 submatrix of AINV to WORK(1:N,2:N) and */ /* expand it to a full matrix, then multiply by A one column at a */ /* time, moving the result one column to the left. */ if (lsame_(uplo, "U")) { /* Copy AINV */ jj = 1; i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { dcopy_(&j, &ainv[jj], &c__1, &work[(j + 1) * work_dim1 + 1], & c__1); i__2 = j - 1; dcopy_(&i__2, &ainv[jj], &c__1, &work[j + (work_dim1 << 1)], ldwork); jj += j; /* L10: */ } jj = (*n - 1) * *n / 2 + 1; i__1 = *n - 1; dcopy_(&i__1, &ainv[jj], &c__1, &work[*n + (work_dim1 << 1)], ldwork); /* Multiply by A */ i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { dspmv_("Upper", n, &c_b13, &a[1], &work[(j + 1) * work_dim1 + 1], &c__1, &c_b15, &work[j * work_dim1 + 1], &c__1) ; /* L20: */ } dspmv_("Upper", n, &c_b13, &a[1], &ainv[jj], &c__1, &c_b15, &work[*n * work_dim1 + 1], &c__1); /* UPLO = 'L': */ /* Copy the trailing N-1 x N-1 submatrix of AINV to WORK(1:N,1:N-1) */ /* and multiply by A, moving each column to the right. */ } else { /* Copy AINV */ i__1 = *n - 1; dcopy_(&i__1, &ainv[2], &c__1, &work[work_dim1 + 1], ldwork); jj = *n + 1; i__1 = *n; for (j = 2; j <= i__1; ++j) { i__2 = *n - j + 1; dcopy_(&i__2, &ainv[jj], &c__1, &work[j + (j - 1) * work_dim1], & c__1); i__2 = *n - j; dcopy_(&i__2, &ainv[jj + 1], &c__1, &work[j + j * work_dim1], ldwork); jj = jj + *n - j + 1; /* L30: */ } /* Multiply by A */ for (j = *n; j >= 2; --j) { dspmv_("Lower", n, &c_b13, &a[1], &work[(j - 1) * work_dim1 + 1], &c__1, &c_b15, &work[j * work_dim1 + 1], &c__1) ; /* L40: */ } dspmv_("Lower", n, &c_b13, &a[1], &ainv[1], &c__1, &c_b15, &work[ work_dim1 + 1], &c__1); } /* Add the identity matrix to WORK . */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { work[i__ + i__ * work_dim1] += 1.; /* L50: */ } /* Compute norm(I - A*AINV) / (N * norm(A) * norm(AINV) * EPS) */ *resid = dlange_("1", n, n, &work[work_offset], ldwork, &rwork[1]); *resid = *resid * *rcond / eps / (doublereal) (*n); return 0; /* End of DPPT03 */ } /* dppt03_ */