Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / slals0.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static real c_b5 = -1.f;
6 static integer c__1 = 1;
7 static real c_b11 = 1.f;
8 static real c_b13 = 0.f;
9 static integer c__0 = 0;
10
11 /* Subroutine */ int slals0_(integer *icompq, integer *nl, integer *nr, 
12         integer *sqre, integer *nrhs, real *b, integer *ldb, real *bx, 
13         integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
14         integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
15         difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
16         work, integer *info)
17 {
18     /* System generated locals */
19     integer givcol_dim1, givcol_offset, b_dim1, b_offset, bx_dim1, bx_offset, 
20             difr_dim1, difr_offset, givnum_dim1, givnum_offset, poles_dim1, 
21             poles_offset, i__1, i__2;
22     real r__1;
23
24     /* Local variables */
25     integer i__, j, m, n;
26     real dj;
27     integer nlp1;
28     real temp;
29     extern /* Subroutine */ int srot_(integer *, real *, integer *, real *, 
30             integer *, real *, real *);
31     extern doublereal snrm2_(integer *, real *, integer *);
32     real diflj, difrj, dsigj;
33     extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *), 
34             sgemv_(char *, integer *, integer *, real *, real *, integer *, 
35             real *, integer *, real *, real *, integer *), scopy_(
36             integer *, real *, integer *, real *, integer *);
37     extern doublereal slamc3_(real *, real *);
38     extern /* Subroutine */ int xerbla_(char *, integer *);
39     real dsigjp;
40     extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *, 
41             real *, integer *, integer *, real *, integer *, integer *), slacpy_(char *, integer *, integer *, real *, integer *, 
42             real *, integer *);
43
44
45 /*  -- LAPACK routine (version 3.1) -- */
46 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
47 /*     November 2006 */
48
49 /*     .. Scalar Arguments .. */
50 /*     .. */
51 /*     .. Array Arguments .. */
52 /*     .. */
53
54 /*  Purpose */
55 /*  ======= */
56
57 /*  SLALS0 applies back the multiplying factors of either the left or the */
58 /*  right singular vector matrix of a diagonal matrix appended by a row */
59 /*  to the right hand side matrix B in solving the least squares problem */
60 /*  using the divide-and-conquer SVD approach. */
61
62 /*  For the left singular vector matrix, three types of orthogonal */
63 /*  matrices are involved: */
64
65 /*  (1L) Givens rotations: the number of such rotations is GIVPTR; the */
66 /*       pairs of columns/rows they were applied to are stored in GIVCOL; */
67 /*       and the C- and S-values of these rotations are stored in GIVNUM. */
68
69 /*  (2L) Permutation. The (NL+1)-st row of B is to be moved to the first */
70 /*       row, and for J=2:N, PERM(J)-th row of B is to be moved to the */
71 /*       J-th row. */
72
73 /*  (3L) The left singular vector matrix of the remaining matrix. */
74
75 /*  For the right singular vector matrix, four types of orthogonal */
76 /*  matrices are involved: */
77
78 /*  (1R) The right singular vector matrix of the remaining matrix. */
79
80 /*  (2R) If SQRE = 1, one extra Givens rotation to generate the right */
81 /*       null space. */
82
83 /*  (3R) The inverse transformation of (2L). */
84
85 /*  (4R) The inverse transformation of (1L). */
86
87 /*  Arguments */
88 /*  ========= */
89
90 /*  ICOMPQ (input) INTEGER */
91 /*         Specifies whether singular vectors are to be computed in */
92 /*         factored form: */
93 /*         = 0: Left singular vector matrix. */
94 /*         = 1: Right singular vector matrix. */
95
96 /*  NL     (input) INTEGER */
97 /*         The row dimension of the upper block. NL >= 1. */
98
99 /*  NR     (input) INTEGER */
100 /*         The row dimension of the lower block. NR >= 1. */
101
102 /*  SQRE   (input) INTEGER */
103 /*         = 0: the lower block is an NR-by-NR square matrix. */
104 /*         = 1: the lower block is an NR-by-(NR+1) rectangular matrix. */
105
106 /*         The bidiagonal matrix has row dimension N = NL + NR + 1, */
107 /*         and column dimension M = N + SQRE. */
108
109 /*  NRHS   (input) INTEGER */
110 /*         The number of columns of B and BX. NRHS must be at least 1. */
111
112 /*  B      (input/output) REAL array, dimension ( LDB, NRHS ) */
113 /*         On input, B contains the right hand sides of the least */
114 /*         squares problem in rows 1 through M. On output, B contains */
115 /*         the solution X in rows 1 through N. */
116
117 /*  LDB    (input) INTEGER */
118 /*         The leading dimension of B. LDB must be at least */
119 /*         max(1,MAX( M, N ) ). */
120
121 /*  BX     (workspace) REAL array, dimension ( LDBX, NRHS ) */
122
123 /*  LDBX   (input) INTEGER */
124 /*         The leading dimension of BX. */
125
126 /*  PERM   (input) INTEGER array, dimension ( N ) */
127 /*         The permutations (from deflation and sorting) applied */
128 /*         to the two blocks. */
129
130 /*  GIVPTR (input) INTEGER */
131 /*         The number of Givens rotations which took place in this */
132 /*         subproblem. */
133
134 /*  GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 ) */
135 /*         Each pair of numbers indicates a pair of rows/columns */
136 /*         involved in a Givens rotation. */
137
138 /*  LDGCOL (input) INTEGER */
139 /*         The leading dimension of GIVCOL, must be at least N. */
140
141 /*  GIVNUM (input) REAL array, dimension ( LDGNUM, 2 ) */
142 /*         Each number indicates the C or S value used in the */
143 /*         corresponding Givens rotation. */
144
145 /*  LDGNUM (input) INTEGER */
146 /*         The leading dimension of arrays DIFR, POLES and */
147 /*         GIVNUM, must be at least K. */
148
149 /*  POLES  (input) REAL array, dimension ( LDGNUM, 2 ) */
150 /*         On entry, POLES(1:K, 1) contains the new singular */
151 /*         values obtained from solving the secular equation, and */
152 /*         POLES(1:K, 2) is an array containing the poles in the secular */
153 /*         equation. */
154
155 /*  DIFL   (input) REAL array, dimension ( K ). */
156 /*         On entry, DIFL(I) is the distance between I-th updated */
157 /*         (undeflated) singular value and the I-th (undeflated) old */
158 /*         singular value. */
159
160 /*  DIFR   (input) REAL array, dimension ( LDGNUM, 2 ). */
161 /*         On entry, DIFR(I, 1) contains the distances between I-th */
162 /*         updated (undeflated) singular value and the I+1-th */
163 /*         (undeflated) old singular value. And DIFR(I, 2) is the */
164 /*         normalizing factor for the I-th right singular vector. */
165
166 /*  Z      (input) REAL array, dimension ( K ) */
167 /*         Contain the components of the deflation-adjusted updating row */
168 /*         vector. */
169
170 /*  K      (input) INTEGER */
171 /*         Contains the dimension of the non-deflated matrix, */
172 /*         This is the order of the related secular equation. 1 <= K <=N. */
173
174 /*  C      (input) REAL */
175 /*         C contains garbage if SQRE =0 and the C-value of a Givens */
176 /*         rotation related to the right null space if SQRE = 1. */
177
178 /*  S      (input) REAL */
179 /*         S contains garbage if SQRE =0 and the S-value of a Givens */
180 /*         rotation related to the right null space if SQRE = 1. */
181
182 /*  WORK   (workspace) REAL array, dimension ( K ) */
183
184 /*  INFO   (output) INTEGER */
185 /*          = 0:  successful exit. */
186 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
187
188 /*  Further Details */
189 /*  =============== */
190
191 /*  Based on contributions by */
192 /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
193 /*       California at Berkeley, USA */
194 /*     Osni Marques, LBNL/NERSC, USA */
195
196 /*  ===================================================================== */
197
198 /*     .. Parameters .. */
199 /*     .. */
200 /*     .. Local Scalars .. */
201 /*     .. */
202 /*     .. External Subroutines .. */
203 /*     .. */
204 /*     .. External Functions .. */
205 /*     .. */
206 /*     .. Intrinsic Functions .. */
207 /*     .. */
208 /*     .. Executable Statements .. */
209
210 /*     Test the input parameters. */
211
212     /* Parameter adjustments */
213     b_dim1 = *ldb;
214     b_offset = 1 + b_dim1;
215     b -= b_offset;
216     bx_dim1 = *ldbx;
217     bx_offset = 1 + bx_dim1;
218     bx -= bx_offset;
219     --perm;
220     givcol_dim1 = *ldgcol;
221     givcol_offset = 1 + givcol_dim1;
222     givcol -= givcol_offset;
223     difr_dim1 = *ldgnum;
224     difr_offset = 1 + difr_dim1;
225     difr -= difr_offset;
226     poles_dim1 = *ldgnum;
227     poles_offset = 1 + poles_dim1;
228     poles -= poles_offset;
229     givnum_dim1 = *ldgnum;
230     givnum_offset = 1 + givnum_dim1;
231     givnum -= givnum_offset;
232     --difl;
233     --z__;
234     --work;
235
236     /* Function Body */
237     *info = 0;
238
239     if (*icompq < 0 || *icompq > 1) {
240         *info = -1;
241     } else if (*nl < 1) {
242         *info = -2;
243     } else if (*nr < 1) {
244         *info = -3;
245     } else if (*sqre < 0 || *sqre > 1) {
246         *info = -4;
247     }
248
249     n = *nl + *nr + 1;
250
251     if (*nrhs < 1) {
252         *info = -5;
253     } else if (*ldb < n) {
254         *info = -7;
255     } else if (*ldbx < n) {
256         *info = -9;
257     } else if (*givptr < 0) {
258         *info = -11;
259     } else if (*ldgcol < n) {
260         *info = -13;
261     } else if (*ldgnum < n) {
262         *info = -15;
263     } else if (*k < 1) {
264         *info = -20;
265     }
266     if (*info != 0) {
267         i__1 = -(*info);
268         xerbla_("SLALS0", &i__1);
269         return 0;
270     }
271
272     m = n + *sqre;
273     nlp1 = *nl + 1;
274
275     if (*icompq == 0) {
276
277 /*        Apply back orthogonal transformations from the left. */
278
279 /*        Step (1L): apply back the Givens rotations performed. */
280
281         i__1 = *givptr;
282         for (i__ = 1; i__ <= i__1; ++i__) {
283             srot_(nrhs, &b[givcol[i__ + (givcol_dim1 << 1)] + b_dim1], ldb, &
284                     b[givcol[i__ + givcol_dim1] + b_dim1], ldb, &givnum[i__ + 
285                     (givnum_dim1 << 1)], &givnum[i__ + givnum_dim1]);
286 /* L10: */
287         }
288
289 /*        Step (2L): permute rows of B. */
290
291         scopy_(nrhs, &b[nlp1 + b_dim1], ldb, &bx[bx_dim1 + 1], ldbx);
292         i__1 = n;
293         for (i__ = 2; i__ <= i__1; ++i__) {
294             scopy_(nrhs, &b[perm[i__] + b_dim1], ldb, &bx[i__ + bx_dim1], 
295                     ldbx);
296 /* L20: */
297         }
298
299 /*        Step (3L): apply the inverse of the left singular vector */
300 /*        matrix to BX. */
301
302         if (*k == 1) {
303             scopy_(nrhs, &bx[bx_offset], ldbx, &b[b_offset], ldb);
304             if (z__[1] < 0.f) {
305                 sscal_(nrhs, &c_b5, &b[b_offset], ldb);
306             }
307         } else {
308             i__1 = *k;
309             for (j = 1; j <= i__1; ++j) {
310                 diflj = difl[j];
311                 dj = poles[j + poles_dim1];
312                 dsigj = -poles[j + (poles_dim1 << 1)];
313                 if (j < *k) {
314                     difrj = -difr[j + difr_dim1];
315                     dsigjp = -poles[j + 1 + (poles_dim1 << 1)];
316                 }
317                 if (z__[j] == 0.f || poles[j + (poles_dim1 << 1)] == 0.f) {
318                     work[j] = 0.f;
319                 } else {
320                     work[j] = -poles[j + (poles_dim1 << 1)] * z__[j] / diflj /
321                              (poles[j + (poles_dim1 << 1)] + dj);
322                 }
323                 i__2 = j - 1;
324                 for (i__ = 1; i__ <= i__2; ++i__) {
325                     if (z__[i__] == 0.f || poles[i__ + (poles_dim1 << 1)] == 
326                             0.f) {
327                         work[i__] = 0.f;
328                     } else {
329                         work[i__] = poles[i__ + (poles_dim1 << 1)] * z__[i__] 
330                                 / (slamc3_(&poles[i__ + (poles_dim1 << 1)], &
331                                 dsigj) - diflj) / (poles[i__ + (poles_dim1 << 
332                                 1)] + dj);
333                     }
334 /* L30: */
335                 }
336                 i__2 = *k;
337                 for (i__ = j + 1; i__ <= i__2; ++i__) {
338                     if (z__[i__] == 0.f || poles[i__ + (poles_dim1 << 1)] == 
339                             0.f) {
340                         work[i__] = 0.f;
341                     } else {
342                         work[i__] = poles[i__ + (poles_dim1 << 1)] * z__[i__] 
343                                 / (slamc3_(&poles[i__ + (poles_dim1 << 1)], &
344                                 dsigjp) + difrj) / (poles[i__ + (poles_dim1 <<
345                                  1)] + dj);
346                     }
347 /* L40: */
348                 }
349                 work[1] = -1.f;
350                 temp = snrm2_(k, &work[1], &c__1);
351                 sgemv_("T", k, nrhs, &c_b11, &bx[bx_offset], ldbx, &work[1], &
352                         c__1, &c_b13, &b[j + b_dim1], ldb);
353                 slascl_("G", &c__0, &c__0, &temp, &c_b11, &c__1, nrhs, &b[j + 
354                         b_dim1], ldb, info);
355 /* L50: */
356             }
357         }
358
359 /*        Move the deflated rows of BX to B also. */
360
361         if (*k < max(m,n)) {
362             i__1 = n - *k;
363             slacpy_("A", &i__1, nrhs, &bx[*k + 1 + bx_dim1], ldbx, &b[*k + 1 
364                     + b_dim1], ldb);
365         }
366     } else {
367
368 /*        Apply back the right orthogonal transformations. */
369
370 /*        Step (1R): apply back the new right singular vector matrix */
371 /*        to B. */
372
373         if (*k == 1) {
374             scopy_(nrhs, &b[b_offset], ldb, &bx[bx_offset], ldbx);
375         } else {
376             i__1 = *k;
377             for (j = 1; j <= i__1; ++j) {
378                 dsigj = poles[j + (poles_dim1 << 1)];
379                 if (z__[j] == 0.f) {
380                     work[j] = 0.f;
381                 } else {
382                     work[j] = -z__[j] / difl[j] / (dsigj + poles[j + 
383                             poles_dim1]) / difr[j + (difr_dim1 << 1)];
384                 }
385                 i__2 = j - 1;
386                 for (i__ = 1; i__ <= i__2; ++i__) {
387                     if (z__[j] == 0.f) {
388                         work[i__] = 0.f;
389                     } else {
390                         r__1 = -poles[i__ + 1 + (poles_dim1 << 1)];
391                         work[i__] = z__[j] / (slamc3_(&dsigj, &r__1) - difr[
392                                 i__ + difr_dim1]) / (dsigj + poles[i__ + 
393                                 poles_dim1]) / difr[i__ + (difr_dim1 << 1)];
394                     }
395 /* L60: */
396                 }
397                 i__2 = *k;
398                 for (i__ = j + 1; i__ <= i__2; ++i__) {
399                     if (z__[j] == 0.f) {
400                         work[i__] = 0.f;
401                     } else {
402                         r__1 = -poles[i__ + (poles_dim1 << 1)];
403                         work[i__] = z__[j] / (slamc3_(&dsigj, &r__1) - difl[
404                                 i__]) / (dsigj + poles[i__ + poles_dim1]) / 
405                                 difr[i__ + (difr_dim1 << 1)];
406                     }
407 /* L70: */
408                 }
409                 sgemv_("T", k, nrhs, &c_b11, &b[b_offset], ldb, &work[1], &
410                         c__1, &c_b13, &bx[j + bx_dim1], ldbx);
411 /* L80: */
412             }
413         }
414
415 /*        Step (2R): if SQRE = 1, apply back the rotation that is */
416 /*        related to the right null space of the subproblem. */
417
418         if (*sqre == 1) {
419             scopy_(nrhs, &b[m + b_dim1], ldb, &bx[m + bx_dim1], ldbx);
420             srot_(nrhs, &bx[bx_dim1 + 1], ldbx, &bx[m + bx_dim1], ldbx, c__, 
421                     s);
422         }
423         if (*k < max(m,n)) {
424             i__1 = n - *k;
425             slacpy_("A", &i__1, nrhs, &b[*k + 1 + b_dim1], ldb, &bx[*k + 1 + 
426                     bx_dim1], ldbx);
427         }
428
429 /*        Step (3R): permute rows of B. */
430
431         scopy_(nrhs, &bx[bx_dim1 + 1], ldbx, &b[nlp1 + b_dim1], ldb);
432         if (*sqre == 1) {
433             scopy_(nrhs, &bx[m + bx_dim1], ldbx, &b[m + b_dim1], ldb);
434         }
435         i__1 = n;
436         for (i__ = 2; i__ <= i__1; ++i__) {
437             scopy_(nrhs, &bx[i__ + bx_dim1], ldbx, &b[perm[i__] + b_dim1], 
438                     ldb);
439 /* L90: */
440         }
441
442 /*        Step (4R): apply back the Givens rotations performed. */
443
444         for (i__ = *givptr; i__ >= 1; --i__) {
445             r__1 = -givnum[i__ + givnum_dim1];
446             srot_(nrhs, &b[givcol[i__ + (givcol_dim1 << 1)] + b_dim1], ldb, &
447                     b[givcol[i__ + givcol_dim1] + b_dim1], ldb, &givnum[i__ + 
448                     (givnum_dim1 << 1)], &r__1);
449 /* L100: */
450         }
451     }
452
453     return 0;
454
455 /*     End of SLALS0 */
456
457 } /* slals0_ */