dspt21.c
Go to the documentation of this file.
00001 /* dspt21.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static doublereal c_b10 = 0.;
00019 static integer c__1 = 1;
00020 static doublereal c_b26 = 1.;
00021 
00022 /* Subroutine */ int dspt21_(integer *itype, char *uplo, integer *n, integer *
00023         kband, doublereal *ap, doublereal *d__, doublereal *e, doublereal *u, 
00024         integer *ldu, doublereal *vp, doublereal *tau, doublereal *work, 
00025         doublereal *result)
00026 {
00027     /* System generated locals */
00028     integer u_dim1, u_offset, i__1, i__2;
00029     doublereal d__1, d__2;
00030 
00031     /* Local variables */
00032     integer j, jp, jr, jp1, lap;
00033     doublereal ulp;
00034     extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, 
00035             integer *);
00036     doublereal unfl, temp;
00037     extern /* Subroutine */ int dspr_(char *, integer *, doublereal *, 
00038             doublereal *, integer *, doublereal *), dspr2_(char *, 
00039             integer *, doublereal *, doublereal *, integer *, doublereal *, 
00040             integer *, doublereal *), dgemm_(char *, char *, integer *
00041 , integer *, integer *, doublereal *, doublereal *, integer *, 
00042             doublereal *, integer *, doublereal *, doublereal *, integer *);
00043     extern logical lsame_(char *, char *);
00044     integer iinfo;
00045     doublereal anorm;
00046     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
00047             doublereal *, integer *);
00048     char cuplo[1];
00049     doublereal vsave;
00050     extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, 
00051             integer *, doublereal *, integer *);
00052     logical lower;
00053     extern /* Subroutine */ int dspmv_(char *, integer *, doublereal *, 
00054             doublereal *, doublereal *, integer *, doublereal *, doublereal *, 
00055              integer *);
00056     doublereal wnorm;
00057     extern doublereal dlamch_(char *), dlange_(char *, integer *, 
00058             integer *, doublereal *, integer *, doublereal *);
00059     extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, 
00060             doublereal *, integer *, doublereal *, integer *), 
00061             dlaset_(char *, integer *, integer *, doublereal *, doublereal *, 
00062             doublereal *, integer *);
00063     extern doublereal dlansp_(char *, char *, integer *, doublereal *, 
00064             doublereal *);
00065     extern /* Subroutine */ int dopmtr_(char *, char *, char *, integer *, 
00066             integer *, doublereal *, doublereal *, doublereal *, integer *, 
00067             doublereal *, integer *);
00068 
00069 
00070 /*  -- LAPACK test routine (version 3.1) -- */
00071 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00072 /*     November 2006 */
00073 
00074 /*     .. Scalar Arguments .. */
00075 /*     .. */
00076 /*     .. Array Arguments .. */
00077 /*     .. */
00078 
00079 /*  Purpose */
00080 /*  ======= */
00081 
00082 /*  DSPT21  generally checks a decomposition of the form */
00083 
00084 /*          A = U S U' */
00085 
00086 /*  where ' means transpose, A is symmetric (stored in packed format), U */
00087 /*  is orthogonal, and S is diagonal (if KBAND=0) or symmetric */
00088 /*  tridiagonal (if KBAND=1).  If ITYPE=1, then U is represented as a */
00089 /*  dense matrix, otherwise the U is expressed as a product of */
00090 /*  Householder transformations, whose vectors are stored in the array */
00091 /*  "V" and whose scaling constants are in "TAU"; we shall use the */
00092 /*  letter "V" to refer to the product of Householder transformations */
00093 /*  (which should be equal to U). */
00094 
00095 /*  Specifically, if ITYPE=1, then: */
00096 
00097 /*          RESULT(1) = | A - U S U' | / ( |A| n ulp ) *and* */
00098 /*          RESULT(2) = | I - UU' | / ( n ulp ) */
00099 
00100 /*  If ITYPE=2, then: */
00101 
00102 /*          RESULT(1) = | A - V S V' | / ( |A| n ulp ) */
00103 
00104 /*  If ITYPE=3, then: */
00105 
00106 /*          RESULT(1) = | I - VU' | / ( n ulp ) */
00107 
00108 /*  Packed storage means that, for example, if UPLO='U', then the columns */
00109 /*  of the upper triangle of A are stored one after another, so that */
00110 /*  A(1,j+1) immediately follows A(j,j) in the array AP.  Similarly, if */
00111 /*  UPLO='L', then the columns of the lower triangle of A are stored one */
00112 /*  after another in AP, so that A(j+1,j+1) immediately follows A(n,j) */
00113 /*  in the array AP.  This means that A(i,j) is stored in: */
00114 
00115 /*     AP( i + j*(j-1)/2 )                 if UPLO='U' */
00116 
00117 /*     AP( i + (2*n-j)*(j-1)/2 )           if UPLO='L' */
00118 
00119 /*  The array VP bears the same relation to the matrix V that A does to */
00120 /*  AP. */
00121 
00122 /*  For ITYPE > 1, the transformation U is expressed as a product */
00123 /*  of Householder transformations: */
00124 
00125 /*     If UPLO='U', then  V = H(n-1)...H(1),  where */
00126 
00127 /*         H(j) = I  -  tau(j) v(j) v(j)' */
00128 
00129 /*     and the first j-1 elements of v(j) are stored in V(1:j-1,j+1), */
00130 /*     (i.e., VP( j*(j+1)/2 + 1 : j*(j+1)/2 + j-1 ) ), */
00131 /*     the j-th element is 1, and the last n-j elements are 0. */
00132 
00133 /*     If UPLO='L', then  V = H(1)...H(n-1),  where */
00134 
00135 /*         H(j) = I  -  tau(j) v(j) v(j)' */
00136 
00137 /*     and the first j elements of v(j) are 0, the (j+1)-st is 1, and the */
00138 /*     (j+2)-nd through n-th elements are stored in V(j+2:n,j) (i.e., */
00139 /*     in VP( (2*n-j)*(j-1)/2 + j+2 : (2*n-j)*(j-1)/2 + n ) .) */
00140 
00141 /*  Arguments */
00142 /*  ========= */
00143 
00144 /*  ITYPE   (input) INTEGER */
00145 /*          Specifies the type of tests to be performed. */
00146 /*          1: U expressed as a dense orthogonal matrix: */
00147 /*             RESULT(1) = | A - U S U' | / ( |A| n ulp )   *and* */
00148 /*             RESULT(2) = | I - UU' | / ( n ulp ) */
00149 
00150 /*          2: U expressed as a product V of Housholder transformations: */
00151 /*             RESULT(1) = | A - V S V' | / ( |A| n ulp ) */
00152 
00153 /*          3: U expressed both as a dense orthogonal matrix and */
00154 /*             as a product of Housholder transformations: */
00155 /*             RESULT(1) = | I - VU' | / ( n ulp ) */
00156 
00157 /*  UPLO    (input) CHARACTER */
00158 /*          If UPLO='U', AP and VP are considered to contain the upper */
00159 /*          triangle of A and V. */
00160 /*          If UPLO='L', AP and VP are considered to contain the lower */
00161 /*          triangle of A and V. */
00162 
00163 /*  N       (input) INTEGER */
00164 /*          The size of the matrix.  If it is zero, DSPT21 does nothing. */
00165 /*          It must be at least zero. */
00166 
00167 /*  KBAND   (input) INTEGER */
00168 /*          The bandwidth of the matrix.  It may only be zero or one. */
00169 /*          If zero, then S is diagonal, and E is not referenced.  If */
00170 /*          one, then S is symmetric tri-diagonal. */
00171 
00172 /*  AP      (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */
00173 /*          The original (unfactored) matrix.  It is assumed to be */
00174 /*          symmetric, and contains the columns of just the upper */
00175 /*          triangle (UPLO='U') or only the lower triangle (UPLO='L'), */
00176 /*          packed one after another. */
00177 
00178 /*  D       (input) DOUBLE PRECISION array, dimension (N) */
00179 /*          The diagonal of the (symmetric tri-) diagonal matrix. */
00180 
00181 /*  E       (input) DOUBLE PRECISION array, dimension (N-1) */
00182 /*          The off-diagonal of the (symmetric tri-) diagonal matrix. */
00183 /*          E(1) is the (1,2) and (2,1) element, E(2) is the (2,3) and */
00184 /*          (3,2) element, etc. */
00185 /*          Not referenced if KBAND=0. */
00186 
00187 /*  U       (input) DOUBLE PRECISION array, dimension (LDU, N) */
00188 /*          If ITYPE=1 or 3, this contains the orthogonal matrix in */
00189 /*          the decomposition, expressed as a dense matrix.  If ITYPE=2, */
00190 /*          then it is not referenced. */
00191 
00192 /*  LDU     (input) INTEGER */
00193 /*          The leading dimension of U.  LDU must be at least N and */
00194 /*          at least 1. */
00195 
00196 /*  VP      (input) DOUBLE PRECISION array, dimension (N*(N+1)/2) */
00197 /*          If ITYPE=2 or 3, the columns of this array contain the */
00198 /*          Householder vectors used to describe the orthogonal matrix */
00199 /*          in the decomposition, as described in purpose. */
00200 /*          *NOTE* If ITYPE=2 or 3, V is modified and restored.  The */
00201 /*          subdiagonal (if UPLO='L') or the superdiagonal (if UPLO='U') */
00202 /*          is set to one, and later reset to its original value, during */
00203 /*          the course of the calculation. */
00204 /*          If ITYPE=1, then it is neither referenced nor modified. */
00205 
00206 /*  TAU     (input) DOUBLE PRECISION array, dimension (N) */
00207 /*          If ITYPE >= 2, then TAU(j) is the scalar factor of */
00208 /*          v(j) v(j)' in the Householder transformation H(j) of */
00209 /*          the product  U = H(1)...H(n-2) */
00210 /*          If ITYPE < 2, then TAU is not referenced. */
00211 
00212 /*  WORK    (workspace) DOUBLE PRECISION array, dimension (N**2+N) */
00213 /*          Workspace. */
00214 
00215 /*  RESULT  (output) DOUBLE PRECISION array, dimension (2) */
00216 /*          The values computed by the two tests described above.  The */
00217 /*          values are currently limited to 1/ulp, to avoid overflow. */
00218 /*          RESULT(1) is always modified.  RESULT(2) is modified only */
00219 /*          if ITYPE=1. */
00220 
00221 /*  ===================================================================== */
00222 
00223 /*     .. Parameters .. */
00224 /*     .. */
00225 /*     .. Local Scalars .. */
00226 /*     .. */
00227 /*     .. External Functions .. */
00228 /*     .. */
00229 /*     .. External Subroutines .. */
00230 /*     .. */
00231 /*     .. Intrinsic Functions .. */
00232 /*     .. */
00233 /*     .. Executable Statements .. */
00234 
00235 /*     1)      Constants */
00236 
00237     /* Parameter adjustments */
00238     --ap;
00239     --d__;
00240     --e;
00241     u_dim1 = *ldu;
00242     u_offset = 1 + u_dim1;
00243     u -= u_offset;
00244     --vp;
00245     --tau;
00246     --work;
00247     --result;
00248 
00249     /* Function Body */
00250     result[1] = 0.;
00251     if (*itype == 1) {
00252         result[2] = 0.;
00253     }
00254     if (*n <= 0) {
00255         return 0;
00256     }
00257 
00258     lap = *n * (*n + 1) / 2;
00259 
00260     if (lsame_(uplo, "U")) {
00261         lower = FALSE_;
00262         *(unsigned char *)cuplo = 'U';
00263     } else {
00264         lower = TRUE_;
00265         *(unsigned char *)cuplo = 'L';
00266     }
00267 
00268     unfl = dlamch_("Safe minimum");
00269     ulp = dlamch_("Epsilon") * dlamch_("Base");
00270 
00271 /*     Some Error Checks */
00272 
00273     if (*itype < 1 || *itype > 3) {
00274         result[1] = 10. / ulp;
00275         return 0;
00276     }
00277 
00278 /*     Do Test 1 */
00279 
00280 /*     Norm of A: */
00281 
00282     if (*itype == 3) {
00283         anorm = 1.;
00284     } else {
00285 /* Computing MAX */
00286         d__1 = dlansp_("1", cuplo, n, &ap[1], &work[1]);
00287         anorm = max(d__1,unfl);
00288     }
00289 
00290 /*     Compute error matrix: */
00291 
00292     if (*itype == 1) {
00293 
00294 /*        ITYPE=1: error = A - U S U' */
00295 
00296         dlaset_("Full", n, n, &c_b10, &c_b10, &work[1], n);
00297         dcopy_(&lap, &ap[1], &c__1, &work[1], &c__1);
00298 
00299         i__1 = *n;
00300         for (j = 1; j <= i__1; ++j) {
00301             d__1 = -d__[j];
00302             dspr_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &work[1]);
00303 /* L10: */
00304         }
00305 
00306         if (*n > 1 && *kband == 1) {
00307             i__1 = *n - 1;
00308             for (j = 1; j <= i__1; ++j) {
00309                 d__1 = -e[j];
00310                 dspr2_(cuplo, n, &d__1, &u[j * u_dim1 + 1], &c__1, &u[(j + 1) 
00311                         * u_dim1 + 1], &c__1, &work[1]);
00312 /* L20: */
00313             }
00314         }
00315 /* Computing 2nd power */
00316         i__1 = *n;
00317         wnorm = dlansp_("1", cuplo, n, &work[1], &work[i__1 * i__1 + 1]);
00318 
00319     } else if (*itype == 2) {
00320 
00321 /*        ITYPE=2: error = V S V' - A */
00322 
00323         dlaset_("Full", n, n, &c_b10, &c_b10, &work[1], n);
00324 
00325         if (lower) {
00326             work[lap] = d__[*n];
00327             for (j = *n - 1; j >= 1; --j) {
00328                 jp = ((*n << 1) - j) * (j - 1) / 2;
00329                 jp1 = jp + *n - j;
00330                 if (*kband == 1) {
00331                     work[jp + j + 1] = (1. - tau[j]) * e[j];
00332                     i__1 = *n;
00333                     for (jr = j + 2; jr <= i__1; ++jr) {
00334                         work[jp + jr] = -tau[j] * e[j] * vp[jp + jr];
00335 /* L30: */
00336                     }
00337                 }
00338 
00339                 if (tau[j] != 0.) {
00340                     vsave = vp[jp + j + 1];
00341                     vp[jp + j + 1] = 1.;
00342                     i__1 = *n - j;
00343                     dspmv_("L", &i__1, &c_b26, &work[jp1 + j + 1], &vp[jp + j 
00344                             + 1], &c__1, &c_b10, &work[lap + 1], &c__1);
00345                     i__1 = *n - j;
00346                     temp = tau[j] * -.5 * ddot_(&i__1, &work[lap + 1], &c__1, 
00347                             &vp[jp + j + 1], &c__1);
00348                     i__1 = *n - j;
00349                     daxpy_(&i__1, &temp, &vp[jp + j + 1], &c__1, &work[lap + 
00350                             1], &c__1);
00351                     i__1 = *n - j;
00352                     d__1 = -tau[j];
00353                     dspr2_("L", &i__1, &d__1, &vp[jp + j + 1], &c__1, &work[
00354                             lap + 1], &c__1, &work[jp1 + j + 1]);
00355                     vp[jp + j + 1] = vsave;
00356                 }
00357                 work[jp + j] = d__[j];
00358 /* L40: */
00359             }
00360         } else {
00361             work[1] = d__[1];
00362             i__1 = *n - 1;
00363             for (j = 1; j <= i__1; ++j) {
00364                 jp = j * (j - 1) / 2;
00365                 jp1 = jp + j;
00366                 if (*kband == 1) {
00367                     work[jp1 + j] = (1. - tau[j]) * e[j];
00368                     i__2 = j - 1;
00369                     for (jr = 1; jr <= i__2; ++jr) {
00370                         work[jp1 + jr] = -tau[j] * e[j] * vp[jp1 + jr];
00371 /* L50: */
00372                     }
00373                 }
00374 
00375                 if (tau[j] != 0.) {
00376                     vsave = vp[jp1 + j];
00377                     vp[jp1 + j] = 1.;
00378                     dspmv_("U", &j, &c_b26, &work[1], &vp[jp1 + 1], &c__1, &
00379                             c_b10, &work[lap + 1], &c__1);
00380                     temp = tau[j] * -.5 * ddot_(&j, &work[lap + 1], &c__1, &
00381                             vp[jp1 + 1], &c__1);
00382                     daxpy_(&j, &temp, &vp[jp1 + 1], &c__1, &work[lap + 1], &
00383                             c__1);
00384                     d__1 = -tau[j];
00385                     dspr2_("U", &j, &d__1, &vp[jp1 + 1], &c__1, &work[lap + 1]
00386 , &c__1, &work[1]);
00387                     vp[jp1 + j] = vsave;
00388                 }
00389                 work[jp1 + j + 1] = d__[j + 1];
00390 /* L60: */
00391             }
00392         }
00393 
00394         i__1 = lap;
00395         for (j = 1; j <= i__1; ++j) {
00396             work[j] -= ap[j];
00397 /* L70: */
00398         }
00399         wnorm = dlansp_("1", cuplo, n, &work[1], &work[lap + 1]);
00400 
00401     } else if (*itype == 3) {
00402 
00403 /*        ITYPE=3: error = U V' - I */
00404 
00405         if (*n < 2) {
00406             return 0;
00407         }
00408         dlacpy_(" ", n, n, &u[u_offset], ldu, &work[1], n);
00409 /* Computing 2nd power */
00410         i__1 = *n;
00411         dopmtr_("R", cuplo, "T", n, n, &vp[1], &tau[1], &work[1], n, &work[
00412                 i__1 * i__1 + 1], &iinfo);
00413         if (iinfo != 0) {
00414             result[1] = 10. / ulp;
00415             return 0;
00416         }
00417 
00418         i__1 = *n;
00419         for (j = 1; j <= i__1; ++j) {
00420             work[(*n + 1) * (j - 1) + 1] += -1.;
00421 /* L80: */
00422         }
00423 
00424 /* Computing 2nd power */
00425         i__1 = *n;
00426         wnorm = dlange_("1", n, n, &work[1], n, &work[i__1 * i__1 + 1]);
00427     }
00428 
00429     if (anorm > wnorm) {
00430         result[1] = wnorm / anorm / (*n * ulp);
00431     } else {
00432         if (anorm < 1.) {
00433 /* Computing MIN */
00434             d__1 = wnorm, d__2 = *n * anorm;
00435             result[1] = min(d__1,d__2) / anorm / (*n * ulp);
00436         } else {
00437 /* Computing MIN */
00438             d__1 = wnorm / anorm, d__2 = (doublereal) (*n);
00439             result[1] = min(d__1,d__2) / (*n * ulp);
00440         }
00441     }
00442 
00443 /*     Do Test 2 */
00444 
00445 /*     Compute  UU' - I */
00446 
00447     if (*itype == 1) {
00448         dgemm_("N", "C", n, n, n, &c_b26, &u[u_offset], ldu, &u[u_offset], 
00449                 ldu, &c_b10, &work[1], n);
00450 
00451         i__1 = *n;
00452         for (j = 1; j <= i__1; ++j) {
00453             work[(*n + 1) * (j - 1) + 1] += -1.;
00454 /* L90: */
00455         }
00456 
00457 /* Computing MIN */
00458 /* Computing 2nd power */
00459         i__1 = *n;
00460         d__1 = dlange_("1", n, n, &work[1], n, &work[i__1 * i__1 + 1]), d__2 = (doublereal) (*n);
00461         result[2] = min(d__1,d__2) / (*n * ulp);
00462     }
00463 
00464     return 0;
00465 
00466 /*     End of DSPT21 */
00467 
00468 } /* dspt21_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:48