doublereal slarnd_(integer *idist, integer *iseed) { /* System generated locals */ real ret_val; /* Builtin functions */ double log(doublereal), sqrt(doublereal), cos(doublereal); /* Local variables */ static real t1, t2; extern doublereal slaran_(integer *); /* -- LAPACK auxiliary routine (version 2.0) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* September 30, 1994 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLARND returns a random real number from a uniform or normal */ /* distribution. */ /* Arguments */ /* ========= */ /* IDIST (input) INTEGER */ /* Specifies the distribution of the random numbers: */ /* = 1: uniform (0,1) */ /* = 2: uniform (-1,1) */ /* = 3: normal (0,1) */ /* ISEED (input/output) INTEGER array, dimension (4) */ /* On entry, the seed of the random number generator; the array */ /* elements must be between 0 and 4095, and ISEED(4) must be */ /* odd. */ /* On exit, the seed is updated. */ /* Further Details */ /* =============== */ /* This routine calls the auxiliary routine SLARAN to generate a random */ /* real number from a uniform (0,1) distribution. The Box-Muller method */ /* is used to transform numbers from a uniform to a normal distribution. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Generate a real random number from a uniform (0,1) distribution */ /* Parameter adjustments */ --iseed; /* Function Body */ t1 = slaran_(&iseed[1]); if (*idist == 1) { /* uniform (0,1) */ ret_val = t1; } else if (*idist == 2) { /* uniform (-1,1) */ ret_val = t1 * 2.f - 1.f; } else if (*idist == 3) { /* normal (0,1) */ t2 = slaran_(&iseed[1]); ret_val = sqrt(log(t1) * -2.f) * cos(t2 * 6.2831853071795864769252867663f); } return ret_val; /* End of SLARND */ } /* slarnd_ */
/* Subroutine */ int slatm4_(integer *itype, integer *n, integer *nz1, integer *nz2, integer *isign, real *amagn, real *rcond, real *triang, integer *idist, integer *iseed, real *a, integer *lda) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; real r__1, r__2, r__3, r__4; doublereal d__1, d__2; /* Builtin functions */ double pow_dd(doublereal *, doublereal *), pow_ri(real *, integer *), log( doublereal), exp(doublereal), sqrt(doublereal); /* Local variables */ static integer kbeg, isdb, kend, ioff, isde, klen; static real temp; static integer i__, k; static real alpha; static integer jc, jd; static real cl, cr; static integer jr; static real sl, sr; extern doublereal slamch_(char *); static real safmin; extern doublereal slaran_(integer *), slarnd_(integer *, integer *); extern /* Subroutine */ int slaset_(char *, integer *, integer *, real *, real *, real *, integer *); static real sv1, sv2; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] /* -- LAPACK auxiliary test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= SLATM4 generates basic square matrices, which may later be multiplied by others in order to produce test matrices. It is intended mainly to be used to test the generalized eigenvalue routines. It first generates the diagonal and (possibly) subdiagonal, according to the value of ITYPE, NZ1, NZ2, ISIGN, AMAGN, and RCOND. It then fills in the upper triangle with random numbers, if TRIANG is non-zero. Arguments ========= ITYPE (input) INTEGER The "type" of matrix on the diagonal and sub-diagonal. If ITYPE < 0, then type abs(ITYPE) is generated and then swapped end for end (A(I,J) := A'(N-J,N-I).) See also the description of AMAGN and ISIGN. Special types: = 0: the zero matrix. = 1: the identity. = 2: a transposed Jordan block. = 3: If N is odd, then a k+1 x k+1 transposed Jordan block followed by a k x k identity block, where k=(N-1)/2. If N is even, then k=(N-2)/2, and a zero diagonal entry is tacked onto the end. Diagonal types. The diagonal consists of NZ1 zeros, then k=N-NZ1-NZ2 nonzeros. The subdiagonal is zero. ITYPE specifies the nonzero diagonal entries as follows: = 4: 1, ..., k = 5: 1, RCOND, ..., RCOND = 6: 1, ..., 1, RCOND = 7: 1, a, a^2, ..., a^(k-1)=RCOND = 8: 1, 1-d, 1-2*d, ..., 1-(k-1)*d=RCOND = 9: random numbers chosen from (RCOND,1) = 10: random numbers with distribution IDIST (see SLARND.) N (input) INTEGER The order of the matrix. NZ1 (input) INTEGER If abs(ITYPE) > 3, then the first NZ1 diagonal entries will be zero. NZ2 (input) INTEGER If abs(ITYPE) > 3, then the last NZ2 diagonal entries will be zero. ISIGN (input) INTEGER = 0: The sign of the diagonal and subdiagonal entries will be left unchanged. = 1: The diagonal and subdiagonal entries will have their sign changed at random. = 2: If ITYPE is 2 or 3, then the same as ISIGN=1. Otherwise, with probability 0.5, odd-even pairs of diagonal entries A(2*j-1,2*j-1), A(2*j,2*j) will be converted to a 2x2 block by pre- and post-multiplying by distinct random orthogonal rotations. The remaining diagonal entries will have their sign changed at random. AMAGN (input) REAL The diagonal and subdiagonal entries will be multiplied by AMAGN. RCOND (input) REAL If abs(ITYPE) > 4, then the smallest diagonal entry will be entry will be RCOND. RCOND must be between 0 and 1. TRIANG (input) REAL The entries above the diagonal will be random numbers with magnitude bounded by TRIANG (i.e., random numbers multiplied by TRIANG.) IDIST (input) INTEGER Specifies the type of distribution to be used to generate a random matrix. = 1: UNIFORM( 0, 1 ) = 2: UNIFORM( -1, 1 ) = 3: NORMAL ( 0, 1 ) ISEED (input/output) INTEGER array, dimension (4) On entry ISEED specifies the seed of the random number generator. The values of ISEED are changed on exit, and can be used in the next call to SLATM4 to continue the same random number sequence. Note: ISEED(4) should be odd, for the random number generator used at present. A (output) REAL array, dimension (LDA, N) Array to be computed. LDA (input) INTEGER Leading dimension of A. Must be at least 1 and at least N. ===================================================================== Parameter adjustments */ --iseed; a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; /* Function Body */ if (*n <= 0) { return 0; } slaset_("Full", n, n, &c_b3, &c_b3, &a[a_offset], lda); /* Insure a correct ISEED */ if (iseed[4] % 2 != 1) { ++iseed[4]; } /* Compute diagonal and subdiagonal according to ITYPE, NZ1, NZ2, and RCOND */ if (*itype != 0) { if (abs(*itype) >= 4) { /* Computing MAX Computing MIN */ i__3 = *n, i__4 = *nz1 + 1; i__1 = 1, i__2 = min(i__3,i__4); kbeg = max(i__1,i__2); /* Computing MAX Computing MIN */ i__3 = *n, i__4 = *n - *nz2; i__1 = kbeg, i__2 = min(i__3,i__4); kend = max(i__1,i__2); klen = kend + 1 - kbeg; } else { kbeg = 1; kend = *n; klen = *n; } isdb = 1; isde = 0; switch (abs(*itype)) { case 1: goto L10; case 2: goto L30; case 3: goto L50; case 4: goto L80; case 5: goto L100; case 6: goto L120; case 7: goto L140; case 8: goto L160; case 9: goto L180; case 10: goto L200; } /* |ITYPE| = 1: Identity */ L10: i__1 = *n; for (jd = 1; jd <= i__1; ++jd) { a_ref(jd, jd) = 1.f; /* L20: */ } goto L220; /* |ITYPE| = 2: Transposed Jordan block */ L30: i__1 = *n - 1; for (jd = 1; jd <= i__1; ++jd) { a_ref(jd + 1, jd) = 1.f; /* L40: */ } isdb = 1; isde = *n - 1; goto L220; /* |ITYPE| = 3: Transposed Jordan block, followed by the identity. */ L50: k = (*n - 1) / 2; i__1 = k; for (jd = 1; jd <= i__1; ++jd) { a_ref(jd + 1, jd) = 1.f; /* L60: */ } isdb = 1; isde = k; i__1 = (k << 1) + 1; for (jd = k + 2; jd <= i__1; ++jd) { a_ref(jd, jd) = 1.f; /* L70: */ } goto L220; /* |ITYPE| = 4: 1,...,k */ L80: i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { a_ref(jd, jd) = (real) (jd - *nz1); /* L90: */ } goto L220; /* |ITYPE| = 5: One large D value: */ L100: i__1 = kend; for (jd = kbeg + 1; jd <= i__1; ++jd) { a_ref(jd, jd) = *rcond; /* L110: */ } a_ref(kbeg, kbeg) = 1.f; goto L220; /* |ITYPE| = 6: One small D value: */ L120: i__1 = kend - 1; for (jd = kbeg; jd <= i__1; ++jd) { a_ref(jd, jd) = 1.f; /* L130: */ } a_ref(kend, kend) = *rcond; goto L220; /* |ITYPE| = 7: Exponentially distributed D values: */ L140: a_ref(kbeg, kbeg) = 1.f; if (klen > 1) { d__1 = (doublereal) (*rcond); d__2 = (doublereal) (1.f / (real) (klen - 1)); alpha = pow_dd(&d__1, &d__2); i__1 = klen; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = i__ - 1; a_ref(*nz1 + i__, *nz1 + i__) = pow_ri(&alpha, &i__2); /* L150: */ } } goto L220; /* |ITYPE| = 8: Arithmetically distributed D values: */ L160: a_ref(kbeg, kbeg) = 1.f; if (klen > 1) { alpha = (1.f - *rcond) / (real) (klen - 1); i__1 = klen; for (i__ = 2; i__ <= i__1; ++i__) { a_ref(*nz1 + i__, *nz1 + i__) = (real) (klen - i__) * alpha + *rcond; /* L170: */ } } goto L220; /* |ITYPE| = 9: Randomly distributed D values on ( RCOND, 1): */ L180: alpha = log(*rcond); i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { a_ref(jd, jd) = exp(alpha * slaran_(&iseed[1])); /* L190: */ } goto L220; /* |ITYPE| = 10: Randomly distributed D values from DIST */ L200: i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { a_ref(jd, jd) = slarnd_(idist, &iseed[1]); /* L210: */ } L220: /* Scale by AMAGN */ i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { a_ref(jd, jd) = *amagn * a_ref(jd, jd); /* L230: */ } i__1 = isde; for (jd = isdb; jd <= i__1; ++jd) { a_ref(jd + 1, jd) = *amagn * a_ref(jd + 1, jd); /* L240: */ } /* If ISIGN = 1 or 2, assign random signs to diagonal and subdiagonal */ if (*isign > 0) { i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { if (a_ref(jd, jd) != 0.f) { if (slaran_(&iseed[1]) > .5f) { a_ref(jd, jd) = -a_ref(jd, jd); } } /* L250: */ } i__1 = isde; for (jd = isdb; jd <= i__1; ++jd) { if (a_ref(jd + 1, jd) != 0.f) { if (slaran_(&iseed[1]) > .5f) { a_ref(jd + 1, jd) = -a_ref(jd + 1, jd); } } /* L260: */ } } /* Reverse if ITYPE < 0 */ if (*itype < 0) { i__1 = (kbeg + kend - 1) / 2; for (jd = kbeg; jd <= i__1; ++jd) { temp = a_ref(jd, jd); a_ref(jd, jd) = a_ref(kbeg + kend - jd, kbeg + kend - jd); a_ref(kbeg + kend - jd, kbeg + kend - jd) = temp; /* L270: */ } i__1 = (*n - 1) / 2; for (jd = 1; jd <= i__1; ++jd) { temp = a_ref(jd + 1, jd); a_ref(jd + 1, jd) = a_ref(*n + 1 - jd, *n - jd); a_ref(*n + 1 - jd, *n - jd) = temp; /* L280: */ } } /* If ISIGN = 2, and no subdiagonals already, then apply random rotations to make 2x2 blocks. */ if (*isign == 2 && *itype != 2 && *itype != 3) { safmin = slamch_("S"); i__1 = kend - 1; for (jd = kbeg; jd <= i__1; jd += 2) { if (slaran_(&iseed[1]) > .5f) { /* Rotation on left. */ cl = slaran_(&iseed[1]) * 2.f - 1.f; sl = slaran_(&iseed[1]) * 2.f - 1.f; /* Computing MAX Computing 2nd power */ r__3 = cl; /* Computing 2nd power */ r__4 = sl; r__1 = safmin, r__2 = sqrt(r__3 * r__3 + r__4 * r__4); temp = 1.f / dmax(r__1,r__2); cl *= temp; sl *= temp; /* Rotation on right. */ cr = slaran_(&iseed[1]) * 2.f - 1.f; sr = slaran_(&iseed[1]) * 2.f - 1.f; /* Computing MAX Computing 2nd power */ r__3 = cr; /* Computing 2nd power */ r__4 = sr; r__1 = safmin, r__2 = sqrt(r__3 * r__3 + r__4 * r__4); temp = 1.f / dmax(r__1,r__2); cr *= temp; sr *= temp; /* Apply */ sv1 = a_ref(jd, jd); sv2 = a_ref(jd + 1, jd + 1); a_ref(jd, jd) = cl * cr * sv1 + sl * sr * sv2; a_ref(jd + 1, jd) = -sl * cr * sv1 + cl * sr * sv2; a_ref(jd, jd + 1) = -cl * sr * sv1 + sl * cr * sv2; a_ref(jd + 1, jd + 1) = sl * sr * sv1 + cl * cr * sv2; } /* L290: */ } } } /* Fill in upper triangle (except for 2x2 blocks) */ if (*triang != 0.f) { if (*isign != 2 || *itype == 2 || *itype == 3) { ioff = 1; } else { ioff = 2; i__1 = *n - 1; for (jr = 1; jr <= i__1; ++jr) { if (a_ref(jr + 1, jr) == 0.f) { a_ref(jr, jr + 1) = *triang * slarnd_(idist, &iseed[1]); } /* L300: */ } } i__1 = *n; for (jc = 2; jc <= i__1; ++jc) { i__2 = jc - ioff; for (jr = 1; jr <= i__2; ++jr) { a_ref(jr, jc) = *triang * slarnd_(idist, &iseed[1]); /* L310: */ } /* L320: */ } } return 0; /* End of SLATM4 */ } /* slatm4_ */
doublereal slatm3_(integer *m, integer *n, integer *i__, integer *j, integer * isub, integer *jsub, integer *kl, integer *ku, integer *idist, integer *iseed, real *d__, integer *igrade, real *dl, real *dr, integer *ipvtng, integer *iwork, real *sparse) { /* System generated locals */ real ret_val; /* Local variables */ real temp; extern doublereal slaran_(integer *), slarnd_(integer *, integer *); /* -- LAPACK auxiliary test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLATM3 returns the (ISUB,JSUB) entry of a random matrix of */ /* dimension (M, N) described by the other paramters. (ISUB,JSUB) */ /* is the final position of the (I,J) entry after pivoting */ /* according to IPVTNG and IWORK. SLATM3 is called by the */ /* SLATMR routine in order to build random test matrices. No error */ /* checking on parameters is done, because this routine is called in */ /* a tight loop by SLATMR which has already checked the parameters. */ /* Use of SLATM3 differs from SLATM2 in the order in which the random */ /* number generator is called to fill in random matrix entries. */ /* With SLATM2, the generator is called to fill in the pivoted matrix */ /* columnwise. With SLATM3, the generator is called to fill in the */ /* matrix columnwise, after which it is pivoted. Thus, SLATM3 can */ /* be used to construct random matrices which differ only in their */ /* order of rows and/or columns. SLATM2 is used to construct band */ /* matrices while avoiding calling the random number generator for */ /* entries outside the band (and therefore generating random numbers */ /* in different orders for different pivot orders). */ /* The matrix whose (ISUB,JSUB) entry is returned is constructed as */ /* follows (this routine only computes one entry): */ /* If ISUB is outside (1..M) or JSUB is outside (1..N), return zero */ /* (this is convenient for generating matrices in band format). */ /* Generate a matrix A with random entries of distribution IDIST. */ /* Set the diagonal to D. */ /* Grade the matrix, if desired, from the left (by DL) and/or */ /* from the right (by DR or DL) as specified by IGRADE. */ /* Permute, if desired, the rows and/or columns as specified by */ /* IPVTNG and IWORK. */ /* Band the matrix to have lower bandwidth KL and upper */ /* bandwidth KU. */ /* Set random entries to zero as specified by SPARSE. */ /* Arguments */ /* ========= */ /* M - INTEGER */ /* Number of rows of matrix. Not modified. */ /* N - INTEGER */ /* Number of columns of matrix. Not modified. */ /* I - INTEGER */ /* Row of unpivoted entry to be returned. Not modified. */ /* J - INTEGER */ /* Column of unpivoted entry to be returned. Not modified. */ /* ISUB - INTEGER */ /* Row of pivoted entry to be returned. Changed on exit. */ /* JSUB - INTEGER */ /* Column of pivoted entry to be returned. Changed on exit. */ /* KL - INTEGER */ /* Lower bandwidth. Not modified. */ /* KU - INTEGER */ /* Upper bandwidth. Not modified. */ /* IDIST - INTEGER */ /* On entry, IDIST specifies the type of distribution to be */ /* used to generate a random matrix . */ /* 1 => UNIFORM( 0, 1 ) */ /* 2 => UNIFORM( -1, 1 ) */ /* 3 => NORMAL( 0, 1 ) */ /* Not modified. */ /* ISEED - INTEGER array of dimension ( 4 ) */ /* Seed for random number generator. */ /* Changed on exit. */ /* D - REAL array of dimension ( MIN( I , J ) ) */ /* Diagonal entries of matrix. Not modified. */ /* IGRADE - INTEGER */ /* Specifies grading of matrix as follows: */ /* 0 => no grading */ /* 1 => matrix premultiplied by diag( DL ) */ /* 2 => matrix postmultiplied by diag( DR ) */ /* 3 => matrix premultiplied by diag( DL ) and */ /* postmultiplied by diag( DR ) */ /* 4 => matrix premultiplied by diag( DL ) and */ /* postmultiplied by inv( diag( DL ) ) */ /* 5 => matrix premultiplied by diag( DL ) and */ /* postmultiplied by diag( DL ) */ /* Not modified. */ /* DL - REAL array ( I or J, as appropriate ) */ /* Left scale factors for grading matrix. Not modified. */ /* DR - REAL array ( I or J, as appropriate ) */ /* Right scale factors for grading matrix. Not modified. */ /* IPVTNG - INTEGER */ /* On entry specifies pivoting permutations as follows: */ /* 0 => none. */ /* 1 => row pivoting. */ /* 2 => column pivoting. */ /* 3 => full pivoting, i.e., on both sides. */ /* Not modified. */ /* IWORK - INTEGER array ( I or J, as appropriate ) */ /* This array specifies the permutation used. The */ /* row (or column) originally in position K is in */ /* position IWORK( K ) after pivoting. */ /* This differs from IWORK for SLATM2. Not modified. */ /* SPARSE - REAL between 0. and 1. */ /* On entry specifies the sparsity of the matrix */ /* if sparse matix is to be generated. */ /* SPARSE should lie between 0 and 1. */ /* 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. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* ----------------------------------------------------------------------- */ /* .. Executable Statements .. */ /* Check for I and J in range */ /* Parameter adjustments */ --iwork; --dr; --dl; --d__; --iseed; /* Function Body */ if (*i__ < 1 || *i__ > *m || *j < 1 || *j > *n) { *isub = *i__; *jsub = *j; ret_val = 0.f; return ret_val; } /* Compute subscripts depending on IPVTNG */ if (*ipvtng == 0) { *isub = *i__; *jsub = *j; } else if (*ipvtng == 1) { *isub = iwork[*i__]; *jsub = *j; } else if (*ipvtng == 2) { *isub = *i__; *jsub = iwork[*j]; } else if (*ipvtng == 3) { *isub = iwork[*i__]; *jsub = iwork[*j]; } /* Check for banding */ if (*jsub > *isub + *ku || *jsub < *isub - *kl) { ret_val = 0.f; return ret_val; } /* Check for sparsity */ if (*sparse > 0.f) { if (slaran_(&iseed[1]) < *sparse) { ret_val = 0.f; return ret_val; } } /* Compute entry and grade it according to IGRADE */ if (*i__ == *j) { temp = d__[*i__]; } else { temp = slarnd_(idist, &iseed[1]); } if (*igrade == 1) { temp *= dl[*i__]; } else if (*igrade == 2) { temp *= dr[*j]; } else if (*igrade == 3) { temp = temp * dl[*i__] * dr[*j]; } else if (*igrade == 4 && *i__ != *j) { temp = temp * dl[*i__] / dl[*j]; } else if (*igrade == 5) { temp = temp * dl[*i__] * dl[*j]; } ret_val = temp; return ret_val; /* End of SLATM3 */ } /* slatm3_ */
/* Subroutine */ int slatme_(integer *n, char *dist, integer *iseed, real * d__, integer *mode, real *cond, real *dmax__, char *ei, char *rsign, char *upper, char *sim, real *ds, integer *modes, real *conds, integer *kl, integer *ku, real *anorm, real *a, integer *lda, real * work, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; real r__1, r__2, r__3; /* Local variables */ static logical bads; extern /* Subroutine */ int sger_(integer *, integer *, real *, real *, integer *, real *, integer *, real *, integer *); static integer isim; static real temp; static logical badei; static integer i__, j; static real alpha; extern logical lsame_(char *, char *); static integer iinfo; extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *); static real tempa[1]; static integer icols; static logical useei; static integer idist; extern /* Subroutine */ int sgemv_(char *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *), scopy_(integer *, real *, integer *, real *, integer *); static integer irows; extern /* Subroutine */ int slatm1_(integer *, real *, integer *, integer *, integer *, real *, integer *, integer *); static integer ic, jc, ir, jr; extern doublereal slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int slarge_(integer *, real *, integer *, integer *, real *, integer *), slarfg_(integer *, real *, real *, integer *, real *), xerbla_(char *, integer *); extern doublereal slaran_(integer *); static integer irsign; extern /* Subroutine */ int slaset_(char *, integer *, integer *, real *, real *, real *, integer *); static integer iupper; extern /* Subroutine */ int slarnv_(integer *, integer *, integer *, real *); static real xnorms; static integer jcr; static real tau; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] /* -- LAPACK test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= SLATME generates random non-symmetric square matrices with specified eigenvalues for testing LAPACK programs. SLATME operates by applying the following sequence of operations: 1. Set the diagonal to D, where D may be input or computed according to MODE, COND, DMAX, and RSIGN as described below. 2. If complex conjugate pairs are desired (MODE=0 and EI(1)='R', or MODE=5), certain pairs of adjacent elements of D are interpreted as the real and complex parts of a complex conjugate pair; A thus becomes block diagonal, with 1x1 and 2x2 blocks. 3. If UPPER='T', the upper triangle of A is set to random values out of distribution DIST. 4. If SIM='T', A is multiplied on the left by a random matrix X, whose singular values are specified by DS, MODES, and CONDS, and on the right by X inverse. 5. If KL < N-1, the lower bandwidth is reduced to KL using Householder transformations. If KU < N-1, the upper bandwidth is reduced to KU. 6. If ANORM is not negative, the matrix is scaled to have maximum-element-norm ANORM. (Note: since the matrix cannot be reduced beyond Hessenberg form, no packing options are available.) Arguments ========= N - INTEGER The number of columns (or rows) of A. Not modified. DIST - CHARACTER*1 On entry, DIST specifies the type of distribution to be used to generate the random eigen-/singular values, and for the upper triangle (see UPPER). '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 SLATME to continue the same random number sequence. Changed on exit. D - REAL array, dimension ( N ) This array is used to specify the eigenvalues of A. If MODE=0, then D is assumed to contain the eigenvalues (but see the description of EI), otherwise they will be computed according to MODE, COND, DMAX, and RSIGN and placed in D. Modified if MODE is nonzero. MODE - INTEGER On entry this describes how the eigenvalues are to be specified: MODE = 0 means use D (with EI) 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. Each odd-even pair of elements will be either used as two real eigenvalues or as the real and imaginary part of a complex conjugate pair of eigenvalues; the choice of which is done is random, with 50-50 probability, for each pair. 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 between 1 and 4, D has entries ranging from 1 to 1/COND, if between -1 and -4, D has entries ranging from 1/COND to 1, Not modified. COND - REAL On entry, this is used as described under MODE above. If used, it must be >= 1. Not modified. DMAX - REAL If MODE is neither -6, 0 nor 6, the contents of D, as computed according to MODE and COND, will be scaled by DMAX / max(abs(D(i))). Note that DMAX need not be positive: if DMAX is negative (or zero), D will be scaled by a negative number (or zero). Not modified. EI - CHARACTER*1 array, dimension ( N ) If MODE is 0, and EI(1) is not ' ' (space character), this array specifies which elements of D (on input) are real eigenvalues and which are the real and imaginary parts of a complex conjugate pair of eigenvalues. The elements of EI may then only have the values 'R' and 'I'. If EI(j)='R' and EI(j+1)='I', then the j-th eigenvalue is CMPLX( D(j) , D(j+1) ), and the (j+1)-th is the complex conjugate thereof. If EI(j)=EI(j+1)='R', then the j-th eigenvalue is D(j) (i.e., real). EI(1) may not be 'I', nor may two adjacent elements of EI both have the value 'I'. If MODE is not 0, then EI is ignored. If MODE is 0 and EI(1)=' ', then the eigenvalues will all be real. Not modified. RSIGN - CHARACTER*1 If MODE is not 0, 6, or -6, and RSIGN='T', then the elements of D, as computed according to MODE and COND, will be multiplied by a random sign (+1 or -1). If RSIGN='F', they will not be. RSIGN may only have the values 'T' or 'F'. Not modified. UPPER - CHARACTER*1 If UPPER='T', then the elements of A above the diagonal (and above the 2x2 diagonal blocks, if A has complex eigenvalues) will be set to random numbers out of DIST. If UPPER='F', they will not. UPPER may only have the values 'T' or 'F'. Not modified. SIM - CHARACTER*1 If SIM='T', then A will be operated on by a "similarity transform", i.e., multiplied on the left by a matrix X and on the right by X inverse. X = U S V, where U and V are random unitary matrices and S is a (diagonal) matrix of singular values specified by DS, MODES, and CONDS. If SIM='F', then A will not be transformed. Not modified. DS - REAL array, dimension ( N ) This array is used to specify the singular values of X, in the same way that D specifies the eigenvalues of A. If MODE=0, the DS contains the singular values, which may not be zero. Modified if MODE is nonzero. MODES - INTEGER CONDS - REAL Same as MODE and COND, but for specifying the diagonal of S. MODES=-6 and +6 are not allowed (since they would result in randomly ill-conditioned eigenvalues.) KL - INTEGER This specifies the lower bandwidth of the matrix. KL=1 specifies upper Hessenberg form. If KL is at least N-1, then A will have full lower bandwidth. KL must be at least 1. Not modified. KU - INTEGER This specifies the upper bandwidth of the matrix. KU=1 specifies lower Hessenberg form. If KU is at least N-1, then A will have full upper bandwidth; if KU and KL are both at least N-1, then A will be dense. Only one of KU and KL may be less than N-1. KU must be at least 1. Not modified. ANORM - REAL If ANORM is not negative, then A will be scaled by a non- negative real number to make the maximum-element-norm of A to be ANORM. Not modified. A - REAL array, dimension ( LDA, N ) On exit A is the desired test matrix. Modified. LDA - INTEGER LDA specifies the first dimension of A as declared in the calling program. LDA must be at least N. Not modified. WORK - REAL array, dimension ( 3*N ) Workspace. Modified. INFO - INTEGER Error code. On exit, INFO will be set to one of the following values: 0 => normal return -1 => N negative -2 => DIST illegal string -5 => MODE not in range -6 to 6 -6 => COND less than 1.0, and MODE neither -6, 0 nor 6 -8 => EI(1) is not ' ' or 'R', EI(j) is not 'R' or 'I', or two adjacent elements of EI are 'I'. -9 => RSIGN is not 'T' or 'F' -10 => UPPER is not 'T' or 'F' -11 => SIM is not 'T' or 'F' -12 => MODES=0 and DS has a zero singular value. -13 => MODES is not in the range -5 to 5. -14 => MODES is nonzero and CONDS is less than 1. -15 => KL is less than 1. -16 => KU is less than 1, or KL and KU are both less than N-1. -19 => LDA is less than N. 1 => Error return from SLATM1 (computing D) 2 => Cannot scale to DMAX (max. eigenvalue is 0) 3 => Error return from SLATM1 (computing DS) 4 => Error return from SLARGE 5 => Zero singular value from SLATM1. ===================================================================== 1) Decode and Test the input parameters. Initialize flags & seed. Parameter adjustments */ --iseed; --d__; --ei; --ds; a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --work; /* Function Body */ *info = 0; /* Quick return if possible */ if (*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; } /* Check EI */ useei = TRUE_; badei = FALSE_; if (lsame_(ei + 1, " ") || *mode != 0) { useei = FALSE_; } else { if (lsame_(ei + 1, "R")) { i__1 = *n; for (j = 2; j <= i__1; ++j) { if (lsame_(ei + j, "I")) { if (lsame_(ei + (j - 1), "I")) { badei = TRUE_; } } else { if (! lsame_(ei + j, "R")) { badei = TRUE_; } } /* L10: */ } } else { badei = TRUE_; } } /* Decode RSIGN */ if (lsame_(rsign, "T")) { irsign = 1; } else if (lsame_(rsign, "F")) { irsign = 0; } else { irsign = -1; } /* Decode UPPER */ if (lsame_(upper, "T")) { iupper = 1; } else if (lsame_(upper, "F")) { iupper = 0; } else { iupper = -1; } /* Decode SIM */ if (lsame_(sim, "T")) { isim = 1; } else if (lsame_(sim, "F")) { isim = 0; } else { isim = -1; } /* Check DS, if MODES=0 and ISIM=1 */ bads = FALSE_; if (*modes == 0 && isim == 1) { i__1 = *n; for (j = 1; j <= i__1; ++j) { if (ds[j] == 0.f) { bads = TRUE_; } /* L20: */ } } /* Set INFO if an error */ if (*n < 0) { *info = -1; } else if (idist == -1) { *info = -2; } else if (abs(*mode) > 6) { *info = -5; } else if (*mode != 0 && abs(*mode) != 6 && *cond < 1.f) { *info = -6; } else if (badei) { *info = -8; } else if (irsign == -1) { *info = -9; } else if (iupper == -1) { *info = -10; } else if (isim == -1) { *info = -11; } else if (bads) { *info = -12; } else if (isim == 1 && abs(*modes) > 5) { *info = -13; } else if (isim == 1 && *modes != 0 && *conds < 1.f) { *info = -14; } else if (*kl < 1) { *info = -15; } else if (*ku < 1 || *ku < *n - 1 && *kl < *n - 1) { *info = -16; } else if (*lda < max(1,*n)) { *info = -19; } if (*info != 0) { i__1 = -(*info); xerbla_("SLATME", &i__1); return 0; } /* Initialize random number generator */ for (i__ = 1; i__ <= 4; ++i__) { iseed[i__] = (i__1 = iseed[i__], abs(i__1)) % 4096; /* L30: */ } if (iseed[4] % 2 != 1) { ++iseed[4]; } /* 2) Set up diagonal of A Compute D according to COND and MODE */ slatm1_(mode, cond, &irsign, &idist, &iseed[1], &d__[1], n, &iinfo); if (iinfo != 0) { *info = 1; return 0; } if (*mode != 0 && abs(*mode) != 6) { /* Scale by DMAX */ temp = dabs(d__[1]); i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { /* Computing MAX */ r__2 = temp, r__3 = (r__1 = d__[i__], dabs(r__1)); temp = dmax(r__2,r__3); /* L40: */ } if (temp > 0.f) { alpha = *dmax__ / temp; } else if (*dmax__ != 0.f) { *info = 2; return 0; } else { alpha = 0.f; } sscal_(n, &alpha, &d__[1], &c__1); } slaset_("Full", n, n, &c_b23, &c_b23, &a[a_offset], lda); i__1 = *lda + 1; scopy_(n, &d__[1], &c__1, &a[a_offset], &i__1); /* Set up complex conjugate pairs */ if (*mode == 0) { if (useei) { i__1 = *n; for (j = 2; j <= i__1; ++j) { if (lsame_(ei + j, "I")) { a_ref(j - 1, j) = a_ref(j, j); a_ref(j, j - 1) = -a_ref(j, j); a_ref(j, j) = a_ref(j - 1, j - 1); } /* L50: */ } } } else if (abs(*mode) == 5) { i__1 = *n; for (j = 2; j <= i__1; j += 2) { if (slaran_(&iseed[1]) > .5f) { a_ref(j - 1, j) = a_ref(j, j); a_ref(j, j - 1) = -a_ref(j, j); a_ref(j, j) = a_ref(j - 1, j - 1); } /* L60: */ } } /* 3) If UPPER='T', set upper triangle of A to random numbers. (but don't modify the corners of 2x2 blocks.) */ if (iupper != 0) { i__1 = *n; for (jc = 2; jc <= i__1; ++jc) { if (a_ref(jc - 1, jc) != 0.f) { jr = jc - 2; } else { jr = jc - 1; } slarnv_(&idist, &iseed[1], &jr, &a_ref(1, jc)); /* L70: */ } } /* 4) If SIM='T', apply similarity transformation. -1 Transform is X A X , where X = U S V, thus it is U S V A V' (1/S) U' */ if (isim != 0) { /* Compute S (singular values of the eigenvector matrix) according to CONDS and MODES */ slatm1_(modes, conds, &c__0, &c__0, &iseed[1], &ds[1], n, &iinfo); if (iinfo != 0) { *info = 3; return 0; } /* Multiply by V and V' */ slarge_(n, &a[a_offset], lda, &iseed[1], &work[1], &iinfo); if (iinfo != 0) { *info = 4; return 0; } /* Multiply by S and (1/S) */ i__1 = *n; for (j = 1; j <= i__1; ++j) { sscal_(n, &ds[j], &a_ref(j, 1), lda); if (ds[j] != 0.f) { r__1 = 1.f / ds[j]; sscal_(n, &r__1, &a_ref(1, j), &c__1); } else { *info = 5; return 0; } /* L80: */ } /* Multiply by U and U' */ slarge_(n, &a[a_offset], lda, &iseed[1], &work[1], &iinfo); if (iinfo != 0) { *info = 4; return 0; } } /* 5) Reduce the bandwidth. */ if (*kl < *n - 1) { /* Reduce bandwidth -- kill column */ i__1 = *n - 1; for (jcr = *kl + 1; jcr <= i__1; ++jcr) { ic = jcr - *kl; irows = *n + 1 - jcr; icols = *n + *kl - jcr; scopy_(&irows, &a_ref(jcr, ic), &c__1, &work[1], &c__1); xnorms = work[1]; slarfg_(&irows, &xnorms, &work[2], &c__1, &tau); work[1] = 1.f; sgemv_("T", &irows, &icols, &c_b39, &a_ref(jcr, ic + 1), lda, & work[1], &c__1, &c_b23, &work[irows + 1], &c__1); r__1 = -tau; sger_(&irows, &icols, &r__1, &work[1], &c__1, &work[irows + 1], & c__1, &a_ref(jcr, ic + 1), lda); sgemv_("N", n, &irows, &c_b39, &a_ref(1, jcr), lda, &work[1], & c__1, &c_b23, &work[irows + 1], &c__1); r__1 = -tau; sger_(n, &irows, &r__1, &work[irows + 1], &c__1, &work[1], &c__1, &a_ref(1, jcr), lda); a_ref(jcr, ic) = xnorms; i__2 = irows - 1; slaset_("Full", &i__2, &c__1, &c_b23, &c_b23, &a_ref(jcr + 1, ic), lda); /* L90: */ } } else if (*ku < *n - 1) { /* Reduce upper bandwidth -- kill a row at a time. */ i__1 = *n - 1; for (jcr = *ku + 1; jcr <= i__1; ++jcr) { ir = jcr - *ku; irows = *n + *ku - jcr; icols = *n + 1 - jcr; scopy_(&icols, &a_ref(ir, jcr), lda, &work[1], &c__1); xnorms = work[1]; slarfg_(&icols, &xnorms, &work[2], &c__1, &tau); work[1] = 1.f; sgemv_("N", &irows, &icols, &c_b39, &a_ref(ir + 1, jcr), lda, & work[1], &c__1, &c_b23, &work[icols + 1], &c__1); r__1 = -tau; sger_(&irows, &icols, &r__1, &work[icols + 1], &c__1, &work[1], & c__1, &a_ref(ir + 1, jcr), lda); sgemv_("C", &icols, n, &c_b39, &a_ref(jcr, 1), lda, &work[1], & c__1, &c_b23, &work[icols + 1], &c__1); r__1 = -tau; sger_(&icols, n, &r__1, &work[1], &c__1, &work[icols + 1], &c__1, &a_ref(jcr, 1), lda); a_ref(ir, jcr) = xnorms; i__2 = icols - 1; slaset_("Full", &c__1, &i__2, &c_b23, &c_b23, &a_ref(ir, jcr + 1), lda); /* L100: */ } } /* Scale the matrix to have norm ANORM */ if (*anorm >= 0.f) { temp = slange_("M", n, n, &a[a_offset], lda, tempa); if (temp > 0.f) { alpha = *anorm / temp; i__1 = *n; for (j = 1; j <= i__1; ++j) { sscal_(n, &alpha, &a_ref(1, j), &c__1); /* L110: */ } } } return 0; /* End of SLATME */ } /* slatme_ */
/* Complex */ VOID clarnd_(complex * ret_val, integer *idist, integer *iseed) { /* System generated locals */ doublereal d__1, d__2; complex q__1, q__2, q__3; /* Builtin functions */ double log(doublereal), sqrt(doublereal); void c_exp(complex *, complex *); /* Local variables */ static real t1, t2; extern doublereal slaran_(integer *); /* -- LAPACK auxiliary routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= CLARND returns a random complex number from a uniform or normal distribution. Arguments ========= IDIST (input) INTEGER Specifies the distribution of the random numbers: = 1: real and imaginary parts each uniform (0,1) = 2: real and imaginary parts each uniform (-1,1) = 3: real and imaginary parts each normal (0,1) = 4: uniformly distributed on the disc abs(z) <= 1 = 5: uniformly distributed on the circle abs(z) = 1 ISEED (input/output) INTEGER array, dimension (4) On entry, the seed of the random number generator; the array elements must be between 0 and 4095, and ISEED(4) must be odd. On exit, the seed is updated. Further Details =============== This routine calls the auxiliary routine SLARAN to generate a random real number from a uniform (0,1) distribution. The Box-Muller method is used to transform numbers from a uniform to a normal distribution. ===================================================================== Generate a pair of real random numbers from a uniform (0,1) distribution Parameter adjustments */ --iseed; /* Function Body */ t1 = slaran_(&iseed[1]); t2 = slaran_(&iseed[1]); if (*idist == 1) { /* real and imaginary parts each uniform (0,1) */ q__1.r = t1, q__1.i = t2; ret_val->r = q__1.r, ret_val->i = q__1.i; } else if (*idist == 2) { /* real and imaginary parts each uniform (-1,1) */ d__1 = t1 * 2.f - 1.f; d__2 = t2 * 2.f - 1.f; q__1.r = d__1, q__1.i = d__2; ret_val->r = q__1.r, ret_val->i = q__1.i; } else if (*idist == 3) { /* real and imaginary parts each normal (0,1) */ d__1 = sqrt(log(t1) * -2.f); d__2 = t2 * 6.2831853071795864769252867663f; q__3.r = 0.f, q__3.i = d__2; c_exp(&q__2, &q__3); q__1.r = d__1 * q__2.r, q__1.i = d__1 * q__2.i; ret_val->r = q__1.r, ret_val->i = q__1.i; } else if (*idist == 4) { /* uniform distribution on the unit disc abs(z) <= 1 */ d__1 = sqrt(t1); d__2 = t2 * 6.2831853071795864769252867663f; q__3.r = 0.f, q__3.i = d__2; c_exp(&q__2, &q__3); q__1.r = d__1 * q__2.r, q__1.i = d__1 * q__2.i; ret_val->r = q__1.r, ret_val->i = q__1.i; } else if (*idist == 5) { /* uniform distribution on the unit circle abs(z) = 1 */ d__1 = t2 * 6.2831853071795864769252867663f; q__2.r = 0.f, q__2.i = d__1; c_exp(&q__1, &q__2); ret_val->r = q__1.r, ret_val->i = q__1.i; } return ; /* End of CLARND */ } /* clarnd_ */
/* Subroutine */ int slatm1_(integer *mode, real *cond, integer *irsign, integer *idist, integer *iseed, real *d__, integer *n, integer *info) { /* System generated locals */ integer i__1, i__2; doublereal d__1, d__2; /* Builtin functions */ double pow_dd(doublereal *, doublereal *), pow_ri(real *, integer *), log( doublereal), exp(doublereal); /* Local variables */ integer i__; real temp, alpha; extern /* Subroutine */ int xerbla_(char *, integer *); extern doublereal slaran_(integer *); extern /* Subroutine */ int slarnv_(integer *, integer *, integer *, real *); /* -- LAPACK auxiliary test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SLATM1 computes the entries of D(1..N) as specified by */ /* MODE, COND and IRSIGN. IDIST and ISEED determine the generation */ /* of random numbers. SLATM1 is called by SLATMR to generate */ /* random test matrices for LAPACK programs. */ /* Arguments */ /* ========= */ /* MODE - INTEGER */ /* On entry describes how D is to be computed: */ /* MODE = 0 means do not change D. */ /* 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 - REAL */ /* On entry, used as described under MODE above. */ /* If used, it must be >= 1. Not modified. */ /* IRSIGN - INTEGER */ /* On entry, if MODE neither -6, 0 nor 6, determines sign of */ /* entries of D */ /* 0 => leave entries of D unchanged */ /* 1 => multiply each entry of D by 1 or -1 with probability .5 */ /* IDIST - CHARACTER*1 */ /* On entry, IDIST specifies the type of distribution to be */ /* used to generate a random matrix . */ /* 1 => UNIFORM( 0, 1 ) */ /* 2 => UNIFORM( -1, 1 ) */ /* 3 => NORMAL( 0, 1 ) */ /* Not modified. */ /* ISEED - INTEGER array, dimension ( 4 ) */ /* On entry ISEED specifies the seed of the random number */ /* generator. 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 SLATM1 */ /* to continue the same random number sequence. */ /* Changed on exit. */ /* D - REAL array, dimension ( MIN( M , N ) ) */ /* Array to be computed according to MODE, COND and IRSIGN. */ /* May be changed on exit if MODE is nonzero. */ /* N - INTEGER */ /* Number of entries of D. Not modified. */ /* INFO - INTEGER */ /* 0 => normal termination */ /* -1 => if MODE not in range -6 to 6 */ /* -2 => if MODE neither -6, 0 nor 6, and */ /* IRSIGN neither 0 nor 1 */ /* -3 => if MODE neither -6, 0 nor 6 and COND less than 1 */ /* -4 => if MODE equals 6 or -6 and IDIST not in range 1 to 3 */ /* -7 => if N negative */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Decode and Test the input parameters. Initialize flags & seed. */ /* Parameter adjustments */ --d__; --iseed; /* Function Body */ *info = 0; /* Quick return if possible */ if (*n == 0) { return 0; } /* Set INFO if an error */ if (*mode < -6 || *mode > 6) { *info = -1; } else if (*mode != -6 && *mode != 0 && *mode != 6 && (*irsign != 0 && * irsign != 1)) { *info = -2; } else if (*mode != -6 && *mode != 0 && *mode != 6 && *cond < 1.f) { *info = -3; } else if ((*mode == 6 || *mode == -6) && (*idist < 1 || *idist > 3)) { *info = -4; } else if (*n < 0) { *info = -7; } if (*info != 0) { i__1 = -(*info); xerbla_("SLATM1", &i__1); return 0; } /* Compute D according to COND and MODE */ if (*mode != 0) { switch (abs(*mode)) { case 1: goto L10; case 2: goto L30; case 3: goto L50; case 4: goto L70; case 5: goto L90; case 6: goto L110; } /* One large D value: */ L10: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = 1.f / *cond; /* L20: */ } d__[1] = 1.f; goto L120; /* One small D value: */ L30: i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = 1.f; /* L40: */ } d__[*n] = 1.f / *cond; goto L120; /* Exponentially distributed D values: */ L50: d__[1] = 1.f; if (*n > 1) { d__1 = (doublereal) (*cond); d__2 = (doublereal) (-1.f / (real) (*n - 1)); alpha = pow_dd(&d__1, &d__2); i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = i__ - 1; d__[i__] = pow_ri(&alpha, &i__2); /* L60: */ } } goto L120; /* Arithmetically distributed D values: */ L70: d__[1] = 1.f; if (*n > 1) { temp = 1.f / *cond; alpha = (1.f - temp) / (real) (*n - 1); i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { d__[i__] = (real) (*n - i__) * alpha + temp; /* L80: */ } } goto L120; /* Randomly distributed D values on ( 1/COND , 1): */ L90: alpha = log(1.f / *cond); i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { d__[i__] = exp(alpha * slaran_(&iseed[1])); /* L100: */ } goto L120; /* Randomly distributed D values from IDIST */ L110: slarnv_(idist, &iseed[1], n, &d__[1]); L120: /* If MODE neither -6 nor 0 nor 6, and IRSIGN = 1, assign */ /* random signs to D */ if (*mode != -6 && *mode != 0 && *mode != 6 && *irsign == 1) { i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { temp = slaran_(&iseed[1]); if (temp > .5f) { d__[i__] = -d__[i__]; } /* L130: */ } } /* Reverse if MODE < 0 */ if (*mode < 0) { i__1 = *n / 2; for (i__ = 1; i__ <= i__1; ++i__) { temp = d__[i__]; d__[i__] = d__[*n + 1 - i__]; d__[*n + 1 - i__] = temp; /* L140: */ } } } return 0; /* End of SLATM1 */ } /* slatm1_ */
doublereal slatm2_(integer *m, integer *n, integer *i__, integer *j, integer * kl, integer *ku, integer *idist, integer *iseed, real *d__, integer * igrade, real *dl, real *dr, integer *ipvtng, integer *iwork, real * sparse) { /* System generated locals */ real ret_val; /* Local variables */ static integer isub, jsub; static real temp; extern doublereal slaran_(integer *), slarnd_(integer *, integer *); /* -- LAPACK auxiliary 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 ======= SLATM2 returns the (I,J) entry of a random matrix of dimension (M, N) described by the other paramters. It is called by the SLATMR routine in order to build random test matrices. No error checking on parameters is done, because this routine is called in a tight loop by SLATMR which has already checked the parameters. Use of SLATM2 differs from SLATM3 in the order in which the random number generator is called to fill in random matrix entries. With SLATM2, the generator is called to fill in the pivoted matrix columnwise. With SLATM3, the generator is called to fill in the matrix columnwise, after which it is pivoted. Thus, SLATM3 can be used to construct random matrices which differ only in their order of rows and/or columns. SLATM2 is used to construct band matrices while avoiding calling the random number generator for entries outside the band (and therefore generating random numbers The matrix whose (I,J) entry is returned is constructed as follows (this routine only computes one entry): If I is outside (1..M) or J is outside (1..N), return zero (this is convenient for generating matrices in band format). Generate a matrix A with random entries of distribution IDIST. Set the diagonal to D. Grade the matrix, if desired, from the left (by DL) and/or from the right (by DR or DL) as specified by IGRADE. Permute, if desired, the rows and/or columns as specified by IPVTNG and IWORK. Band the matrix to have lower bandwidth KL and upper bandwidth KU. Set random entries to zero as specified by SPARSE. Arguments ========= M - INTEGER Number of rows of matrix. Not modified. N - INTEGER Number of columns of matrix. Not modified. I - INTEGER Row of entry to be returned. Not modified. J - INTEGER Column of entry to be returned. Not modified. KL - INTEGER Lower bandwidth. Not modified. KU - INTEGER Upper bandwidth. Not modified. IDIST - INTEGER On entry, IDIST specifies the type of distribution to be used to generate a random matrix . 1 => UNIFORM( 0, 1 ) 2 => UNIFORM( -1, 1 ) 3 => NORMAL( 0, 1 ) Not modified. ISEED - INTEGER array of dimension ( 4 ) Seed for random number generator. Changed on exit. D - REAL array of dimension ( MIN( I , J ) ) Diagonal entries of matrix. Not modified. IGRADE - INTEGER Specifies grading of matrix as follows: 0 => no grading 1 => matrix premultiplied by diag( DL ) 2 => matrix postmultiplied by diag( DR ) 3 => matrix premultiplied by diag( DL ) and postmultiplied by diag( DR ) 4 => matrix premultiplied by diag( DL ) and postmultiplied by inv( diag( DL ) ) 5 => matrix premultiplied by diag( DL ) and postmultiplied by diag( DL ) Not modified. DL - REAL array ( I or J, as appropriate ) Left scale factors for grading matrix. Not modified. DR - REAL array ( I or J, as appropriate ) Right scale factors for grading matrix. Not modified. IPVTNG - INTEGER On entry specifies pivoting permutations as follows: 0 => none. 1 => row pivoting. 2 => column pivoting. 3 => full pivoting, i.e., on both sides. Not modified. IWORK - INTEGER array ( I or J, as appropriate ) This array specifies the permutation used. The row (or column) in position K was originally in position IWORK( K ). This differs from IWORK for SLATM3. Not modified. SPARSE - REAL between 0. and 1. On entry specifies the sparsity of the matrix if sparse matix is to be generated. SPARSE should lie between 0 and 1. 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. ===================================================================== ----------------------------------------------------------------------- Check for I and J in range Parameter adjustments */ --iwork; --dr; --dl; --d__; --iseed; /* Function Body */ if (*i__ < 1 || *i__ > *m || *j < 1 || *j > *n) { ret_val = 0.f; return ret_val; } /* Check for banding */ if (*j > *i__ + *ku || *j < *i__ - *kl) { ret_val = 0.f; return ret_val; } /* Check for sparsity */ if (*sparse > 0.f) { if (slaran_(&iseed[1]) < *sparse) { ret_val = 0.f; return ret_val; } } /* Compute subscripts depending on IPVTNG */ if (*ipvtng == 0) { isub = *i__; jsub = *j; } else if (*ipvtng == 1) { isub = iwork[*i__]; jsub = *j; } else if (*ipvtng == 2) { isub = *i__; jsub = iwork[*j]; } else if (*ipvtng == 3) { isub = iwork[*i__]; jsub = iwork[*j]; } /* Compute entry and grade it according to IGRADE */ if (isub == jsub) { temp = d__[isub]; } else { temp = slarnd_(idist, &iseed[1]); } if (*igrade == 1) { temp *= dl[isub]; } else if (*igrade == 2) { temp *= dr[jsub]; } else if (*igrade == 3) { temp = temp * dl[isub] * dr[jsub]; } else if (*igrade == 4 && isub != jsub) { temp = temp * dl[isub] / dl[jsub]; } else if (*igrade == 5) { temp = temp * dl[isub] * dl[jsub]; } ret_val = temp; return ret_val; /* End of SLATM2 */ } /* slatm2_ */
/* Subroutine */ int clatm4_(integer *itype, integer *n, integer *nz1, integer *nz2, logical *rsign, real *amagn, real *rcond, real *triang, integer *idist, integer *iseed, complex *a, integer *lda) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; real r__1; doublereal d__1, d__2; complex q__1, q__2; /* Builtin functions */ double pow_dd(doublereal *, doublereal *), pow_ri(real *, integer *), log( doublereal), exp(doublereal), c_abs(complex *); /* Local variables */ static integer kbeg, isdb, kend, isde, klen, i__, k; static real alpha; static complex ctemp; static integer jc, jd, jr; extern /* Complex */ VOID clarnd_(complex *, integer *, integer *); extern /* Subroutine */ int claset_(char *, integer *, integer *, complex *, complex *, complex *, integer *); extern doublereal slaran_(integer *); #define a_subscr(a_1,a_2) (a_2)*a_dim1 + a_1 #define a_ref(a_1,a_2) a[a_subscr(a_1,a_2)] /* -- LAPACK auxiliary test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= CLATM4 generates basic square matrices, which may later be multiplied by others in order to produce test matrices. It is intended mainly to be used to test the generalized eigenvalue routines. It first generates the diagonal and (possibly) subdiagonal, according to the value of ITYPE, NZ1, NZ2, RSIGN, AMAGN, and RCOND. It then fills in the upper triangle with random numbers, if TRIANG is non-zero. Arguments ========= ITYPE (input) INTEGER The "type" of matrix on the diagonal and sub-diagonal. If ITYPE < 0, then type abs(ITYPE) is generated and then swapped end for end (A(I,J) := A'(N-J,N-I).) See also the description of AMAGN and RSIGN. Special types: = 0: the zero matrix. = 1: the identity. = 2: a transposed Jordan block. = 3: If N is odd, then a k+1 x k+1 transposed Jordan block followed by a k x k identity block, where k=(N-1)/2. If N is even, then k=(N-2)/2, and a zero diagonal entry is tacked onto the end. Diagonal types. The diagonal consists of NZ1 zeros, then k=N-NZ1-NZ2 nonzeros. The subdiagonal is zero. ITYPE specifies the nonzero diagonal entries as follows: = 4: 1, ..., k = 5: 1, RCOND, ..., RCOND = 6: 1, ..., 1, RCOND = 7: 1, a, a^2, ..., a^(k-1)=RCOND = 8: 1, 1-d, 1-2*d, ..., 1-(k-1)*d=RCOND = 9: random numbers chosen from (RCOND,1) = 10: random numbers with distribution IDIST (see CLARND.) N (input) INTEGER The order of the matrix. NZ1 (input) INTEGER If abs(ITYPE) > 3, then the first NZ1 diagonal entries will be zero. NZ2 (input) INTEGER If abs(ITYPE) > 3, then the last NZ2 diagonal entries will be zero. RSIGN (input) LOGICAL = .TRUE.: The diagonal and subdiagonal entries will be multiplied by random numbers of magnitude 1. = .FALSE.: The diagonal and subdiagonal entries will be left as they are (usually non-negative real.) AMAGN (input) REAL The diagonal and subdiagonal entries will be multiplied by AMAGN. RCOND (input) REAL If abs(ITYPE) > 4, then the smallest diagonal entry will be RCOND. RCOND must be between 0 and 1. TRIANG (input) REAL The entries above the diagonal will be random numbers with magnitude bounded by TRIANG (i.e., random numbers multiplied by TRIANG.) IDIST (input) INTEGER On entry, DIST specifies the type of distribution to be used to generate a random matrix . = 1: real and imaginary parts each UNIFORM( 0, 1 ) = 2: real and imaginary parts each UNIFORM( -1, 1 ) = 3: real and imaginary parts each NORMAL( 0, 1 ) = 4: complex number uniform in DISK( 0, 1 ) ISEED (input/output) INTEGER array, dimension (4) On entry ISEED specifies the seed of the random number generator. The values of ISEED are changed on exit, and can be used in the next call to CLATM4 to continue the same random number sequence. Note: ISEED(4) should be odd, for the random number generator used at present. A (output) COMPLEX array, dimension (LDA, N) Array to be computed. LDA (input) INTEGER Leading dimension of A. Must be at least 1 and at least N. ===================================================================== Parameter adjustments */ --iseed; a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; /* Function Body */ if (*n <= 0) { return 0; } claset_("Full", n, n, &c_b1, &c_b1, &a[a_offset], lda); /* Insure a correct ISEED */ if (iseed[4] % 2 != 1) { ++iseed[4]; } /* Compute diagonal and subdiagonal according to ITYPE, NZ1, NZ2, and RCOND */ if (*itype != 0) { if (abs(*itype) >= 4) { /* Computing MAX Computing MIN */ i__3 = *n, i__4 = *nz1 + 1; i__1 = 1, i__2 = min(i__3,i__4); kbeg = max(i__1,i__2); /* Computing MAX Computing MIN */ i__3 = *n, i__4 = *n - *nz2; i__1 = kbeg, i__2 = min(i__3,i__4); kend = max(i__1,i__2); klen = kend + 1 - kbeg; } else { kbeg = 1; kend = *n; klen = *n; } isdb = 1; isde = 0; switch (abs(*itype)) { case 1: goto L10; case 2: goto L30; case 3: goto L50; case 4: goto L80; case 5: goto L100; case 6: goto L120; case 7: goto L140; case 8: goto L160; case 9: goto L180; case 10: goto L200; } /* |ITYPE| = 1: Identity */ L10: i__1 = *n; for (jd = 1; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); a[i__2].r = 1.f, a[i__2].i = 0.f; /* L20: */ } goto L220; /* |ITYPE| = 2: Transposed Jordan block */ L30: i__1 = *n - 1; for (jd = 1; jd <= i__1; ++jd) { i__2 = a_subscr(jd + 1, jd); a[i__2].r = 1.f, a[i__2].i = 0.f; /* L40: */ } isdb = 1; isde = *n - 1; goto L220; /* |ITYPE| = 3: Transposed Jordan block, followed by the identity. */ L50: k = (*n - 1) / 2; i__1 = k; for (jd = 1; jd <= i__1; ++jd) { i__2 = a_subscr(jd + 1, jd); a[i__2].r = 1.f, a[i__2].i = 0.f; /* L60: */ } isdb = 1; isde = k; i__1 = (k << 1) + 1; for (jd = k + 2; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); a[i__2].r = 1.f, a[i__2].i = 0.f; /* L70: */ } goto L220; /* |ITYPE| = 4: 1,...,k */ L80: i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); i__3 = jd - *nz1; q__1.r = (real) i__3, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; /* L90: */ } goto L220; /* |ITYPE| = 5: One large D value: */ L100: i__1 = kend; for (jd = kbeg + 1; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); q__1.r = *rcond, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; /* L110: */ } i__1 = a_subscr(kbeg, kbeg); a[i__1].r = 1.f, a[i__1].i = 0.f; goto L220; /* |ITYPE| = 6: One small D value: */ L120: i__1 = kend - 1; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); a[i__2].r = 1.f, a[i__2].i = 0.f; /* L130: */ } i__1 = a_subscr(kend, kend); q__1.r = *rcond, q__1.i = 0.f; a[i__1].r = q__1.r, a[i__1].i = q__1.i; goto L220; /* |ITYPE| = 7: Exponentially distributed D values: */ L140: i__1 = a_subscr(kbeg, kbeg); a[i__1].r = 1.f, a[i__1].i = 0.f; if (klen > 1) { d__1 = (doublereal) (*rcond); d__2 = (doublereal) (1.f / (real) (klen - 1)); alpha = pow_dd(&d__1, &d__2); i__1 = klen; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = a_subscr(*nz1 + i__, *nz1 + i__); i__3 = i__ - 1; r__1 = pow_ri(&alpha, &i__3); q__1.r = r__1, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; /* L150: */ } } goto L220; /* |ITYPE| = 8: Arithmetically distributed D values: */ L160: i__1 = a_subscr(kbeg, kbeg); a[i__1].r = 1.f, a[i__1].i = 0.f; if (klen > 1) { alpha = (1.f - *rcond) / (real) (klen - 1); i__1 = klen; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = a_subscr(*nz1 + i__, *nz1 + i__); r__1 = (real) (klen - i__) * alpha + *rcond; q__1.r = r__1, q__1.i = 0.f; a[i__2].r = q__1.r, a[i__2].i = q__1.i; /* L170: */ } } goto L220; /* |ITYPE| = 9: Randomly distributed D values on ( RCOND, 1): */ L180: alpha = log(*rcond); i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); r__1 = exp(alpha * slaran_(&iseed[1])); a[i__2].r = r__1, a[i__2].i = 0.f; /* L190: */ } goto L220; /* |ITYPE| = 10: Randomly distributed D values from DIST */ L200: i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); clarnd_(&q__1, idist, &iseed[1]); a[i__2].r = q__1.r, a[i__2].i = q__1.i; /* L210: */ } L220: /* Scale by AMAGN */ i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); i__3 = a_subscr(jd, jd); r__1 = *amagn * a[i__3].r; a[i__2].r = r__1, a[i__2].i = 0.f; /* L230: */ } i__1 = isde; for (jd = isdb; jd <= i__1; ++jd) { i__2 = a_subscr(jd + 1, jd); i__3 = a_subscr(jd + 1, jd); r__1 = *amagn * a[i__3].r; a[i__2].r = r__1, a[i__2].i = 0.f; /* L240: */ } /* If RSIGN = .TRUE., assign random signs to diagonal and subdiagonal */ if (*rsign) { i__1 = kend; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); if (a[i__2].r != 0.f) { clarnd_(&q__1, &c__3, &iseed[1]); ctemp.r = q__1.r, ctemp.i = q__1.i; r__1 = c_abs(&ctemp); q__1.r = ctemp.r / r__1, q__1.i = ctemp.i / r__1; ctemp.r = q__1.r, ctemp.i = q__1.i; i__2 = a_subscr(jd, jd); i__3 = a_subscr(jd, jd); r__1 = a[i__3].r; q__1.r = r__1 * ctemp.r, q__1.i = r__1 * ctemp.i; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } /* L250: */ } i__1 = isde; for (jd = isdb; jd <= i__1; ++jd) { i__2 = a_subscr(jd + 1, jd); if (a[i__2].r != 0.f) { clarnd_(&q__1, &c__3, &iseed[1]); ctemp.r = q__1.r, ctemp.i = q__1.i; r__1 = c_abs(&ctemp); q__1.r = ctemp.r / r__1, q__1.i = ctemp.i / r__1; ctemp.r = q__1.r, ctemp.i = q__1.i; i__2 = a_subscr(jd + 1, jd); i__3 = a_subscr(jd + 1, jd); r__1 = a[i__3].r; q__1.r = r__1 * ctemp.r, q__1.i = r__1 * ctemp.i; a[i__2].r = q__1.r, a[i__2].i = q__1.i; } /* L260: */ } } /* Reverse if ITYPE < 0 */ if (*itype < 0) { i__1 = (kbeg + kend - 1) / 2; for (jd = kbeg; jd <= i__1; ++jd) { i__2 = a_subscr(jd, jd); ctemp.r = a[i__2].r, ctemp.i = a[i__2].i; i__2 = a_subscr(jd, jd); i__3 = a_subscr(kbeg + kend - jd, kbeg + kend - jd); a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i; i__2 = a_subscr(kbeg + kend - jd, kbeg + kend - jd); a[i__2].r = ctemp.r, a[i__2].i = ctemp.i; /* L270: */ } i__1 = (*n - 1) / 2; for (jd = 1; jd <= i__1; ++jd) { i__2 = a_subscr(jd + 1, jd); ctemp.r = a[i__2].r, ctemp.i = a[i__2].i; i__2 = a_subscr(jd + 1, jd); i__3 = a_subscr(*n + 1 - jd, *n - jd); a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i; i__2 = a_subscr(*n + 1 - jd, *n - jd); a[i__2].r = ctemp.r, a[i__2].i = ctemp.i; /* L280: */ } } } /* Fill in upper triangle */ if (*triang != 0.f) { i__1 = *n; for (jc = 2; jc <= i__1; ++jc) { i__2 = jc - 1; for (jr = 1; jr <= i__2; ++jr) { i__3 = a_subscr(jr, jc); clarnd_(&q__2, idist, &iseed[1]); q__1.r = *triang * q__2.r, q__1.i = *triang * q__2.i; a[i__3].r = q__1.r, a[i__3].i = q__1.i; /* L290: */ } /* L300: */ } } return 0; /* End of CLATM4 */ } /* clatm4_ */
/* Complex */ VOID clatm3_(complex * ret_val, integer *m, integer *n, integer *i, integer *j, integer *isub, integer *jsub, integer *kl, integer * ku, integer *idist, integer *iseed, complex *d, integer *igrade, complex *dl, complex *dr, integer *ipvtng, integer *iwork, real * sparse) { /* System generated locals */ integer i__1, i__2; complex q__1, q__2, q__3; /* Builtin functions */ void c_div(complex *, complex *, complex *), r_cnjg(complex *, complex *); /* Local variables */ static complex ctemp; extern /* Complex */ VOID clarnd_(complex *, integer *, integer *); extern doublereal slaran_(integer *); /* -- LAPACK auxiliary test routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University February 29, 1992 Purpose ======= CLATM3 returns the (ISUB,JSUB) entry of a random matrix of dimension (M, N) described by the other paramters. (ISUB,JSUB) is the final position of the (I,J) entry after pivoting according to IPVTNG and IWORK. CLATM3 is called by the CLATMR routine in order to build random test matrices. No error checking on parameters is done, because this routine is called in a tight loop by CLATMR which has already checked the parameters. Use of CLATM3 differs from CLATM2 in the order in which the random number generator is called to fill in random matrix entries. With CLATM2, the generator is called to fill in the pivoted matrix columnwise. With CLATM3, the generator is called to fill in the matrix columnwise, after which it is pivoted. Thus, CLATM3 can be used to construct random matrices which differ only in their order of rows and/or columns. CLATM2 is used to construct band matrices while avoiding calling the random number generator for entries outside the band (and therefore generating random numbers in different orders for different pivot orders). The matrix whose (ISUB,JSUB) entry is returned is constructed as follows (this routine only computes one entry): If ISUB is outside (1..M) or JSUB is outside (1..N), return zero (this is convenient for generating matrices in band format). Generate a matrix A with random entries of distribution IDIST. Set the diagonal to D. Grade the matrix, if desired, from the left (by DL) and/or from the right (by DR or DL) as specified by IGRADE. Permute, if desired, the rows and/or columns as specified by IPVTNG and IWORK. Band the matrix to have lower bandwidth KL and upper bandwidth KU. Set random entries to zero as specified by SPARSE. Arguments ========= M - INTEGER Number of rows of matrix. Not modified. N - INTEGER Number of columns of matrix. Not modified. I - INTEGER Row of unpivoted entry to be returned. Not modified. J - INTEGER Column of unpivoted entry to be returned. Not modified. ISUB - INTEGER Row of pivoted entry to be returned. Changed on exit. JSUB - INTEGER Column of pivoted entry to be returned. Changed on exit. KL - INTEGER Lower bandwidth. Not modified. KU - INTEGER Upper bandwidth. Not modified. IDIST - INTEGER On entry, IDIST specifies the type of distribution to be used to generate a random matrix . 1 => real and imaginary parts each UNIFORM( 0, 1 ) 2 => real and imaginary parts each UNIFORM( -1, 1 ) 3 => real and imaginary parts each NORMAL( 0, 1 ) 4 => complex number uniform in DISK( 0 , 1 ) Not modified. ISEED - INTEGER array of dimension ( 4 ) Seed for random number generator. Changed on exit. D - COMPLEX array of dimension ( MIN( I , J ) ) Diagonal entries of matrix. Not modified. IGRADE - INTEGER Specifies grading of matrix as follows: 0 => no grading 1 => matrix premultiplied by diag( DL ) 2 => matrix postmultiplied by diag( DR ) 3 => matrix premultiplied by diag( DL ) and postmultiplied by diag( DR ) 4 => matrix premultiplied by diag( DL ) and postmultiplied by inv( diag( DL ) ) 5 => matrix premultiplied by diag( DL ) and postmultiplied by diag( CONJG(DL) ) 6 => matrix premultiplied by diag( DL ) and postmultiplied by diag( DL ) Not modified. DL - COMPLEX array ( I or J, as appropriate ) Left scale factors for grading matrix. Not modified. DR - COMPLEX array ( I or J, as appropriate ) Right scale factors for grading matrix. Not modified. IPVTNG - INTEGER On entry specifies pivoting permutations as follows: 0 => none. 1 => row pivoting. 2 => column pivoting. 3 => full pivoting, i.e., on both sides. Not modified. IWORK - INTEGER array ( I or J, as appropriate ) This array specifies the permutation used. The row (or column) originally in position K is in position IWORK( K ) after pivoting. This differs from IWORK for CLATM2. Not modified. SPARSE - REAL between 0. and 1. On entry specifies the sparsity of the matrix if sparse matix is to be generated. SPARSE should lie between 0 and 1. 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. ===================================================================== ----------------------------------------------------------------------- Check for I and J in range Parameter adjustments */ --iwork; --dr; --dl; --d; --iseed; /* Function Body */ if (*i < 1 || *i > *m || *j < 1 || *j > *n) { *isub = *i; *jsub = *j; ret_val->r = 0.f, ret_val->i = 0.f; return ; } /* Compute subscripts depending on IPVTNG */ if (*ipvtng == 0) { *isub = *i; *jsub = *j; } else if (*ipvtng == 1) { *isub = iwork[*i]; *jsub = *j; } else if (*ipvtng == 2) { *isub = *i; *jsub = iwork[*j]; } else if (*ipvtng == 3) { *isub = iwork[*i]; *jsub = iwork[*j]; } /* Check for banding */ if (*jsub > *isub + *ku || *jsub < *isub - *kl) { ret_val->r = 0.f, ret_val->i = 0.f; return ; } /* Check for sparsity */ if (*sparse > 0.f) { if (slaran_(&iseed[1]) < *sparse) { ret_val->r = 0.f, ret_val->i = 0.f; return ; } } /* Compute entry and grade it according to IGRADE */ if (*i == *j) { i__1 = *i; ctemp.r = d[i__1].r, ctemp.i = d[i__1].i; } else { clarnd_(&q__1, idist, &iseed[1]); ctemp.r = q__1.r, ctemp.i = q__1.i; } if (*igrade == 1) { i__1 = *i; q__1.r = ctemp.r * dl[i__1].r - ctemp.i * dl[i__1].i, q__1.i = ctemp.r * dl[i__1].i + ctemp.i * dl[i__1].r; ctemp.r = q__1.r, ctemp.i = q__1.i; } else if (*igrade == 2) { i__1 = *j; q__1.r = ctemp.r * dr[i__1].r - ctemp.i * dr[i__1].i, q__1.i = ctemp.r * dr[i__1].i + ctemp.i * dr[i__1].r; ctemp.r = q__1.r, ctemp.i = q__1.i; } else if (*igrade == 3) { i__1 = *i; q__2.r = ctemp.r * dl[i__1].r - ctemp.i * dl[i__1].i, q__2.i = ctemp.r * dl[i__1].i + ctemp.i * dl[i__1].r; i__2 = *j; q__1.r = q__2.r * dr[i__2].r - q__2.i * dr[i__2].i, q__1.i = q__2.r * dr[i__2].i + q__2.i * dr[i__2].r; ctemp.r = q__1.r, ctemp.i = q__1.i; } else if (*igrade == 4 && *i != *j) { i__1 = *i; q__2.r = ctemp.r * dl[i__1].r - ctemp.i * dl[i__1].i, q__2.i = ctemp.r * dl[i__1].i + ctemp.i * dl[i__1].r; c_div(&q__1, &q__2, &dl[*j]); ctemp.r = q__1.r, ctemp.i = q__1.i; } else if (*igrade == 5) { i__1 = *i; q__2.r = ctemp.r * dl[i__1].r - ctemp.i * dl[i__1].i, q__2.i = ctemp.r * dl[i__1].i + ctemp.i * dl[i__1].r; r_cnjg(&q__3, &dl[*j]); q__1.r = q__2.r * q__3.r - q__2.i * q__3.i, q__1.i = q__2.r * q__3.i + q__2.i * q__3.r; ctemp.r = q__1.r, ctemp.i = q__1.i; } else if (*igrade == 6) { i__1 = *i; q__2.r = ctemp.r * dl[i__1].r - ctemp.i * dl[i__1].i, q__2.i = ctemp.r * dl[i__1].i + ctemp.i * dl[i__1].r; i__2 = *j; q__1.r = q__2.r * dl[i__2].r - q__2.i * dl[i__2].i, q__1.i = q__2.r * dl[i__2].i + q__2.i * dl[i__2].r; ctemp.r = q__1.r, ctemp.i = q__1.i; } ret_val->r = ctemp.r, ret_val->i = ctemp.i; return ; /* End of CLATM3 */ } /* clatm3_ */