3 /* Table of constant values */
5 static integer c__1 = 1;
6 static integer c_n1 = -1;
7 static integer c__2 = 2;
9 /* Subroutine */ int dormbr_(char *vect, char *side, char *trans, integer *m,
10 integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau,
11 doublereal *c__, integer *ldc, doublereal *work, integer *lwork,
14 /* System generated locals */
16 integer a_dim1, a_offset, c_dim1, c_offset, i__1, i__2, i__3[2];
19 /* Builtin functions */
20 /* Subroutine */ int s_cat(char *, char **, integer *, integer *, ftnlen);
23 integer i1, i2, nb, mi, ni, nq, nw;
25 extern logical lsame_(char *, char *);
27 extern /* Subroutine */ int xerbla_(char *, integer *);
28 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
29 integer *, integer *);
30 extern /* Subroutine */ int dormlq_(char *, char *, integer *, integer *,
31 integer *, doublereal *, integer *, doublereal *, doublereal *,
32 integer *, doublereal *, integer *, integer *);
34 extern /* Subroutine */ int dormqr_(char *, char *, integer *, integer *,
35 integer *, doublereal *, integer *, doublereal *, doublereal *,
36 integer *, doublereal *, integer *, integer *);
43 /* -- LAPACK routine (version 3.1) -- */
44 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
47 /* .. Scalar Arguments .. */
49 /* .. Array Arguments .. */
55 /* If VECT = 'Q', DORMBR overwrites the general real M-by-N matrix C */
57 /* SIDE = 'L' SIDE = 'R' */
58 /* TRANS = 'N': Q * C C * Q */
59 /* TRANS = 'T': Q**T * C C * Q**T */
61 /* If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C */
63 /* SIDE = 'L' SIDE = 'R' */
64 /* TRANS = 'N': P * C C * P */
65 /* TRANS = 'T': P**T * C C * P**T */
67 /* Here Q and P**T are the orthogonal matrices determined by DGEBRD when */
68 /* reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and */
69 /* P**T are defined as products of elementary reflectors H(i) and G(i) */
72 /* Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the */
73 /* order of the orthogonal matrix Q or P**T that is applied. */
75 /* If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: */
76 /* if nq >= k, Q = H(1) H(2) . . . H(k); */
77 /* if nq < k, Q = H(1) H(2) . . . H(nq-1). */
79 /* If VECT = 'P', A is assumed to have been a K-by-NQ matrix: */
80 /* if k < nq, P = G(1) G(2) . . . G(k); */
81 /* if k >= nq, P = G(1) G(2) . . . G(nq-1). */
86 /* VECT (input) CHARACTER*1 */
87 /* = 'Q': apply Q or Q**T; */
88 /* = 'P': apply P or P**T. */
90 /* SIDE (input) CHARACTER*1 */
91 /* = 'L': apply Q, Q**T, P or P**T from the Left; */
92 /* = 'R': apply Q, Q**T, P or P**T from the Right. */
94 /* TRANS (input) CHARACTER*1 */
95 /* = 'N': No transpose, apply Q or P; */
96 /* = 'T': Transpose, apply Q**T or P**T. */
98 /* M (input) INTEGER */
99 /* The number of rows of the matrix C. M >= 0. */
101 /* N (input) INTEGER */
102 /* The number of columns of the matrix C. N >= 0. */
104 /* K (input) INTEGER */
105 /* If VECT = 'Q', the number of columns in the original */
106 /* matrix reduced by DGEBRD. */
107 /* If VECT = 'P', the number of rows in the original */
108 /* matrix reduced by DGEBRD. */
111 /* A (input) DOUBLE PRECISION array, dimension */
112 /* (LDA,min(nq,K)) if VECT = 'Q' */
113 /* (LDA,nq) if VECT = 'P' */
114 /* The vectors which define the elementary reflectors H(i) and */
115 /* G(i), whose products determine the matrices Q and P, as */
116 /* returned by DGEBRD. */
118 /* LDA (input) INTEGER */
119 /* The leading dimension of the array A. */
120 /* If VECT = 'Q', LDA >= max(1,nq); */
121 /* if VECT = 'P', LDA >= max(1,min(nq,K)). */
123 /* TAU (input) DOUBLE PRECISION array, dimension (min(nq,K)) */
124 /* TAU(i) must contain the scalar factor of the elementary */
125 /* reflector H(i) or G(i) which determines Q or P, as returned */
126 /* by DGEBRD in the array argument TAUQ or TAUP. */
128 /* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) */
129 /* On entry, the M-by-N matrix C. */
130 /* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q */
131 /* or P*C or P**T*C or C*P or C*P**T. */
133 /* LDC (input) INTEGER */
134 /* The leading dimension of the array C. LDC >= max(1,M). */
136 /* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */
137 /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
139 /* LWORK (input) INTEGER */
140 /* The dimension of the array WORK. */
141 /* If SIDE = 'L', LWORK >= max(1,N); */
142 /* if SIDE = 'R', LWORK >= max(1,M). */
143 /* For optimum performance LWORK >= N*NB if SIDE = 'L', and */
144 /* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */
147 /* If LWORK = -1, then a workspace query is assumed; the routine */
148 /* only calculates the optimal size of the WORK array, returns */
149 /* this value as the first entry of the WORK array, and no error */
150 /* message related to LWORK is issued by XERBLA. */
152 /* INFO (output) INTEGER */
153 /* = 0: successful exit */
154 /* < 0: if INFO = -i, the i-th argument had an illegal value */
156 /* ===================================================================== */
158 /* .. Local Scalars .. */
160 /* .. External Functions .. */
162 /* .. External Subroutines .. */
164 /* .. Intrinsic Functions .. */
166 /* .. Executable Statements .. */
168 /* Test the input arguments */
170 /* Parameter adjustments */
172 a_offset = 1 + a_dim1;
176 c_offset = 1 + c_dim1;
182 applyq = lsame_(vect, "Q");
183 left = lsame_(side, "L");
184 notran = lsame_(trans, "N");
185 lquery = *lwork == -1;
187 /* NQ is the order of Q or P and NW is the minimum dimension of WORK */
196 if (! applyq && ! lsame_(vect, "P")) {
198 } else if (! left && ! lsame_(side, "R")) {
200 } else if (! notran && ! lsame_(trans, "T")) {
208 } else /* if(complicated condition) */ {
210 i__1 = 1, i__2 = min(nq,*k);
211 if (applyq && *lda < max(1,nq) || ! applyq && *lda < max(i__1,i__2)) {
213 } else if (*ldc < max(1,*m)) {
215 } else if (*lwork < max(1,nw) && ! lquery) {
223 /* Writing concatenation */
224 i__3[0] = 1, a__1[0] = side;
225 i__3[1] = 1, a__1[1] = trans;
226 s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2);
229 nb = ilaenv_(&c__1, "DORMQR", ch__1, &i__1, n, &i__2, &c_n1);
231 /* Writing concatenation */
232 i__3[0] = 1, a__1[0] = side;
233 i__3[1] = 1, a__1[1] = trans;
234 s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2);
237 nb = ilaenv_(&c__1, "DORMQR", ch__1, m, &i__1, &i__2, &c_n1);
241 /* Writing concatenation */
242 i__3[0] = 1, a__1[0] = side;
243 i__3[1] = 1, a__1[1] = trans;
244 s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2);
247 nb = ilaenv_(&c__1, "DORMLQ", ch__1, &i__1, n, &i__2, &c_n1);
249 /* Writing concatenation */
250 i__3[0] = 1, a__1[0] = side;
251 i__3[1] = 1, a__1[1] = trans;
252 s_cat(ch__1, a__1, i__3, &c__2, (ftnlen)2);
255 nb = ilaenv_(&c__1, "DORMLQ", ch__1, m, &i__1, &i__2, &c_n1);
258 lwkopt = max(1,nw) * nb;
259 work[1] = (doublereal) lwkopt;
264 xerbla_("DORMBR", &i__1);
270 /* Quick return if possible */
273 if (*m == 0 || *n == 0) {
283 /* Q was determined by a call to DGEBRD with nq >= k */
285 dormqr_(side, trans, m, n, k, &a[a_offset], lda, &tau[1], &c__[
286 c_offset], ldc, &work[1], lwork, &iinfo);
289 /* Q was determined by a call to DGEBRD with nq < k */
303 dormqr_(side, trans, &mi, &ni, &i__1, &a[a_dim1 + 2], lda, &tau[1]
304 , &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &iinfo);
311 *(unsigned char *)transt = 'T';
313 *(unsigned char *)transt = 'N';
317 /* P was determined by a call to DGEBRD with nq > k */
319 dormlq_(side, transt, m, n, k, &a[a_offset], lda, &tau[1], &c__[
320 c_offset], ldc, &work[1], lwork, &iinfo);
323 /* P was determined by a call to DGEBRD with nq <= k */
337 dormlq_(side, transt, &mi, &ni, &i__1, &a[(a_dim1 << 1) + 1], lda,
338 &tau[1], &c__[i1 + i2 * c_dim1], ldc, &work[1], lwork, &
342 work[1] = (doublereal) lwkopt;