/* Subroutine */ int ctimhp_(char *line, integer *nn, integer *nval, integer * nns, integer *nsval, integer *la, real *timmin, complex *a, complex * b, complex *work, integer *iwork, real *reslts, integer *ldr1, integer *ldr2, integer *ldr3, integer *nout, ftnlen line_len) { /* Initialized data */ static char uplos[1*2] = "U" "L"; static char subnam[6*3] = "CHPTRF" "CHPTRS" "CHPTRI"; /* Format strings */ static char fmt_9999[] = "(1x,a6,\002 timing run not attempted\002,/)"; static char fmt_9998[] = "(/\002 *** Speed of \002,a6,\002 in megaflops " "***\002,/)"; static char fmt_9997[] = "(5x,a6,\002 with UPLO = '\002,a1,\002'\002,/)"; /* System generated locals */ integer reslts_dim1, reslts_dim2, reslts_dim3, reslts_offset, i__1, i__2; /* Builtin functions Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ static integer info; static char path[3]; static real time; static integer isub, nrhs; static char uplo[1]; static integer i__, n; static char cname[6]; static integer laval[1]; extern logical lsame_(char *, char *); extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *); extern doublereal sopla_(char *, integer *, integer *, integer *, integer *, integer *); static integer iuplo; static real s1, s2; static integer ic, in; extern /* Subroutine */ int atimck_(integer *, char *, integer *, integer *, integer *, integer *, integer *, integer *, ftnlen); extern doublereal second_(void); extern /* Subroutine */ int ctimmg_(integer *, integer *, integer *, complex *, integer *, integer *, integer *), atimin_(char *, char *, integer *, char *, logical *, integer *, integer *, ftnlen, ftnlen, ftnlen), chptrf_(char *, integer *, complex *, integer *, integer *), chptri_(char *, integer *, complex *, integer *, complex *, integer *); extern doublereal smflop_(real *, real *, integer *); static real untime; static logical timsub[3]; extern /* Subroutine */ int chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *), sprtbl_( char *, char *, integer *, integer *, integer *, integer *, integer *, real *, integer *, integer *, integer *, ftnlen, ftnlen); static integer lda, ldb, icl, mat; static real ops; /* Fortran I/O blocks */ static cilist io___8 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___26 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___27 = { 0, 0, 0, fmt_9997, 0 }; #define subnam_ref(a_0,a_1) &subnam[(a_1)*6 + a_0 - 6] #define reslts_ref(a_1,a_2,a_3,a_4) reslts[(((a_4)*reslts_dim3 + (a_3))*\ reslts_dim2 + (a_2))*reslts_dim1 + a_1] /* -- LAPACK timing routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University March 31, 1993 Purpose ======= CTIMHP times CHPTRF, -TRS, and -TRI. Arguments ========= LINE (input) CHARACTER*80 The input line that requested this routine. The first six characters contain either the name of a subroutine or a generic path name. The remaining characters may be used to specify the individual routines to be timed. See ATIMIN for a full description of the format of the input line. 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 size 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. LA (input) INTEGER The size of the arrays A, B, and C. TIMMIN (input) REAL The minimum time a subroutine will be timed. A (workspace) COMPLEX array, dimension (LA) B (workspace) COMPLEX array, dimension (LA) WORK (workspace) COMPLEX array, dimension (NMAX) IWORK (workspace) INTEGER array, dimension (NMAX) where NMAX is the maximum value of N permitted. RESLTS (output) REAL array, dimension (LDR1,LDR2,LDR3,NSUBS) The timing results for each subroutine over the relevant values of N. LDR1 (input) INTEGER The first dimension of RESLTS. LDR1 >= max(4,NNB). LDR2 (input) INTEGER The second dimension of RESLTS. LDR2 >= max(1,NN). LDR3 (input) INTEGER The third dimension of RESLTS. LDR3 >= 2. NOUT (input) INTEGER The unit number for output. ===================================================================== Parameter adjustments */ --nval; --nsval; --a; --b; --work; --iwork; reslts_dim1 = *ldr1; reslts_dim2 = *ldr2; reslts_dim3 = *ldr3; reslts_offset = 1 + reslts_dim1 * (1 + reslts_dim2 * (1 + reslts_dim3 * 1) ); reslts -= reslts_offset; /* Function Body Extract the timing request from the input line. */ s_copy(path, "Complex precision", (ftnlen)1, (ftnlen)17); s_copy(path + 1, "HP", (ftnlen)2, (ftnlen)2); atimin_(path, line, &c__3, subnam, timsub, nout, &info, (ftnlen)3, ( ftnlen)80, (ftnlen)6); if (info != 0) { goto L120; } /* Check that N*(N+1)/2 <= LA for the input values. */ s_copy(cname, line, (ftnlen)6, (ftnlen)6); laval[0] = *la; atimck_(&c__4, cname, nn, &nval[1], &c__1, laval, nout, &info, (ftnlen)6); if (info > 0) { io___8.ciunit = *nout; s_wsfe(&io___8); do_fio(&c__1, cname, (ftnlen)6); e_wsfe(); goto L120; } /* Do first for UPLO = 'U', then for UPLO = 'L' */ for (iuplo = 1; iuplo <= 2; ++iuplo) { *(unsigned char *)uplo = *(unsigned char *)&uplos[iuplo - 1]; if (lsame_(uplo, "U")) { mat = 7; } else { mat = -7; } /* Do for each value of N in NVAL. */ i__1 = *nn; for (in = 1; in <= i__1; ++in) { n = nval[in]; lda = n * (n + 1) / 2; /* Time CHPTRF */ if (timsub[0]) { ctimmg_(&mat, &n, &n, &a[1], &lda, &c__0, &c__0); ic = 0; s1 = second_(); L10: chptrf_(uplo, &n, &a[1], &iwork[1], &info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { ctimmg_(&mat, &n, &n, &a[1], &lda, &c__0, &c__0); goto L10; } /* Subtract the time used in CTIMMG. */ icl = 1; s1 = second_(); L20: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { ctimmg_(&mat, &n, &n, &a[1], &lda, &c__0, &c__0); goto L20; } time = (time - untime) / (real) ic; ops = sopla_("CHPTRF", &n, &n, &c__0, &c__0, &c__0) ; reslts_ref(1, in, iuplo, 1) = smflop_(&ops, &time, &info); } else { ic = 0; ctimmg_(&mat, &n, &n, &a[1], &lda, &c__0, &c__0); } /* Generate another matrix and factor it using CHPTRF so that the factored form can be used in timing the other routines. */ if (ic != 1) { chptrf_(uplo, &n, &a[1], &iwork[1], &info); } /* Time CHPTRI */ if (timsub[2]) { ccopy_(&lda, &a[1], &c__1, &b[1], &c__1); ic = 0; s1 = second_(); L30: chptri_(uplo, &n, &b[1], &iwork[1], &work[1], &info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { ccopy_(&lda, &a[1], &c__1, &b[1], &c__1); goto L30; } /* Subtract the time used in CCOPY. */ icl = 1; s1 = second_(); L40: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { ccopy_(&lda, &a[1], &c__1, &b[1], &c__1); goto L40; } time = (time - untime) / (real) ic; ops = sopla_("CHPTRI", &n, &n, &c__0, &c__0, &c__0) ; reslts_ref(1, in, iuplo, 3) = smflop_(&ops, &time, &info); } /* Time CHPTRS */ if (timsub[1]) { i__2 = *nns; for (i__ = 1; i__ <= i__2; ++i__) { nrhs = nsval[i__]; ldb = n; if (ldb % 2 == 0) { ++ldb; } ctimmg_(&c__0, &n, &nrhs, &b[1], &ldb, &c__0, &c__0); ic = 0; s1 = second_(); L50: chptrs_(uplo, &n, &nrhs, &a[1], &iwork[1], &b[1], &ldb, & info); s2 = second_(); time = s2 - s1; ++ic; if (time < *timmin) { ctimmg_(&c__0, &n, &nrhs, &b[1], &ldb, &c__0, &c__0); goto L50; } /* Subtract the time used in CTIMMG. */ icl = 1; s1 = second_(); L60: s2 = second_(); untime = s2 - s1; ++icl; if (icl <= ic) { ctimmg_(&c__0, &n, &nrhs, &b[1], &ldb, &c__0, &c__0); goto L60; } time = (time - untime) / (real) ic; ops = sopla_("CHPTRS", &n, &nrhs, &c__0, &c__0, &c__0); reslts_ref(i__, in, iuplo, 2) = smflop_(&ops, &time, & info); /* L70: */ } } /* L80: */ } /* L90: */ } /* Print tables of results for each timed routine. */ for (isub = 1; isub <= 3; ++isub) { if (! timsub[isub - 1]) { goto L110; } io___26.ciunit = *nout; s_wsfe(&io___26); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); e_wsfe(); for (iuplo = 1; iuplo <= 2; ++iuplo) { io___27.ciunit = *nout; s_wsfe(&io___27); do_fio(&c__1, subnam_ref(0, isub), (ftnlen)6); do_fio(&c__1, uplos + (iuplo - 1), (ftnlen)1); e_wsfe(); if (isub == 1) { sprtbl_(" ", "N", &c__1, laval, nn, &nval[1], &c__1, & reslts_ref(1, 1, iuplo, 1), ldr1, ldr2, nout, (ftnlen) 1, (ftnlen)1); } else if (isub == 2) { sprtbl_("NRHS", "N", nns, &nsval[1], nn, &nval[1], &c__1, & reslts_ref(1, 1, iuplo, 2), ldr1, ldr2, nout, (ftnlen) 4, (ftnlen)1); } else if (isub == 3) { sprtbl_(" ", "N", &c__1, laval, nn, &nval[1], &c__1, & reslts_ref(1, 1, iuplo, 3), ldr1, ldr2, nout, (ftnlen) 1, (ftnlen)1); } /* L100: */ } L110: ; } L120: return 0; /* End of CTIMHP */ } /* ctimhp_ */
/* Subroutine */ int chprfs_(char *uplo, integer *n, integer *nrhs, complex * ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork, integer *info) { /* System generated locals */ integer b_dim1, b_offset, x_dim1, x_offset, i__1, i__2, i__3, i__4, i__5; real r__1, r__2, r__3, r__4; complex q__1; /* Builtin functions */ double r_imag(complex *); /* Local variables */ integer i__, j, k; real s; integer ik, kk; real xk; integer nz; real eps; integer kase; real safe1, safe2; extern logical lsame_(char *, char *); integer isave[3]; extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *), chpmv_(char *, integer *, complex *, complex *, complex *, integer *, complex *, complex *, integer *), caxpy_(integer *, complex *, complex *, integer *, complex *, integer *); integer count; logical upper; extern /* Subroutine */ int clacn2_(integer *, complex *, complex *, real *, integer *, integer *); extern doublereal slamch_(char *); real safmin; extern /* Subroutine */ int xerbla_(char *, integer *), chptrs_( char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); real lstres; /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* Modified to call CLACN2 in place of CLACON, 10 Feb 03, SJH. */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHPRFS improves the computed solution to a system of linear */ /* equations when the coefficient matrix is Hermitian indefinite */ /* and packed, and provides error bounds and backward error estimates */ /* for the solution. */ /* Arguments */ /* ========= */ /* 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. */ /* 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) COMPLEX array, dimension (N*(N+1)/2) */ /* The upper or lower triangle of the Hermitian 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. */ /* AFP (input) COMPLEX array, dimension (N*(N+1)/2) */ /* The factored form of the matrix A. AFP contains the block */ /* diagonal matrix D and the multipliers used to obtain the */ /* factor U or L from the factorization A = U*D*U**H or */ /* A = L*D*L**H as computed by CHPTRF, stored as a packed */ /* triangular matrix. */ /* IPIV (input) INTEGER array, dimension (N) */ /* Details of the interchanges and the block structure of D */ /* as determined by CHPTRF. */ /* B (input) COMPLEX array, dimension (LDB,NRHS) */ /* The right hand side matrix B. */ /* LDB (input) INTEGER */ /* The leading dimension of the array B. LDB >= max(1,N). */ /* X (input/output) COMPLEX array, dimension (LDX,NRHS) */ /* On entry, the solution matrix X, as computed by CHPTRS. */ /* On exit, the improved solution matrix X. */ /* LDX (input) INTEGER */ /* The leading dimension of the array X. LDX >= max(1,N). */ /* FERR (output) REAL 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) REAL 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) COMPLEX array, dimension (2*N) */ /* RWORK (workspace) REAL array, dimension (N) */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* Internal Parameters */ /* =================== */ /* ITMAX is the maximum number of steps of iterative refinement. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Statement Functions .. */ /* .. */ /* .. Statement Function definitions .. */ /* .. */ /* .. 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; --rwork; /* Function Body */ *info = 0; upper = lsame_(uplo, "U"); if (! upper && ! lsame_(uplo, "L")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*ldb < max(1,*n)) { *info = -8; } else if (*ldx < max(1,*n)) { *info = -10; } if (*info != 0) { i__1 = -(*info); xerbla_("CHPRFS", &i__1); return 0; } /* Quick return if possible */ if (*n == 0 || *nrhs == 0) { i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { ferr[j] = 0.f; berr[j] = 0.f; /* L10: */ } return 0; } /* NZ = maximum number of nonzero elements in each row of A, plus 1 */ nz = *n + 1; eps = slamch_("Epsilon"); safmin = slamch_("Safe minimum"); safe1 = nz * safmin; safe2 = safe1 / eps; /* Do for each right hand side */ i__1 = *nrhs; for (j = 1; j <= i__1; ++j) { count = 1; lstres = 3.f; L20: /* Loop until stopping criterion is satisfied. */ /* Compute residual R = B - A * X */ ccopy_(n, &b[j * b_dim1 + 1], &c__1, &work[1], &c__1); q__1.r = -1.f, q__1.i = -0.f; chpmv_(uplo, n, &q__1, &ap[1], &x[j * x_dim1 + 1], &c__1, &c_b1, & work[1], &c__1); /* Compute componentwise relative backward error from formula */ /* max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) ) */ /* where abs(Z) is the componentwise absolute value of the matrix */ /* or vector Z. If the i-th component of the denominator is less */ /* than SAFE2, then SAFE1 is added to the i-th components of the */ /* numerator and denominator before dividing. */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * b_dim1; rwork[i__] = (r__1 = b[i__3].r, dabs(r__1)) + (r__2 = r_imag(&b[ i__ + j * b_dim1]), dabs(r__2)); /* L30: */ } /* Compute abs(A)*abs(X) + abs(B). */ kk = 1; if (upper) { i__2 = *n; for (k = 1; k <= i__2; ++k) { s = 0.f; i__3 = k + j * x_dim1; xk = (r__1 = x[i__3].r, dabs(r__1)) + (r__2 = r_imag(&x[k + j * x_dim1]), dabs(r__2)); ik = kk; i__3 = k - 1; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = ik; rwork[i__] += ((r__1 = ap[i__4].r, dabs(r__1)) + (r__2 = r_imag(&ap[ik]), dabs(r__2))) * xk; i__4 = ik; i__5 = i__ + j * x_dim1; s += ((r__1 = ap[i__4].r, dabs(r__1)) + (r__2 = r_imag(& ap[ik]), dabs(r__2))) * ((r__3 = x[i__5].r, dabs( r__3)) + (r__4 = r_imag(&x[i__ + j * x_dim1]), dabs(r__4))); ++ik; /* L40: */ } i__3 = kk + k - 1; rwork[k] = rwork[k] + (r__1 = ap[i__3].r, dabs(r__1)) * xk + s; kk += k; /* L50: */ } } else { i__2 = *n; for (k = 1; k <= i__2; ++k) { s = 0.f; i__3 = k + j * x_dim1; xk = (r__1 = x[i__3].r, dabs(r__1)) + (r__2 = r_imag(&x[k + j * x_dim1]), dabs(r__2)); i__3 = kk; rwork[k] += (r__1 = ap[i__3].r, dabs(r__1)) * xk; ik = kk + 1; i__3 = *n; for (i__ = k + 1; i__ <= i__3; ++i__) { i__4 = ik; rwork[i__] += ((r__1 = ap[i__4].r, dabs(r__1)) + (r__2 = r_imag(&ap[ik]), dabs(r__2))) * xk; i__4 = ik; i__5 = i__ + j * x_dim1; s += ((r__1 = ap[i__4].r, dabs(r__1)) + (r__2 = r_imag(& ap[ik]), dabs(r__2))) * ((r__3 = x[i__5].r, dabs( r__3)) + (r__4 = r_imag(&x[i__ + j * x_dim1]), dabs(r__4))); ++ik; /* L60: */ } rwork[k] += s; kk += *n - k + 1; /* L70: */ } } s = 0.f; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { if (rwork[i__] > safe2) { /* Computing MAX */ i__3 = i__; r__3 = s, r__4 = ((r__1 = work[i__3].r, dabs(r__1)) + (r__2 = r_imag(&work[i__]), dabs(r__2))) / rwork[i__]; s = dmax(r__3,r__4); } else { /* Computing MAX */ i__3 = i__; r__3 = s, r__4 = ((r__1 = work[i__3].r, dabs(r__1)) + (r__2 = r_imag(&work[i__]), dabs(r__2)) + safe1) / (rwork[i__] + safe1); s = dmax(r__3,r__4); } /* L80: */ } berr[j] = s; /* Test stopping criterion. Continue iterating if */ /* 1) The residual BERR(J) is larger than machine epsilon, and */ /* 2) BERR(J) decreased by at least a factor of 2 during the */ /* last iteration, and */ /* 3) At most ITMAX iterations tried. */ if (berr[j] > eps && berr[j] * 2.f <= lstres && count <= 5) { /* Update solution and try again. */ chptrs_(uplo, n, &c__1, &afp[1], &ipiv[1], &work[1], n, info); caxpy_(n, &c_b1, &work[1], &c__1, &x[j * x_dim1 + 1], &c__1); lstres = berr[j]; ++count; goto L20; } /* Bound error from formula */ /* norm(X - XTRUE) / norm(X) .le. FERR = */ /* norm( abs(inv(A))* */ /* ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X) */ /* where */ /* norm(Z) is the magnitude of the largest component of Z */ /* inv(A) is the inverse of A */ /* abs(Z) is the componentwise absolute value of the matrix or */ /* vector Z */ /* NZ is the maximum number of nonzeros in any row of A, plus 1 */ /* EPS is machine epsilon */ /* The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B)) */ /* is incremented by SAFE1 if the i-th component of */ /* abs(A)*abs(X) + abs(B) is less than SAFE2. */ /* Use CLACN2 to estimate the infinity-norm of the matrix */ /* inv(A) * diag(W), */ /* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { if (rwork[i__] > safe2) { i__3 = i__; rwork[i__] = (r__1 = work[i__3].r, dabs(r__1)) + (r__2 = r_imag(&work[i__]), dabs(r__2)) + nz * eps * rwork[ i__]; } else { i__3 = i__; rwork[i__] = (r__1 = work[i__3].r, dabs(r__1)) + (r__2 = r_imag(&work[i__]), dabs(r__2)) + nz * eps * rwork[ i__] + safe1; } /* L90: */ } kase = 0; L100: clacn2_(n, &work[*n + 1], &work[1], &ferr[j], &kase, isave); if (kase != 0) { if (kase == 1) { /* Multiply by diag(W)*inv(A'). */ chptrs_(uplo, n, &c__1, &afp[1], &ipiv[1], &work[1], n, info); i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = i__; q__1.r = rwork[i__4] * work[i__5].r, q__1.i = rwork[i__4] * work[i__5].i; work[i__3].r = q__1.r, work[i__3].i = q__1.i; /* L110: */ } } else if (kase == 2) { /* Multiply by inv(A)*diag(W). */ i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__; i__4 = i__; i__5 = i__; q__1.r = rwork[i__4] * work[i__5].r, q__1.i = rwork[i__4] * work[i__5].i; work[i__3].r = q__1.r, work[i__3].i = q__1.i; /* L120: */ } chptrs_(uplo, n, &c__1, &afp[1], &ipiv[1], &work[1], n, info); } goto L100; } /* Normalize error. */ lstres = 0.f; i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { /* Computing MAX */ i__3 = i__ + j * x_dim1; r__3 = lstres, r__4 = (r__1 = x[i__3].r, dabs(r__1)) + (r__2 = r_imag(&x[i__ + j * x_dim1]), dabs(r__2)); lstres = dmax(r__3,r__4); /* L130: */ } if (lstres != 0.f) { ferr[j] /= lstres; } /* L140: */ } return 0; /* End of CHPRFS */ } /* chprfs_ */
/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer * ipiv, real *anorm, real *rcond, complex *work, integer *info) { /* -- LAPACK routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University March 31, 1993 Purpose ======= CHPCON estimates the reciprocal of the condition number of a complex Hermitian packed matrix A using the factorization A = U*D*U**H or A = L*D*L**H computed by CHPTRF. An estimate is obtained for norm(inv(A)), and the reciprocal of the condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). Arguments ========= UPLO (input) CHARACTER*1 Specifies whether the details of the factorization are stored as an upper or lower triangular matrix. = 'U': Upper triangular, form is A = U*D*U**H; = 'L': Lower triangular, form is A = L*D*L**H. N (input) INTEGER The order of the matrix A. N >= 0. AP (input) COMPLEX array, dimension (N*(N+1)/2) The block diagonal matrix D and the multipliers used to obtain the factor U or L as computed by CHPTRF, stored as a packed triangular matrix. IPIV (input) INTEGER array, dimension (N) Details of the interchanges and the block structure of D as determined by CHPTRF. ANORM (input) REAL The 1-norm of the original matrix A. RCOND (output) REAL The reciprocal of the condition number of the matrix A, computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an estimate of the 1-norm of inv(A) computed in this routine. WORK (workspace) COMPLEX array, dimension (2*N) INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value ===================================================================== Test the input parameters. Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; /* System generated locals */ integer i__1, i__2; /* Local variables */ static integer kase, i__; extern logical lsame_(char *, char *); static logical upper; static integer ip; extern /* Subroutine */ int clacon_(integer *, complex *, complex *, real *, integer *), xerbla_(char *, integer *); static real ainvnm; extern /* Subroutine */ int chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); --work; --ipiv; --ap; /* Function Body */ *info = 0; upper = lsame_(uplo, "U"); if (! upper && ! lsame_(uplo, "L")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*anorm < 0.f) { *info = -5; } if (*info != 0) { i__1 = -(*info); xerbla_("CHPCON", &i__1); return 0; } /* Quick return if possible */ *rcond = 0.f; if (*n == 0) { *rcond = 1.f; return 0; } else if (*anorm <= 0.f) { return 0; } /* Check that the diagonal matrix D is nonsingular. */ if (upper) { /* Upper triangular storage: examine D from bottom to top */ ip = *n * (*n + 1) / 2; for (i__ = *n; i__ >= 1; --i__) { i__1 = ip; if (ipiv[i__] > 0 && (ap[i__1].r == 0.f && ap[i__1].i == 0.f)) { return 0; } ip -= i__; /* L10: */ } } else { /* Lower triangular storage: examine D from top to bottom. */ ip = 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = ip; if (ipiv[i__] > 0 && (ap[i__2].r == 0.f && ap[i__2].i == 0.f)) { return 0; } ip = ip + *n - i__ + 1; /* L20: */ } } /* Estimate the 1-norm of the inverse. */ kase = 0; L30: clacon_(n, &work[*n + 1], &work[1], &ainvnm, &kase); if (kase != 0) { /* Multiply by inv(L*D*L') or inv(U*D*U'). */ chptrs_(uplo, n, &c__1, &ap[1], &ipiv[1], &work[1], n, info); goto L30; } /* Compute the estimate of the reciprocal condition number. */ if (ainvnm != 0.f) { *rcond = 1.f / ainvnm / *anorm; } return 0; /* End of CHPCON */ } /* chpcon_ */
/* Subroutine */ int cchkhp_(logical *dotype, integer *nn, integer *nval, integer *nns, integer *nsval, real *thresh, logical *tsterr, integer * nmax, complex *a, complex *afac, complex *ainv, complex *b, complex * x, complex *xact, complex *work, real *rwork, integer *iwork, integer *nout) { /* Initialized data */ static integer iseedy[4] = { 1988,1989,1990,1991 }; static char uplos[1*2] = "U" "L"; /* 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, i__4, i__5; /* 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__, j, k, n, i1, i2, in, kl, ku, nt, 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 *), cget04_( integer *, integer *, complex *, integer *, complex *, integer *, real *, real *); integer nfail, iseed[4]; extern /* Subroutine */ int chpt01_(char *, integer *, complex *, complex *, integer *, complex *, integer *, real *, real *); extern logical lsame_(char *, char *); real rcond; integer nimat; extern doublereal sget06_(real *, real *); extern /* Subroutine */ int cppt02_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, real *, real *), cppt03_(char *, integer *, complex *, complex *, complex *, integer *, real *, real *, real *); real anorm; extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *), cppt05_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *, real *, real *, real *); integer iuplo, izero, nerrs; logical zerot; char xtype[1]; extern /* Subroutine */ int clatb4_(char *, integer *, integer *, integer *, char *, integer *, integer *, real *, integer *, real *, char * ), alaerh_(char *, char *, integer *, integer *, char *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *, integer *), claipd_(integer *, complex *, integer *, integer *); extern doublereal clanhp_(char *, char *, integer *, complex *, real *); real rcondc; extern /* Subroutine */ int chpcon_(char *, integer *, complex *, integer *, real *, real *, complex *, integer *); char packit[1]; extern /* Subroutine */ int clacpy_(char *, integer *, integer *, complex *, integer *, complex *, integer *), clarhs_(char *, char *, char *, char *, integer *, integer *, integer *, integer *, integer *, complex *, integer *, complex *, integer *, complex *, integer *, integer *, integer *), alasum_(char *, integer *, integer *, integer *, integer *); real cndnum; extern /* Subroutine */ int chprfs_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *, real *, real *, complex *, real *, integer *), chptrf_( char *, integer *, complex *, integer *, integer *), clatms_(integer *, integer *, char *, integer *, char *, real *, integer *, real *, real *, integer *, integer *, char *, complex * , integer *, complex *, integer *), chptri_(char *, integer *, complex *, integer *, complex *, integer *); logical trfcon; extern /* Subroutine */ int chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *), cerrsy_( char *, integer *); real result[8]; /* Fortran I/O blocks */ static cilist io___38 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___41 = { 0, 0, 0, fmt_9998, 0 }; static cilist io___43 = { 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 */ /* ======= */ /* CCHKHP tests CHPTRF, -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) REAL */ /* 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) COMPLEX array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AFAC (workspace) COMPLEX array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* AINV (workspace) COMPLEX array, dimension */ /* (NMAX*(NMAX+1)/2) */ /* B (workspace) COMPLEX array, dimension (NMAX*NSMAX) */ /* where NSMAX is the largest entry in NSVAL. */ /* X (workspace) COMPLEX array, dimension (NMAX*NSMAX) */ /* XACT (workspace) COMPLEX array, dimension (NMAX*NSMAX) */ /* WORK (workspace) COMPLEX array, dimension */ /* (NMAX*max(2,NSMAX)) */ /* RWORK (workspace) REAL array, */ /* dimension (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 .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. 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, "Complex precision", (ftnlen)1, (ftnlen)17); s_copy(path + 1, "HP", (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) { cerrsy_(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 = 10; if (n <= 0) { nimat = 1; } izero = 0; i__2 = nimat; for (imat = 1; imat <= i__2; ++imat) { /* Do the tests only if DOTYPE( IMAT ) is true. */ if (! dotype[imat]) { goto L160; } /* 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 L160; } /* Do first for UPLO = 'U', then for UPLO = 'L' */ for (iuplo = 1; iuplo <= 2; ++iuplo) { *(unsigned char *)uplo = *(unsigned char *)&uplos[iuplo - 1]; if (lsame_(uplo, "U")) { *(unsigned char *)packit = 'C'; } else { *(unsigned char *)packit = 'R'; } /* Set up parameters with CLATB4 and generate a test matrix */ /* with CLATMS. */ clatb4_(path, &imat, &n, &n, type__, &kl, &ku, &anorm, &mode, &cndnum, dist); s_copy(srnamc_1.srnamt, "CLATMS", (ftnlen)6, (ftnlen)6); clatms_(&n, &n, dist, iseed, type__, &rwork[1], &mode, & cndnum, &anorm, &kl, &ku, packit, &a[1], &lda, &work[ 1], &info); /* Check error code from CLATMS. */ if (info != 0) { alaerh_(path, "CLATMS", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); goto L150; } /* 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__) { i__4 = ioff + i__; a[i__4].r = 0.f, a[i__4].i = 0.f; /* L20: */ } ioff += izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { i__4 = ioff; a[i__4].r = 0.f, a[i__4].i = 0.f; ioff += i__; /* L30: */ } } else { ioff = izero; i__3 = izero - 1; for (i__ = 1; i__ <= i__3; ++i__) { i__4 = ioff; a[i__4].r = 0.f, a[i__4].i = 0.f; ioff = ioff + n - i__; /* L40: */ } ioff -= izero; i__3 = n; for (i__ = izero; i__ <= i__3; ++i__) { i__4 = ioff + i__; a[i__4].r = 0.f, a[i__4].i = 0.f; /* 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__) { i__5 = ioff + i__; a[i__5].r = 0.f, a[i__5].i = 0.f; /* 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__) { i__5 = ioff + i__; a[i__5].r = 0.f, a[i__5].i = 0.f; /* L80: */ } ioff = ioff + n - j; /* L90: */ } } } } else { izero = 0; } /* Set the imaginary part of the diagonals. */ if (iuplo == 1) { claipd_(&n, &a[1], &c__2, &c__1); } else { claipd_(&n, &a[1], &n, &c_n1); } /* Compute the L*D*L' or U*D*U' factorization of the matrix. */ npp = n * (n + 1) / 2; ccopy_(&npp, &a[1], &c__1, &afac[1], &c__1); s_copy(srnamc_1.srnamt, "CHPTRF", (ftnlen)6, (ftnlen)6); chptrf_(uplo, &n, &afac[1], &iwork[1], &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 CHPTRF. */ if (info != k) { alaerh_(path, "CHPTRF", &info, &k, uplo, &n, &n, &c_n1, & c_n1, &c_n1, &imat, &nfail, &nerrs, nout); } if (info != 0) { trfcon = TRUE_; } else { trfcon = FALSE_; } /* + TEST 1 */ /* Reconstruct matrix from factors and compute residual. */ chpt01_(uplo, &n, &a[1], &afac[1], &iwork[1], &ainv[1], &lda, &rwork[1], result); nt = 1; /* + TEST 2 */ /* Form the inverse and compute the residual. */ if (! trfcon) { ccopy_(&npp, &afac[1], &c__1, &ainv[1], &c__1); s_copy(srnamc_1.srnamt, "CHPTRI", (ftnlen)6, (ftnlen)6); chptri_(uplo, &n, &ainv[1], &iwork[1], &work[1], &info); /* Check error code from CHPTRI. */ if (info != 0) { alaerh_(path, "CHPTRI", &info, &c__0, uplo, &n, &n, & c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); } cppt03_(uplo, &n, &a[1], &ainv[1], &work[1], &lda, &rwork[ 1], &rcondc, &result[1]); nt = 2; } /* 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) { alahd_(nout, path); } io___38.ciunit = *nout; s_wsfe(&io___38); 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( real)); e_wsfe(); ++nfail; } /* L110: */ } nrun += nt; /* Do only the condition estimate if INFO is not 0. */ if (trfcon) { rcondc = 0.f; goto L140; } 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, "CLARHS", (ftnlen)6, (ftnlen)6); clarhs_(path, xtype, uplo, " ", &n, &n, &kl, &ku, &nrhs, & a[1], &lda, &xact[1], &lda, &b[1], &lda, iseed, & info); *(unsigned char *)xtype = 'C'; clacpy_("Full", &n, &nrhs, &b[1], &lda, &x[1], &lda); s_copy(srnamc_1.srnamt, "CHPTRS", (ftnlen)6, (ftnlen)6); chptrs_(uplo, &n, &nrhs, &afac[1], &iwork[1], &x[1], &lda, &info); /* Check error code from CHPTRS. */ if (info != 0) { alaerh_(path, "CHPTRS", &info, &c__0, uplo, &n, &n, & c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, nout); } clacpy_("Full", &n, &nrhs, &b[1], &lda, &work[1], &lda); cppt02_(uplo, &n, &nrhs, &a[1], &x[1], &lda, &work[1], & lda, &rwork[1], &result[2]); /* + TEST 4 */ /* Check solution from generated exact solution. */ cget04_(&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, "CHPRFS", (ftnlen)6, (ftnlen)6); chprfs_(uplo, &n, &nrhs, &a[1], &afac[1], &iwork[1], &b[1] , &lda, &x[1], &lda, &rwork[1], &rwork[nrhs + 1], &work[1], &rwork[(nrhs << 1) + 1], &info); /* Check error code from CHPRFS. */ if (info != 0) { alaerh_(path, "CHPRFS", &info, &c__0, uplo, &n, &n, & c_n1, &c_n1, &nrhs, &imat, &nfail, &nerrs, nout); } cget04_(&n, &nrhs, &x[1], &lda, &xact[1], &lda, &rcondc, & result[4]); cppt05_(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___41.ciunit = *nout; s_wsfe(&io___41); 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(real)); e_wsfe(); ++nfail; } /* L120: */ } nrun += 5; /* L130: */ } /* + TEST 8 */ /* Get an estimate of RCOND = 1/CNDNUM. */ L140: anorm = clanhp_("1", uplo, &n, &a[1], &rwork[1]); s_copy(srnamc_1.srnamt, "CHPCON", (ftnlen)6, (ftnlen)6); chpcon_(uplo, &n, &afac[1], &iwork[1], &anorm, &rcond, &work[ 1], &info); /* Check error code from CHPCON. */ if (info != 0) { alaerh_(path, "CHPCON", &info, &c__0, uplo, &n, &n, &c_n1, &c_n1, &c_n1, &imat, &nfail, &nerrs, nout); } result[7] = sget06_(&rcond, &rcondc); /* Print the test ratio if it is .GE. THRESH. */ if (result[7] >= *thresh) { if (nfail == 0 && nerrs == 0) { alahd_(nout, path); } io___43.ciunit = *nout; s_wsfe(&io___43); 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(real)); e_wsfe(); ++nfail; } ++nrun; L150: ; } L160: ; } /* L170: */ } /* Print a summary of the results. */ alasum_(path, nout, &nfail, &nrun, &nerrs); return 0; /* End of CCHKHP */ } /* cchkhp_ */
/* Subroutine */ int chpsvx_(char *fact, char *uplo, integer *n, integer * nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer * ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, complex *work, real *rwork, integer *info) { /* System generated locals */ integer b_dim1, b_offset, x_dim1, x_offset, i__1; /* Local variables */ extern logical lsame_(char *, char *); real anorm; extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *); extern doublereal clanhp_(char *, char *, integer *, complex *, real *), slamch_(char *); logical nofact; extern /* Subroutine */ int chpcon_(char *, integer *, complex *, integer *, real *, real *, complex *, integer *), clacpy_(char *, integer *, integer *, complex *, integer *, complex *, integer *), xerbla_(char *, integer *), chprfs_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *, real *, real *, complex *, real * , integer *), chptrf_(char *, integer *, complex *, integer *, integer *), chptrs_(char *, integer *, integer *, complex *, integer *, complex *, 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 */ /* ======= */ /* CHPSVX uses the diagonal pivoting factorization A = U*D*U**H or */ /* A = L*D*L**H to compute the solution to a complex system of linear */ /* equations A * X = B, where A is an N-by-N Hermitian 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**H, if UPLO = 'U', or */ /* A = L * D * L**H, if UPLO = 'L', */ /* where U (or L) is a product of permutation and unit upper (lower) */ /* triangular matrices and D is Hermitian 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. 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) COMPLEX array, dimension (N*(N+1)/2) */ /* The upper or lower triangle of the Hermitian 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) COMPLEX 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**H or A = L*D*L**H as computed by CHPTRF, 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**H or A = L*D*L**H as computed by CHPTRF, 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 CHPTRF. */ /* 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 CHPTRF. */ /* B (input) COMPLEX 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) COMPLEX 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) REAL */ /* 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) REAL 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) REAL 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) COMPLEX array, dimension (2*N) */ /* RWORK (workspace) REAL 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 Hermitian 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 ] */ /* ===================================================================== */ /* .. 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; --rwork; /* 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_("CHPSVX", &i__1); return 0; } if (nofact) { /* Compute the factorization A = U*D*U' or A = L*D*L'. */ i__1 = *n * (*n + 1) / 2; ccopy_(&i__1, &ap[1], &c__1, &afp[1], &c__1); chptrf_(uplo, n, &afp[1], &ipiv[1], info); /* Return if INFO is non-zero. */ if (*info > 0) { *rcond = 0.f; return 0; } } /* Compute the norm of the matrix A. */ anorm = clanhp_("I", uplo, n, &ap[1], &rwork[1]); /* Compute the reciprocal of the condition number of A. */ chpcon_(uplo, n, &afp[1], &ipiv[1], &anorm, rcond, &work[1], info); /* Compute the solution vectors X. */ clacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx); chptrs_(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. */ chprfs_(uplo, n, nrhs, &ap[1], &afp[1], &ipiv[1], &b[b_offset], ldb, &x[ x_offset], ldx, &ferr[1], &berr[1], &work[1], &rwork[1], info); /* Set INFO = N+1 if the matrix is singular to working precision. */ if (*rcond < slamch_("Epsilon")) { *info = *n + 1; } return 0; /* End of CHPSVX */ } /* chpsvx_ */
/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer * ipiv, real *anorm, real *rcond, complex *work, integer *info) { /* System generated locals */ integer i__1, i__2; /* Local variables */ integer i__, ip, kase; extern logical lsame_(char *, char *); integer isave[3]; logical upper; extern /* Subroutine */ int clacn2_(integer *, complex *, complex *, real *, integer *, integer *), xerbla_(char *, integer *); real ainvnm; extern /* Subroutine */ int chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* Modified to call CLACN2 in place of CLACON, 10 Feb 03, SJH. */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* CHPCON estimates the reciprocal of the condition number of a complex */ /* Hermitian packed matrix A using the factorization A = U*D*U**H or */ /* A = L*D*L**H computed by CHPTRF. */ /* An estimate is obtained for norm(inv(A)), and the reciprocal of the */ /* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). */ /* Arguments */ /* ========= */ /* UPLO (input) CHARACTER*1 */ /* Specifies whether the details of the factorization are stored */ /* as an upper or lower triangular matrix. */ /* = 'U': Upper triangular, form is A = U*D*U**H; */ /* = 'L': Lower triangular, form is A = L*D*L**H. */ /* N (input) INTEGER */ /* The order of the matrix A. N >= 0. */ /* AP (input) COMPLEX array, dimension (N*(N+1)/2) */ /* The block diagonal matrix D and the multipliers used to */ /* obtain the factor U or L as computed by CHPTRF, stored as a */ /* packed triangular matrix. */ /* IPIV (input) INTEGER array, dimension (N) */ /* Details of the interchanges and the block structure of D */ /* as determined by CHPTRF. */ /* ANORM (input) REAL */ /* The 1-norm of the original matrix A. */ /* RCOND (output) REAL */ /* The reciprocal of the condition number of the matrix A, */ /* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an */ /* estimate of the 1-norm of inv(A) computed in this routine. */ /* WORK (workspace) COMPLEX array, dimension (2*N) */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --work; --ipiv; --ap; /* Function Body */ *info = 0; upper = lsame_(uplo, "U"); if (! upper && ! lsame_(uplo, "L")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*anorm < 0.f) { *info = -5; } if (*info != 0) { i__1 = -(*info); xerbla_("CHPCON", &i__1); return 0; } /* Quick return if possible */ *rcond = 0.f; if (*n == 0) { *rcond = 1.f; return 0; } else if (*anorm <= 0.f) { return 0; } /* Check that the diagonal matrix D is nonsingular. */ if (upper) { /* Upper triangular storage: examine D from bottom to top */ ip = *n * (*n + 1) / 2; for (i__ = *n; i__ >= 1; --i__) { i__1 = ip; if (ipiv[i__] > 0 && (ap[i__1].r == 0.f && ap[i__1].i == 0.f)) { return 0; } ip -= i__; /* L10: */ } } else { /* Lower triangular storage: examine D from top to bottom. */ ip = 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = ip; if (ipiv[i__] > 0 && (ap[i__2].r == 0.f && ap[i__2].i == 0.f)) { return 0; } ip = ip + *n - i__ + 1; /* L20: */ } } /* Estimate the 1-norm of the inverse. */ kase = 0; L30: clacn2_(n, &work[*n + 1], &work[1], &ainvnm, &kase, isave); if (kase != 0) { /* Multiply by inv(L*D*L') or inv(U*D*U'). */ chptrs_(uplo, n, &c__1, &ap[1], &ipiv[1], &work[1], n, info); goto L30; } /* Compute the estimate of the reciprocal condition number. */ if (ainvnm != 0.f) { *rcond = 1.f / ainvnm / *anorm; } return 0; /* End of CHPCON */ } /* chpcon_ */
/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer * ipiv, real *anorm, real *rcond, complex *work, integer *info) { /* System generated locals */ integer i__1, i__2; /* Local variables */ integer i__, ip, kase; extern logical lsame_(char *, char *); integer isave[3]; logical upper; extern /* Subroutine */ int clacn2_(integer *, complex *, complex *, real *, integer *, integer *), xerbla_(char *, integer *); real ainvnm; extern /* Subroutine */ int chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); /* -- LAPACK computational routine (version 3.4.0) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* November 2011 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --work; --ipiv; --ap; /* Function Body */ *info = 0; upper = lsame_(uplo, "U"); if (! upper && ! lsame_(uplo, "L")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*anorm < 0.f) { *info = -5; } if (*info != 0) { i__1 = -(*info); xerbla_("CHPCON", &i__1); return 0; } /* Quick return if possible */ *rcond = 0.f; if (*n == 0) { *rcond = 1.f; return 0; } else if (*anorm <= 0.f) { return 0; } /* Check that the diagonal matrix D is nonsingular. */ if (upper) { /* Upper triangular storage: examine D from bottom to top */ ip = *n * (*n + 1) / 2; for (i__ = *n; i__ >= 1; --i__) { i__1 = ip; if (ipiv[i__] > 0 && (ap[i__1].r == 0.f && ap[i__1].i == 0.f)) { return 0; } ip -= i__; /* L10: */ } } else { /* Lower triangular storage: examine D from top to bottom. */ ip = 1; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = ip; if (ipiv[i__] > 0 && (ap[i__2].r == 0.f && ap[i__2].i == 0.f)) { return 0; } ip = ip + *n - i__ + 1; /* L20: */ } } /* Estimate the 1-norm of the inverse. */ kase = 0; L30: clacn2_(n, &work[*n + 1], &work[1], &ainvnm, &kase, isave); if (kase != 0) { /* Multiply by inv(L*D*L**H) or inv(U*D*U**H). */ chptrs_(uplo, n, &c__1, &ap[1], &ipiv[1], &work[1], n, info); goto L30; } /* Compute the estimate of the reciprocal condition number. */ if (ainvnm != 0.f) { *rcond = 1.f / ainvnm / *anorm; } return 0; /* End of CHPCON */ }
/* Subroutine */ int chpsvx_(char *fact, char *uplo, integer *n, integer * nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer * ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, complex *work, real *rwork, integer *info) { /* System generated locals */ integer b_dim1, b_offset, x_dim1, x_offset, i__1; /* Local variables */ extern logical lsame_(char *, char *); real anorm; extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, complex *, integer *); extern real clanhp_(char *, char *, integer *, complex *, real *), slamch_(char *); logical nofact; extern /* Subroutine */ int chpcon_(char *, integer *, complex *, integer *, real *, real *, complex *, integer *), clacpy_(char *, integer *, integer *, complex *, integer *, complex *, integer *), xerbla_(char *, integer *), chprfs_(char *, integer *, integer *, complex *, complex *, integer *, complex *, integer *, complex *, integer *, real *, real *, complex *, real * , integer *), chptrf_(char *, integer *, complex *, integer *, integer *), chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); /* -- LAPACK driver routine (version 3.4.1) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* April 2012 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ===================================================================== */ /* .. 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; --rwork; /* 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_("CHPSVX", &i__1); return 0; } if (nofact) { /* Compute the factorization A = U*D*U**H or A = L*D*L**H. */ i__1 = *n * (*n + 1) / 2; ccopy_(&i__1, &ap[1], &c__1, &afp[1], &c__1); chptrf_(uplo, n, &afp[1], &ipiv[1], info); /* Return if INFO is non-zero. */ if (*info > 0) { *rcond = 0.f; return 0; } } /* Compute the norm of the matrix A. */ anorm = clanhp_("I", uplo, n, &ap[1], &rwork[1]); /* Compute the reciprocal of the condition number of A. */ chpcon_(uplo, n, &afp[1], &ipiv[1], &anorm, rcond, &work[1], info); /* Compute the solution vectors X. */ clacpy_("Full", n, nrhs, &b[b_offset], ldb, &x[x_offset], ldx); chptrs_(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. */ chprfs_(uplo, n, nrhs, &ap[1], &afp[1], &ipiv[1], &b[b_offset], ldb, &x[ x_offset], ldx, &ferr[1], &berr[1], &work[1], &rwork[1], info); /* Set INFO = N+1 if the matrix is singular to working precision. */ if (*rcond < slamch_("Epsilon")) { *info = *n + 1; } return 0; /* End of CHPSVX */ }
/* Subroutine */ int chpsv_(char *uplo, integer *n, integer *nrhs, complex * ap, integer *ipiv, complex *b, integer *ldb, integer *info) { /* System generated locals */ integer b_dim1, b_offset, i__1; /* Local variables */ extern logical lsame_(char *, char *); extern /* Subroutine */ int xerbla_(char *, integer *), chptrf_( char *, integer *, complex *, integer *, integer *), chptrs_(char *, integer *, integer *, complex *, integer *, complex *, integer *, integer *); /* -- LAPACK driver routine (version 3.4.0) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* November 2011 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ===================================================================== */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --ap; --ipiv; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; /* Function Body */ *info = 0; if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) { *info = -1; } else if (*n < 0) { *info = -2; } else if (*nrhs < 0) { *info = -3; } else if (*ldb < max(1,*n)) { *info = -7; } if (*info != 0) { i__1 = -(*info); xerbla_("CHPSV ", &i__1); return 0; } /* Compute the factorization A = U*D*U**H or A = L*D*L**H. */ chptrf_(uplo, n, &ap[1], &ipiv[1], info); if (*info == 0) { /* Solve the system A*X = B, overwriting B with X. */ chptrs_(uplo, n, nrhs, &ap[1], &ipiv[1], &b[b_offset], ldb, info); } return 0; /* End of CHPSV */ }