00001 /* dtzrzf.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 integer c__1 = 1; 00019 static integer c_n1 = -1; 00020 static integer c__3 = 3; 00021 static integer c__2 = 2; 00022 00023 /* Subroutine */ int dtzrzf_(integer *m, integer *n, doublereal *a, integer * 00024 lda, doublereal *tau, doublereal *work, integer *lwork, integer *info) 00025 { 00026 /* System generated locals */ 00027 integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5; 00028 00029 /* Local variables */ 00030 integer i__, m1, ib, nb, ki, kk, mu, nx, iws, nbmin; 00031 extern /* Subroutine */ int xerbla_(char *, integer *), dlarzb_( 00032 char *, char *, char *, char *, integer *, integer *, integer *, 00033 integer *, doublereal *, integer *, doublereal *, integer *, 00034 doublereal *, integer *, doublereal *, integer *); 00035 extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 00036 integer *, integer *); 00037 extern /* Subroutine */ int dlarzt_(char *, char *, integer *, integer *, 00038 doublereal *, integer *, doublereal *, doublereal *, integer *), dlatrz_(integer *, integer *, integer *, 00039 doublereal *, integer *, doublereal *, doublereal *); 00040 integer ldwork, lwkopt; 00041 logical lquery; 00042 00043 00044 /* -- LAPACK routine (version 3.2) -- */ 00045 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00046 /* November 2006 */ 00047 00048 /* .. Scalar Arguments .. */ 00049 /* .. */ 00050 /* .. Array Arguments .. */ 00051 /* .. */ 00052 00053 /* Purpose */ 00054 /* ======= */ 00055 00056 /* DTZRZF reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A */ 00057 /* to upper triangular form by means of orthogonal transformations. */ 00058 00059 /* The upper trapezoidal matrix A is factored as */ 00060 00061 /* A = ( R 0 ) * Z, */ 00062 00063 /* where Z is an N-by-N orthogonal matrix and R is an M-by-M upper */ 00064 /* triangular matrix. */ 00065 00066 /* Arguments */ 00067 /* ========= */ 00068 00069 /* M (input) INTEGER */ 00070 /* The number of rows of the matrix A. M >= 0. */ 00071 00072 /* N (input) INTEGER */ 00073 /* The number of columns of the matrix A. N >= M. */ 00074 00075 /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ 00076 /* On entry, the leading M-by-N upper trapezoidal part of the */ 00077 /* array A must contain the matrix to be factorized. */ 00078 /* On exit, the leading M-by-M upper triangular part of A */ 00079 /* contains the upper triangular matrix R, and elements M+1 to */ 00080 /* N of the first M rows of A, with the array TAU, represent the */ 00081 /* orthogonal matrix Z as a product of M elementary reflectors. */ 00082 00083 /* LDA (input) INTEGER */ 00084 /* The leading dimension of the array A. LDA >= max(1,M). */ 00085 00086 /* TAU (output) DOUBLE PRECISION array, dimension (M) */ 00087 /* The scalar factors of the elementary reflectors. */ 00088 00089 /* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ 00090 /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ 00091 00092 /* LWORK (input) INTEGER */ 00093 /* The dimension of the array WORK. LWORK >= max(1,M). */ 00094 /* For optimum performance LWORK >= M*NB, where NB is */ 00095 /* the optimal blocksize. */ 00096 00097 /* If LWORK = -1, then a workspace query is assumed; the routine */ 00098 /* only calculates the optimal size of the WORK array, returns */ 00099 /* this value as the first entry of the WORK array, and no error */ 00100 /* message related to LWORK is issued by XERBLA. */ 00101 00102 /* INFO (output) INTEGER */ 00103 /* = 0: successful exit */ 00104 /* < 0: if INFO = -i, the i-th argument had an illegal value */ 00105 00106 /* Further Details */ 00107 /* =============== */ 00108 00109 /* Based on contributions by */ 00110 /* A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA */ 00111 00112 /* The factorization is obtained by Householder's method. The kth */ 00113 /* transformation matrix, Z( k ), which is used to introduce zeros into */ 00114 /* the ( m - k + 1 )th row of A, is given in the form */ 00115 00116 /* Z( k ) = ( I 0 ), */ 00117 /* ( 0 T( k ) ) */ 00118 00119 /* where */ 00120 00121 /* T( k ) = I - tau*u( k )*u( k )', u( k ) = ( 1 ), */ 00122 /* ( 0 ) */ 00123 /* ( z( k ) ) */ 00124 00125 /* tau is a scalar and z( k ) is an ( n - m ) element vector. */ 00126 /* tau and z( k ) are chosen to annihilate the elements of the kth row */ 00127 /* of X. */ 00128 00129 /* The scalar tau is returned in the kth element of TAU and the vector */ 00130 /* u( k ) in the kth row of A, such that the elements of z( k ) are */ 00131 /* in a( k, m + 1 ), ..., a( k, n ). The elements of R are returned in */ 00132 /* the upper triangular part of A. */ 00133 00134 /* Z is given by */ 00135 00136 /* Z = Z( 1 ) * Z( 2 ) * ... * Z( m ). */ 00137 00138 /* ===================================================================== */ 00139 00140 /* .. Parameters .. */ 00141 /* .. */ 00142 /* .. Local Scalars .. */ 00143 /* .. */ 00144 /* .. External Subroutines .. */ 00145 /* .. */ 00146 /* .. Intrinsic Functions .. */ 00147 /* .. */ 00148 /* .. External Functions .. */ 00149 /* .. */ 00150 /* .. Executable Statements .. */ 00151 00152 /* Test the input arguments */ 00153 00154 /* Parameter adjustments */ 00155 a_dim1 = *lda; 00156 a_offset = 1 + a_dim1; 00157 a -= a_offset; 00158 --tau; 00159 --work; 00160 00161 /* Function Body */ 00162 *info = 0; 00163 lquery = *lwork == -1; 00164 if (*m < 0) { 00165 *info = -1; 00166 } else if (*n < *m) { 00167 *info = -2; 00168 } else if (*lda < max(1,*m)) { 00169 *info = -4; 00170 } 00171 00172 if (*info == 0) { 00173 if (*m == 0 || *m == *n) { 00174 lwkopt = 1; 00175 } else { 00176 00177 /* Determine the block size. */ 00178 00179 nb = ilaenv_(&c__1, "DGERQF", " ", m, n, &c_n1, &c_n1); 00180 lwkopt = *m * nb; 00181 } 00182 work[1] = (doublereal) lwkopt; 00183 00184 if (*lwork < max(1,*m) && ! lquery) { 00185 *info = -7; 00186 } 00187 } 00188 00189 if (*info != 0) { 00190 i__1 = -(*info); 00191 xerbla_("DTZRZF", &i__1); 00192 return 0; 00193 } else if (lquery) { 00194 return 0; 00195 } 00196 00197 /* Quick return if possible */ 00198 00199 if (*m == 0) { 00200 return 0; 00201 } else if (*m == *n) { 00202 i__1 = *n; 00203 for (i__ = 1; i__ <= i__1; ++i__) { 00204 tau[i__] = 0.; 00205 /* L10: */ 00206 } 00207 return 0; 00208 } 00209 00210 nbmin = 2; 00211 nx = 1; 00212 iws = *m; 00213 if (nb > 1 && nb < *m) { 00214 00215 /* Determine when to cross over from blocked to unblocked code. */ 00216 00217 /* Computing MAX */ 00218 i__1 = 0, i__2 = ilaenv_(&c__3, "DGERQF", " ", m, n, &c_n1, &c_n1); 00219 nx = max(i__1,i__2); 00220 if (nx < *m) { 00221 00222 /* Determine if workspace is large enough for blocked code. */ 00223 00224 ldwork = *m; 00225 iws = ldwork * nb; 00226 if (*lwork < iws) { 00227 00228 /* Not enough workspace to use optimal NB: reduce NB and */ 00229 /* determine the minimum value of NB. */ 00230 00231 nb = *lwork / ldwork; 00232 /* Computing MAX */ 00233 i__1 = 2, i__2 = ilaenv_(&c__2, "DGERQF", " ", m, n, &c_n1, & 00234 c_n1); 00235 nbmin = max(i__1,i__2); 00236 } 00237 } 00238 } 00239 00240 if (nb >= nbmin && nb < *m && nx < *m) { 00241 00242 /* Use blocked code initially. */ 00243 /* The last kk rows are handled by the block method. */ 00244 00245 /* Computing MIN */ 00246 i__1 = *m + 1; 00247 m1 = min(i__1,*n); 00248 ki = (*m - nx - 1) / nb * nb; 00249 /* Computing MIN */ 00250 i__1 = *m, i__2 = ki + nb; 00251 kk = min(i__1,i__2); 00252 00253 i__1 = *m - kk + 1; 00254 i__2 = -nb; 00255 for (i__ = *m - kk + ki + 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; 00256 i__ += i__2) { 00257 /* Computing MIN */ 00258 i__3 = *m - i__ + 1; 00259 ib = min(i__3,nb); 00260 00261 /* Compute the TZ factorization of the current block */ 00262 /* A(i:i+ib-1,i:n) */ 00263 00264 i__3 = *n - i__ + 1; 00265 i__4 = *n - *m; 00266 dlatrz_(&ib, &i__3, &i__4, &a[i__ + i__ * a_dim1], lda, &tau[i__], 00267 &work[1]); 00268 if (i__ > 1) { 00269 00270 /* Form the triangular factor of the block reflector */ 00271 /* H = H(i+ib-1) . . . H(i+1) H(i) */ 00272 00273 i__3 = *n - *m; 00274 dlarzt_("Backward", "Rowwise", &i__3, &ib, &a[i__ + m1 * 00275 a_dim1], lda, &tau[i__], &work[1], &ldwork); 00276 00277 /* Apply H to A(1:i-1,i:n) from the right */ 00278 00279 i__3 = i__ - 1; 00280 i__4 = *n - i__ + 1; 00281 i__5 = *n - *m; 00282 dlarzb_("Right", "No transpose", "Backward", "Rowwise", &i__3, 00283 &i__4, &ib, &i__5, &a[i__ + m1 * a_dim1], lda, &work[ 00284 1], &ldwork, &a[i__ * a_dim1 + 1], lda, &work[ib + 1], 00285 &ldwork) 00286 ; 00287 } 00288 /* L20: */ 00289 } 00290 mu = i__ + nb - 1; 00291 } else { 00292 mu = *m; 00293 } 00294 00295 /* Use unblocked code to factor the last or only block */ 00296 00297 if (mu > 0) { 00298 i__2 = *n - *m; 00299 dlatrz_(&mu, n, &i__2, &a[a_offset], lda, &tau[1], &work[1]); 00300 } 00301 00302 work[1] = (doublereal) lwkopt; 00303 00304 return 0; 00305 00306 /* End of DTZRZF */ 00307 00308 } /* dtzrzf_ */