Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / dlalsa.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static doublereal c_b7 = 1.;
6 static doublereal c_b8 = 0.;
7 static integer c__2 = 2;
8
9 /* Subroutine */ int dlalsa_(integer *icompq, integer *smlsiz, integer *n, 
10         integer *nrhs, doublereal *b, integer *ldb, doublereal *bx, integer *
11         ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *k, 
12         doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
13         poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
14         perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
15         work, integer *iwork, integer *info)
16 {
17     /* System generated locals */
18     integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, b_dim1, 
19             b_offset, bx_dim1, bx_offset, difl_dim1, difl_offset, difr_dim1, 
20             difr_offset, givnum_dim1, givnum_offset, poles_dim1, poles_offset,
21              u_dim1, u_offset, vt_dim1, vt_offset, z_dim1, z_offset, i__1, 
22             i__2;
23
24     /* Builtin functions */
25     integer pow_ii(integer *, integer *);
26
27     /* Local variables */
28     integer i__, j, i1, ic, lf, nd, ll, nl, nr, im1, nlf, nrf, lvl, ndb1, 
29             nlp1, lvl2, nrp1, nlvl, sqre;
30     extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, 
31             integer *, doublereal *, doublereal *, integer *, doublereal *, 
32             integer *, doublereal *, doublereal *, integer *);
33     integer inode, ndiml, ndimr;
34     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
35             doublereal *, integer *), dlals0_(integer *, integer *, integer *, 
36              integer *, integer *, doublereal *, integer *, doublereal *, 
37             integer *, integer *, integer *, integer *, integer *, doublereal 
38             *, integer *, doublereal *, doublereal *, doublereal *, 
39             doublereal *, integer *, doublereal *, doublereal *, doublereal *, 
40              integer *), dlasdt_(integer *, integer *, integer *, integer *, 
41             integer *, integer *, integer *), xerbla_(char *, integer *);
42
43
44 /*  -- LAPACK routine (version 3.1) -- */
45 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
46 /*     November 2006 */
47
48 /*     .. Scalar Arguments .. */
49 /*     .. */
50 /*     .. Array Arguments .. */
51 /*     .. */
52
53 /*  Purpose */
54 /*  ======= */
55
56 /*  DLALSA is an itermediate step in solving the least squares problem */
57 /*  by computing the SVD of the coefficient matrix in compact form (The */
58 /*  singular vectors are computed as products of simple orthorgonal */
59 /*  matrices.). */
60
61 /*  If ICOMPQ = 0, DLALSA applies the inverse of the left singular vector */
62 /*  matrix of an upper bidiagonal matrix to the right hand side; and if */
63 /*  ICOMPQ = 1, DLALSA applies the right singular vector matrix to the */
64 /*  right hand side. The singular vector matrices were generated in */
65 /*  compact form by DLALSA. */
66
67 /*  Arguments */
68 /*  ========= */
69
70
71 /*  ICOMPQ (input) INTEGER */
72 /*         Specifies whether the left or the right singular vector */
73 /*         matrix is involved. */
74 /*         = 0: Left singular vector matrix */
75 /*         = 1: Right singular vector matrix */
76
77 /*  SMLSIZ (input) INTEGER */
78 /*         The maximum size of the subproblems at the bottom of the */
79 /*         computation tree. */
80
81 /*  N      (input) INTEGER */
82 /*         The row and column dimensions of the upper bidiagonal matrix. */
83
84 /*  NRHS   (input) INTEGER */
85 /*         The number of columns of B and BX. NRHS must be at least 1. */
86
87 /*  B      (input/output) DOUBLE PRECISION array, dimension ( LDB, NRHS ) */
88 /*         On input, B contains the right hand sides of the least */
89 /*         squares problem in rows 1 through M. */
90 /*         On output, B contains the solution X in rows 1 through N. */
91
92 /*  LDB    (input) INTEGER */
93 /*         The leading dimension of B in the calling subprogram. */
94 /*         LDB must be at least max(1,MAX( M, N ) ). */
95
96 /*  BX     (output) DOUBLE PRECISION array, dimension ( LDBX, NRHS ) */
97 /*         On exit, the result of applying the left or right singular */
98 /*         vector matrix to B. */
99
100 /*  LDBX   (input) INTEGER */
101 /*         The leading dimension of BX. */
102
103 /*  U      (input) DOUBLE PRECISION array, dimension ( LDU, SMLSIZ ). */
104 /*         On entry, U contains the left singular vector matrices of all */
105 /*         subproblems at the bottom level. */
106
107 /*  LDU    (input) INTEGER, LDU = > N. */
108 /*         The leading dimension of arrays U, VT, DIFL, DIFR, */
109 /*         POLES, GIVNUM, and Z. */
110
111 /*  VT     (input) DOUBLE PRECISION array, dimension ( LDU, SMLSIZ+1 ). */
112 /*         On entry, VT' contains the right singular vector matrices of */
113 /*         all subproblems at the bottom level. */
114
115 /*  K      (input) INTEGER array, dimension ( N ). */
116
117 /*  DIFL   (input) DOUBLE PRECISION array, dimension ( LDU, NLVL ). */
118 /*         where NLVL = INT(log_2 (N/(SMLSIZ+1))) + 1. */
119
120 /*  DIFR   (input) DOUBLE PRECISION array, dimension ( LDU, 2 * NLVL ). */
121 /*         On entry, DIFL(*, I) and DIFR(*, 2 * I -1) record */
122 /*         distances between singular values on the I-th level and */
123 /*         singular values on the (I -1)-th level, and DIFR(*, 2 * I) */
124 /*         record the normalizing factors of the right singular vectors */
125 /*         matrices of subproblems on I-th level. */
126
127 /*  Z      (input) DOUBLE PRECISION array, dimension ( LDU, NLVL ). */
128 /*         On entry, Z(1, I) contains the components of the deflation- */
129 /*         adjusted updating row vector for subproblems on the I-th */
130 /*         level. */
131
132 /*  POLES  (input) DOUBLE PRECISION array, dimension ( LDU, 2 * NLVL ). */
133 /*         On entry, POLES(*, 2 * I -1: 2 * I) contains the new and old */
134 /*         singular values involved in the secular equations on the I-th */
135 /*         level. */
136
137 /*  GIVPTR (input) INTEGER array, dimension ( N ). */
138 /*         On entry, GIVPTR( I ) records the number of Givens */
139 /*         rotations performed on the I-th problem on the computation */
140 /*         tree. */
141
142 /*  GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 * NLVL ). */
143 /*         On entry, for each I, GIVCOL(*, 2 * I - 1: 2 * I) records the */
144 /*         locations of Givens rotations performed on the I-th level on */
145 /*         the computation tree. */
146
147 /*  LDGCOL (input) INTEGER, LDGCOL = > N. */
148 /*         The leading dimension of arrays GIVCOL and PERM. */
149
150 /*  PERM   (input) INTEGER array, dimension ( LDGCOL, NLVL ). */
151 /*         On entry, PERM(*, I) records permutations done on the I-th */
152 /*         level of the computation tree. */
153
154 /*  GIVNUM (input) DOUBLE PRECISION array, dimension ( LDU, 2 * NLVL ). */
155 /*         On entry, GIVNUM(*, 2 *I -1 : 2 * I) records the C- and S- */
156 /*         values of Givens rotations performed on the I-th level on the */
157 /*         computation tree. */
158
159 /*  C      (input) DOUBLE PRECISION array, dimension ( N ). */
160 /*         On entry, if the I-th subproblem is not square, */
161 /*         C( I ) contains the C-value of a Givens rotation related to */
162 /*         the right null space of the I-th subproblem. */
163
164 /*  S      (input) DOUBLE PRECISION array, dimension ( N ). */
165 /*         On entry, if the I-th subproblem is not square, */
166 /*         S( I ) contains the S-value of a Givens rotation related to */
167 /*         the right null space of the I-th subproblem. */
168
169 /*  WORK   (workspace) DOUBLE PRECISION array. */
170 /*         The dimension must be at least N. */
171
172 /*  IWORK  (workspace) INTEGER array. */
173 /*         The dimension must be at least 3 * N */
174
175 /*  INFO   (output) INTEGER */
176 /*          = 0:  successful exit. */
177 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
178
179 /*  Further Details */
180 /*  =============== */
181
182 /*  Based on contributions by */
183 /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
184 /*       California at Berkeley, USA */
185 /*     Osni Marques, LBNL/NERSC, USA */
186
187 /*  ===================================================================== */
188
189 /*     .. Parameters .. */
190 /*     .. */
191 /*     .. Local Scalars .. */
192 /*     .. */
193 /*     .. External Subroutines .. */
194 /*     .. */
195 /*     .. Executable Statements .. */
196
197 /*     Test the input parameters. */
198
199     /* Parameter adjustments */
200     b_dim1 = *ldb;
201     b_offset = 1 + b_dim1;
202     b -= b_offset;
203     bx_dim1 = *ldbx;
204     bx_offset = 1 + bx_dim1;
205     bx -= bx_offset;
206     givnum_dim1 = *ldu;
207     givnum_offset = 1 + givnum_dim1;
208     givnum -= givnum_offset;
209     poles_dim1 = *ldu;
210     poles_offset = 1 + poles_dim1;
211     poles -= poles_offset;
212     z_dim1 = *ldu;
213     z_offset = 1 + z_dim1;
214     z__ -= z_offset;
215     difr_dim1 = *ldu;
216     difr_offset = 1 + difr_dim1;
217     difr -= difr_offset;
218     difl_dim1 = *ldu;
219     difl_offset = 1 + difl_dim1;
220     difl -= difl_offset;
221     vt_dim1 = *ldu;
222     vt_offset = 1 + vt_dim1;
223     vt -= vt_offset;
224     u_dim1 = *ldu;
225     u_offset = 1 + u_dim1;
226     u -= u_offset;
227     --k;
228     --givptr;
229     perm_dim1 = *ldgcol;
230     perm_offset = 1 + perm_dim1;
231     perm -= perm_offset;
232     givcol_dim1 = *ldgcol;
233     givcol_offset = 1 + givcol_dim1;
234     givcol -= givcol_offset;
235     --c__;
236     --s;
237     --work;
238     --iwork;
239
240     /* Function Body */
241     *info = 0;
242
243     if (*icompq < 0 || *icompq > 1) {
244         *info = -1;
245     } else if (*smlsiz < 3) {
246         *info = -2;
247     } else if (*n < *smlsiz) {
248         *info = -3;
249     } else if (*nrhs < 1) {
250         *info = -4;
251     } else if (*ldb < *n) {
252         *info = -6;
253     } else if (*ldbx < *n) {
254         *info = -8;
255     } else if (*ldu < *n) {
256         *info = -10;
257     } else if (*ldgcol < *n) {
258         *info = -19;
259     }
260     if (*info != 0) {
261         i__1 = -(*info);
262         xerbla_("DLALSA", &i__1);
263         return 0;
264     }
265
266 /*     Book-keeping and  setting up the computation tree. */
267
268     inode = 1;
269     ndiml = inode + *n;
270     ndimr = ndiml + *n;
271
272     dlasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr], 
273             smlsiz);
274
275 /*     The following code applies back the left singular vector factors. */
276 /*     For applying back the right singular vector factors, go to 50. */
277
278     if (*icompq == 1) {
279         goto L50;
280     }
281
282 /*     The nodes on the bottom level of the tree were solved */
283 /*     by DLASDQ. The corresponding left and right singular vector */
284 /*     matrices are in explicit form. First apply back the left */
285 /*     singular vector matrices. */
286
287     ndb1 = (nd + 1) / 2;
288     i__1 = nd;
289     for (i__ = ndb1; i__ <= i__1; ++i__) {
290
291 /*        IC : center row of each node */
292 /*        NL : number of rows of left  subproblem */
293 /*        NR : number of rows of right subproblem */
294 /*        NLF: starting row of the left   subproblem */
295 /*        NRF: starting row of the right  subproblem */
296
297         i1 = i__ - 1;
298         ic = iwork[inode + i1];
299         nl = iwork[ndiml + i1];
300         nr = iwork[ndimr + i1];
301         nlf = ic - nl;
302         nrf = ic + 1;
303         dgemm_("T", "N", &nl, nrhs, &nl, &c_b7, &u[nlf + u_dim1], ldu, &b[nlf 
304                 + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
305         dgemm_("T", "N", &nr, nrhs, &nr, &c_b7, &u[nrf + u_dim1], ldu, &b[nrf 
306                 + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
307 /* L10: */
308     }
309
310 /*     Next copy the rows of B that correspond to unchanged rows */
311 /*     in the bidiagonal matrix to BX. */
312
313     i__1 = nd;
314     for (i__ = 1; i__ <= i__1; ++i__) {
315         ic = iwork[inode + i__ - 1];
316         dcopy_(nrhs, &b[ic + b_dim1], ldb, &bx[ic + bx_dim1], ldbx);
317 /* L20: */
318     }
319
320 /*     Finally go through the left singular vector matrices of all */
321 /*     the other subproblems bottom-up on the tree. */
322
323     j = pow_ii(&c__2, &nlvl);
324     sqre = 0;
325
326     for (lvl = nlvl; lvl >= 1; --lvl) {
327         lvl2 = (lvl << 1) - 1;
328
329 /*        find the first node LF and last node LL on */
330 /*        the current level LVL */
331
332         if (lvl == 1) {
333             lf = 1;
334             ll = 1;
335         } else {
336             i__1 = lvl - 1;
337             lf = pow_ii(&c__2, &i__1);
338             ll = (lf << 1) - 1;
339         }
340         i__1 = ll;
341         for (i__ = lf; i__ <= i__1; ++i__) {
342             im1 = i__ - 1;
343             ic = iwork[inode + im1];
344             nl = iwork[ndiml + im1];
345             nr = iwork[ndimr + im1];
346             nlf = ic - nl;
347             nrf = ic + 1;
348             --j;
349             dlals0_(icompq, &nl, &nr, &sqre, nrhs, &bx[nlf + bx_dim1], ldbx, &
350                     b[nlf + b_dim1], ldb, &perm[nlf + lvl * perm_dim1], &
351                     givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
352                     givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
353                      poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf + 
354                     lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
355                     j], &s[j], &work[1], info);
356 /* L30: */
357         }
358 /* L40: */
359     }
360     goto L90;
361
362 /*     ICOMPQ = 1: applying back the right singular vector factors. */
363
364 L50:
365
366 /*     First now go through the right singular vector matrices of all */
367 /*     the tree nodes top-down. */
368
369     j = 0;
370     i__1 = nlvl;
371     for (lvl = 1; lvl <= i__1; ++lvl) {
372         lvl2 = (lvl << 1) - 1;
373
374 /*        Find the first node LF and last node LL on */
375 /*        the current level LVL. */
376
377         if (lvl == 1) {
378             lf = 1;
379             ll = 1;
380         } else {
381             i__2 = lvl - 1;
382             lf = pow_ii(&c__2, &i__2);
383             ll = (lf << 1) - 1;
384         }
385         i__2 = lf;
386         for (i__ = ll; i__ >= i__2; --i__) {
387             im1 = i__ - 1;
388             ic = iwork[inode + im1];
389             nl = iwork[ndiml + im1];
390             nr = iwork[ndimr + im1];
391             nlf = ic - nl;
392             nrf = ic + 1;
393             if (i__ == ll) {
394                 sqre = 0;
395             } else {
396                 sqre = 1;
397             }
398             ++j;
399             dlals0_(icompq, &nl, &nr, &sqre, nrhs, &b[nlf + b_dim1], ldb, &bx[
400                     nlf + bx_dim1], ldbx, &perm[nlf + lvl * perm_dim1], &
401                     givptr[j], &givcol[nlf + lvl2 * givcol_dim1], ldgcol, &
402                     givnum[nlf + lvl2 * givnum_dim1], ldu, &poles[nlf + lvl2 *
403                      poles_dim1], &difl[nlf + lvl * difl_dim1], &difr[nlf + 
404                     lvl2 * difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[
405                     j], &s[j], &work[1], info);
406 /* L60: */
407         }
408 /* L70: */
409     }
410
411 /*     The nodes on the bottom level of the tree were solved */
412 /*     by DLASDQ. The corresponding right singular vector */
413 /*     matrices are in explicit form. Apply them back. */
414
415     ndb1 = (nd + 1) / 2;
416     i__1 = nd;
417     for (i__ = ndb1; i__ <= i__1; ++i__) {
418         i1 = i__ - 1;
419         ic = iwork[inode + i1];
420         nl = iwork[ndiml + i1];
421         nr = iwork[ndimr + i1];
422         nlp1 = nl + 1;
423         if (i__ == nd) {
424             nrp1 = nr;
425         } else {
426             nrp1 = nr + 1;
427         }
428         nlf = ic - nl;
429         nrf = ic + 1;
430         dgemm_("T", "N", &nlp1, nrhs, &nlp1, &c_b7, &vt[nlf + vt_dim1], ldu, &
431                 b[nlf + b_dim1], ldb, &c_b8, &bx[nlf + bx_dim1], ldbx);
432         dgemm_("T", "N", &nrp1, nrhs, &nrp1, &c_b7, &vt[nrf + vt_dim1], ldu, &
433                 b[nrf + b_dim1], ldb, &c_b8, &bx[nrf + bx_dim1], ldbx);
434 /* L80: */
435     }
436
437 L90:
438
439     return 0;
440
441 /*     End of DLALSA */
442
443 } /* dlalsa_ */