Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / dorglq.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static integer c__1 = 1;
6 static integer c_n1 = -1;
7 static integer c__3 = 3;
8 static integer c__2 = 2;
9
10 /* Subroutine */ int dorglq_(integer *m, integer *n, integer *k, doublereal *
11         a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
12         integer *info)
13 {
14     /* System generated locals */
15     integer a_dim1, a_offset, i__1, i__2, i__3;
16
17     /* Local variables */
18     integer i__, j, l, ib, nb, ki, kk, nx, iws, nbmin, iinfo;
19     extern /* Subroutine */ int dorgl2_(integer *, integer *, integer *, 
20             doublereal *, integer *, doublereal *, doublereal *, integer *), 
21             dlarfb_(char *, char *, char *, char *, integer *, integer *, 
22             integer *, doublereal *, integer *, doublereal *, integer *, 
23             doublereal *, integer *, doublereal *, integer *), dlarft_(char *, char *, integer *, integer *, 
24             doublereal *, integer *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *);
25     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
26             integer *, integer *);
27     integer ldwork, lwkopt;
28     logical lquery;
29
30
31 /*  -- LAPACK routine (version 3.1) -- */
32 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
33 /*     November 2006 */
34
35 /*     .. Scalar Arguments .. */
36 /*     .. */
37 /*     .. Array Arguments .. */
38 /*     .. */
39
40 /*  Purpose */
41 /*  ======= */
42
43 /*  DORGLQ generates an M-by-N real matrix Q with orthonormal rows, */
44 /*  which is defined as the first M rows of a product of K elementary */
45 /*  reflectors of order N */
46
47 /*        Q  =  H(k) . . . H(2) H(1) */
48
49 /*  as returned by DGELQF. */
50
51 /*  Arguments */
52 /*  ========= */
53
54 /*  M       (input) INTEGER */
55 /*          The number of rows of the matrix Q. M >= 0. */
56
57 /*  N       (input) INTEGER */
58 /*          The number of columns of the matrix Q. N >= M. */
59
60 /*  K       (input) INTEGER */
61 /*          The number of elementary reflectors whose product defines the */
62 /*          matrix Q. M >= K >= 0. */
63
64 /*  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N) */
65 /*          On entry, the i-th row must contain the vector which defines */
66 /*          the elementary reflector H(i), for i = 1,2,...,k, as returned */
67 /*          by DGELQF in the first k rows of its array argument A. */
68 /*          On exit, the M-by-N matrix Q. */
69
70 /*  LDA     (input) INTEGER */
71 /*          The first dimension of the array A. LDA >= max(1,M). */
72
73 /*  TAU     (input) DOUBLE PRECISION array, dimension (K) */
74 /*          TAU(i) must contain the scalar factor of the elementary */
75 /*          reflector H(i), as returned by DGELQF. */
76
77 /*  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */
78 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
79
80 /*  LWORK   (input) INTEGER */
81 /*          The dimension of the array WORK. LWORK >= max(1,M). */
82 /*          For optimum performance LWORK >= M*NB, where NB is */
83 /*          the optimal blocksize. */
84
85 /*          If LWORK = -1, then a workspace query is assumed; the routine */
86 /*          only calculates the optimal size of the WORK array, returns */
87 /*          this value as the first entry of the WORK array, and no error */
88 /*          message related to LWORK is issued by XERBLA. */
89
90 /*  INFO    (output) INTEGER */
91 /*          = 0:  successful exit */
92 /*          < 0:  if INFO = -i, the i-th argument has an illegal value */
93
94 /*  ===================================================================== */
95
96 /*     .. Parameters .. */
97 /*     .. */
98 /*     .. Local Scalars .. */
99 /*     .. */
100 /*     .. External Subroutines .. */
101 /*     .. */
102 /*     .. Intrinsic Functions .. */
103 /*     .. */
104 /*     .. External Functions .. */
105 /*     .. */
106 /*     .. Executable Statements .. */
107
108 /*     Test the input arguments */
109
110     /* Parameter adjustments */
111     a_dim1 = *lda;
112     a_offset = 1 + a_dim1;
113     a -= a_offset;
114     --tau;
115     --work;
116
117     /* Function Body */
118     *info = 0;
119     nb = ilaenv_(&c__1, "DORGLQ", " ", m, n, k, &c_n1);
120     lwkopt = max(1,*m) * nb;
121     work[1] = (doublereal) lwkopt;
122     lquery = *lwork == -1;
123     if (*m < 0) {
124         *info = -1;
125     } else if (*n < *m) {
126         *info = -2;
127     } else if (*k < 0 || *k > *m) {
128         *info = -3;
129     } else if (*lda < max(1,*m)) {
130         *info = -5;
131     } else if (*lwork < max(1,*m) && ! lquery) {
132         *info = -8;
133     }
134     if (*info != 0) {
135         i__1 = -(*info);
136         xerbla_("DORGLQ", &i__1);
137         return 0;
138     } else if (lquery) {
139         return 0;
140     }
141
142 /*     Quick return if possible */
143
144     if (*m <= 0) {
145         work[1] = 1.;
146         return 0;
147     }
148
149     nbmin = 2;
150     nx = 0;
151     iws = *m;
152     if (nb > 1 && nb < *k) {
153
154 /*        Determine when to cross over from blocked to unblocked code. */
155
156 /* Computing MAX */
157         i__1 = 0, i__2 = ilaenv_(&c__3, "DORGLQ", " ", m, n, k, &c_n1);
158         nx = max(i__1,i__2);
159         if (nx < *k) {
160
161 /*           Determine if workspace is large enough for blocked code. */
162
163             ldwork = *m;
164             iws = ldwork * nb;
165             if (*lwork < iws) {
166
167 /*              Not enough workspace to use optimal NB:  reduce NB and */
168 /*              determine the minimum value of NB. */
169
170                 nb = *lwork / ldwork;
171 /* Computing MAX */
172                 i__1 = 2, i__2 = ilaenv_(&c__2, "DORGLQ", " ", m, n, k, &c_n1);
173                 nbmin = max(i__1,i__2);
174             }
175         }
176     }
177
178     if (nb >= nbmin && nb < *k && nx < *k) {
179
180 /*        Use blocked code after the last block. */
181 /*        The first kk rows are handled by the block method. */
182
183         ki = (*k - nx - 1) / nb * nb;
184 /* Computing MIN */
185         i__1 = *k, i__2 = ki + nb;
186         kk = min(i__1,i__2);
187
188 /*        Set A(kk+1:m,1:kk) to zero. */
189
190         i__1 = kk;
191         for (j = 1; j <= i__1; ++j) {
192             i__2 = *m;
193             for (i__ = kk + 1; i__ <= i__2; ++i__) {
194                 a[i__ + j * a_dim1] = 0.;
195 /* L10: */
196             }
197 /* L20: */
198         }
199     } else {
200         kk = 0;
201     }
202
203 /*     Use unblocked code for the last or only block. */
204
205     if (kk < *m) {
206         i__1 = *m - kk;
207         i__2 = *n - kk;
208         i__3 = *k - kk;
209         dorgl2_(&i__1, &i__2, &i__3, &a[kk + 1 + (kk + 1) * a_dim1], lda, &
210                 tau[kk + 1], &work[1], &iinfo);
211     }
212
213     if (kk > 0) {
214
215 /*        Use blocked code */
216
217         i__1 = -nb;
218         for (i__ = ki + 1; i__1 < 0 ? i__ >= 1 : i__ <= 1; i__ += i__1) {
219 /* Computing MIN */
220             i__2 = nb, i__3 = *k - i__ + 1;
221             ib = min(i__2,i__3);
222             if (i__ + ib <= *m) {
223
224 /*              Form the triangular factor of the block reflector */
225 /*              H = H(i) H(i+1) . . . H(i+ib-1) */
226
227                 i__2 = *n - i__ + 1;
228                 dlarft_("Forward", "Rowwise", &i__2, &ib, &a[i__ + i__ * 
229                         a_dim1], lda, &tau[i__], &work[1], &ldwork);
230
231 /*              Apply H' to A(i+ib:m,i:n) from the right */
232
233                 i__2 = *m - i__ - ib + 1;
234                 i__3 = *n - i__ + 1;
235                 dlarfb_("Right", "Transpose", "Forward", "Rowwise", &i__2, &
236                         i__3, &ib, &a[i__ + i__ * a_dim1], lda, &work[1], &
237                         ldwork, &a[i__ + ib + i__ * a_dim1], lda, &work[ib + 
238                         1], &ldwork);
239             }
240
241 /*           Apply H' to columns i:n of current block */
242
243             i__2 = *n - i__ + 1;
244             dorgl2_(&ib, &i__2, &ib, &a[i__ + i__ * a_dim1], lda, &tau[i__], &
245                     work[1], &iinfo);
246
247 /*           Set columns 1:i-1 of current block to zero */
248
249             i__2 = i__ - 1;
250             for (j = 1; j <= i__2; ++j) {
251                 i__3 = i__ + ib - 1;
252                 for (l = i__; l <= i__3; ++l) {
253                     a[l + j * a_dim1] = 0.;
254 /* L30: */
255                 }
256 /* L40: */
257             }
258 /* L50: */
259         }
260     }
261
262     work[1] = (doublereal) iws;
263     return 0;
264
265 /*     End of DORGLQ */
266
267 } /* dorglq_ */