Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / sorgqr.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 sorgqr_(integer *m, integer *n, integer *k, real *a, 
11         integer *lda, real *tau, real *work, integer *lwork, integer *info)
12 {
13     /* System generated locals */
14     integer a_dim1, a_offset, i__1, i__2, i__3;
15
16     /* Local variables */
17     integer i__, j, l, ib, nb, ki, kk, nx, iws, nbmin, iinfo;
18     extern /* Subroutine */ int sorg2r_(integer *, integer *, integer *, real 
19             *, integer *, real *, real *, integer *), slarfb_(char *, char *, 
20             char *, char *, integer *, integer *, integer *, real *, integer *
21 , real *, integer *, real *, integer *, real *, integer *), xerbla_(char *, integer *);
22     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
23             integer *, integer *);
24     extern /* Subroutine */ int slarft_(char *, char *, integer *, integer *, 
25             real *, integer *, real *, real *, integer *);
26     integer ldwork, lwkopt;
27     logical lquery;
28
29
30 /*  -- LAPACK routine (version 3.1) -- */
31 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
32 /*     November 2006 */
33
34 /*     .. Scalar Arguments .. */
35 /*     .. */
36 /*     .. Array Arguments .. */
37 /*     .. */
38
39 /*  Purpose */
40 /*  ======= */
41
42 /*  SORGQR generates an M-by-N real matrix Q with orthonormal columns, */
43 /*  which is defined as the first N columns of a product of K elementary */
44 /*  reflectors of order M */
45
46 /*        Q  =  H(1) H(2) . . . H(k) */
47
48 /*  as returned by SGEQRF. */
49
50 /*  Arguments */
51 /*  ========= */
52
53 /*  M       (input) INTEGER */
54 /*          The number of rows of the matrix Q. M >= 0. */
55
56 /*  N       (input) INTEGER */
57 /*          The number of columns of the matrix Q. M >= N >= 0. */
58
59 /*  K       (input) INTEGER */
60 /*          The number of elementary reflectors whose product defines the */
61 /*          matrix Q. N >= K >= 0. */
62
63 /*  A       (input/output) REAL array, dimension (LDA,N) */
64 /*          On entry, the i-th column must contain the vector which */
65 /*          defines the elementary reflector H(i), for i = 1,2,...,k, as */
66 /*          returned by SGEQRF in the first k columns of its array */
67 /*          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) REAL array, dimension (K) */
74 /*          TAU(i) must contain the scalar factor of the elementary */
75 /*          reflector H(i), as returned by SGEQRF. */
76
77 /*  WORK    (workspace/output) REAL 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,N). */
82 /*          For optimum performance LWORK >= N*NB, where NB is the */
83 /*          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, "SORGQR", " ", m, n, k, &c_n1);
120     lwkopt = max(1,*n) * nb;
121     work[1] = (real) lwkopt;
122     lquery = *lwork == -1;
123     if (*m < 0) {
124         *info = -1;
125     } else if (*n < 0 || *n > *m) {
126         *info = -2;
127     } else if (*k < 0 || *k > *n) {
128         *info = -3;
129     } else if (*lda < max(1,*m)) {
130         *info = -5;
131     } else if (*lwork < max(1,*n) && ! lquery) {
132         *info = -8;
133     }
134     if (*info != 0) {
135         i__1 = -(*info);
136         xerbla_("SORGQR", &i__1);
137         return 0;
138     } else if (lquery) {
139         return 0;
140     }
141
142 /*     Quick return if possible */
143
144     if (*n <= 0) {
145         work[1] = 1.f;
146         return 0;
147     }
148
149     nbmin = 2;
150     nx = 0;
151     iws = *n;
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, "SORGQR", " ", 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 = *n;
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, "SORGQR", " ", 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 columns 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(1:kk,kk+1:n) to zero. */
189
190         i__1 = *n;
191         for (j = kk + 1; j <= i__1; ++j) {
192             i__2 = kk;
193             for (i__ = 1; i__ <= i__2; ++i__) {
194                 a[i__ + j * a_dim1] = 0.f;
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 < *n) {
206         i__1 = *m - kk;
207         i__2 = *n - kk;
208         i__3 = *k - kk;
209         sorg2r_(&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 <= *n) {
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 = *m - i__ + 1;
228                 slarft_("Forward", "Columnwise", &i__2, &ib, &a[i__ + i__ * 
229                         a_dim1], lda, &tau[i__], &work[1], &ldwork);
230
231 /*              Apply H to A(i:m,i+ib:n) from the left */
232
233                 i__2 = *m - i__ + 1;
234                 i__3 = *n - i__ - ib + 1;
235                 slarfb_("Left", "No transpose", "Forward", "Columnwise", &
236                         i__2, &i__3, &ib, &a[i__ + i__ * a_dim1], lda, &work[
237                         1], &ldwork, &a[i__ + (i__ + ib) * a_dim1], lda, &
238                         work[ib + 1], &ldwork);
239             }
240
241 /*           Apply H to rows i:m of current block */
242
243             i__2 = *m - i__ + 1;
244             sorg2r_(&i__2, &ib, &ib, &a[i__ + i__ * a_dim1], lda, &tau[i__], &
245                     work[1], &iinfo);
246
247 /*           Set rows 1:i-1 of current block to zero */
248
249             i__2 = i__ + ib - 1;
250             for (j = i__; j <= i__2; ++j) {
251                 i__3 = i__ - 1;
252                 for (l = 1; l <= i__3; ++l) {
253                     a[l + j * a_dim1] = 0.f;
254 /* L30: */
255                 }
256 /* L40: */
257             }
258 /* L50: */
259         }
260     }
261
262     work[1] = (real) iws;
263     return 0;
264
265 /*     End of SORGQR */
266
267 } /* sorgqr_ */