Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / sgelsd.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static integer c__9 = 9;
6 static integer c__0 = 0;
7 static integer c__6 = 6;
8 static integer c_n1 = -1;
9 static integer c__1 = 1;
10 static real c_b81 = 0.f;
11
12 /* Subroutine */ int sgelsd_(integer *m, integer *n, integer *nrhs, real *a, 
13         integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
14         rank, real *work, integer *lwork, integer *iwork, integer *info)
15 {
16     /* System generated locals */
17     integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4;
18
19     /* Builtin functions */
20     double log(doublereal);
21
22     /* Local variables */
23     integer ie, il, mm;
24     real eps, anrm, bnrm;
25     integer itau, nlvl, iascl, ibscl;
26     real sfmin;
27     integer minmn, maxmn, itaup, itauq, mnthr, nwork;
28     extern /* Subroutine */ int slabad_(real *, real *), sgebrd_(integer *, 
29             integer *, real *, integer *, real *, real *, real *, real *, 
30             real *, integer *, integer *);
31     extern doublereal slamch_(char *), slange_(char *, integer *, 
32             integer *, real *, integer *, real *);
33     extern /* Subroutine */ int xerbla_(char *, integer *);
34     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
35             integer *, integer *);
36     real bignum;
37     extern /* Subroutine */ int sgelqf_(integer *, integer *, real *, integer 
38             *, real *, real *, integer *, integer *), slalsd_(char *, integer 
39             *, integer *, integer *, real *, real *, real *, integer *, real *
40 , integer *, real *, integer *, integer *), slascl_(char *
41 , integer *, integer *, real *, real *, integer *, integer *, 
42             real *, integer *, integer *);
43     integer wlalsd;
44     extern /* Subroutine */ int sgeqrf_(integer *, integer *, real *, integer 
45             *, real *, real *, integer *, integer *), slacpy_(char *, integer 
46             *, integer *, real *, integer *, real *, integer *), 
47             slaset_(char *, integer *, integer *, real *, real *, real *, 
48             integer *);
49     integer ldwork;
50     extern /* Subroutine */ int sormbr_(char *, char *, char *, integer *, 
51             integer *, integer *, real *, integer *, real *, real *, integer *
52 , real *, integer *, integer *);
53     integer liwork, minwrk, maxwrk;
54     real smlnum;
55     extern /* Subroutine */ int sormlq_(char *, char *, integer *, integer *, 
56             integer *, real *, integer *, real *, real *, integer *, real *, 
57             integer *, integer *);
58     logical lquery;
59     integer smlsiz;
60     extern /* Subroutine */ int sormqr_(char *, char *, integer *, integer *, 
61             integer *, real *, integer *, real *, real *, integer *, real *, 
62             integer *, integer *);
63
64
65 /*  -- LAPACK driver routine (version 3.1) -- */
66 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
67 /*     November 2006 */
68
69 /*     .. Scalar Arguments .. */
70 /*     .. */
71 /*     .. Array Arguments .. */
72 /*     .. */
73
74 /*  Purpose */
75 /*  ======= */
76
77 /*  SGELSD computes the minimum-norm solution to a real linear least */
78 /*  squares problem: */
79 /*      minimize 2-norm(| b - A*x |) */
80 /*  using the singular value decomposition (SVD) of A. A is an M-by-N */
81 /*  matrix which may be rank-deficient. */
82
83 /*  Several right hand side vectors b and solution vectors x can be */
84 /*  handled in a single call; they are stored as the columns of the */
85 /*  M-by-NRHS right hand side matrix B and the N-by-NRHS solution */
86 /*  matrix X. */
87
88 /*  The problem is solved in three steps: */
89 /*  (1) Reduce the coefficient matrix A to bidiagonal form with */
90 /*      Householder transformations, reducing the original problem */
91 /*      into a "bidiagonal least squares problem" (BLS) */
92 /*  (2) Solve the BLS using a divide and conquer approach. */
93 /*  (3) Apply back all the Householder tranformations to solve */
94 /*      the original least squares problem. */
95
96 /*  The effective rank of A is determined by treating as zero those */
97 /*  singular values which are less than RCOND times the largest singular */
98 /*  value. */
99
100 /*  The divide and conquer algorithm makes very mild assumptions about */
101 /*  floating point arithmetic. It will work on machines with a guard */
102 /*  digit in add/subtract, or on those binary machines without guard */
103 /*  digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or */
104 /*  Cray-2. It could conceivably fail on hexadecimal or decimal machines */
105 /*  without guard digits, but we know of none. */
106
107 /*  Arguments */
108 /*  ========= */
109
110 /*  M       (input) INTEGER */
111 /*          The number of rows of A. M >= 0. */
112
113 /*  N       (input) INTEGER */
114 /*          The number of columns of A. N >= 0. */
115
116 /*  NRHS    (input) INTEGER */
117 /*          The number of right hand sides, i.e., the number of columns */
118 /*          of the matrices B and X. NRHS >= 0. */
119
120 /*  A       (input) REAL array, dimension (LDA,N) */
121 /*          On entry, the M-by-N matrix A. */
122 /*          On exit, A has been destroyed. */
123
124 /*  LDA     (input) INTEGER */
125 /*          The leading dimension of the array A.  LDA >= max(1,M). */
126
127 /*  B       (input/output) REAL array, dimension (LDB,NRHS) */
128 /*          On entry, the M-by-NRHS right hand side matrix B. */
129 /*          On exit, B is overwritten by the N-by-NRHS solution */
130 /*          matrix X.  If m >= n and RANK = n, the residual */
131 /*          sum-of-squares for the solution in the i-th column is given */
132 /*          by the sum of squares of elements n+1:m in that column. */
133
134 /*  LDB     (input) INTEGER */
135 /*          The leading dimension of the array B. LDB >= max(1,max(M,N)). */
136
137 /*  S       (output) REAL array, dimension (min(M,N)) */
138 /*          The singular values of A in decreasing order. */
139 /*          The condition number of A in the 2-norm = S(1)/S(min(m,n)). */
140
141 /*  RCOND   (input) REAL */
142 /*          RCOND is used to determine the effective rank of A. */
143 /*          Singular values S(i) <= RCOND*S(1) are treated as zero. */
144 /*          If RCOND < 0, machine precision is used instead. */
145
146 /*  RANK    (output) INTEGER */
147 /*          The effective rank of A, i.e., the number of singular values */
148 /*          which are greater than RCOND*S(1). */
149
150 /*  WORK    (workspace/output) REAL array, dimension (MAX(1,LWORK)) */
151 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
152
153 /*  LWORK   (input) INTEGER */
154 /*          The dimension of the array WORK. LWORK must be at least 1. */
155 /*          The exact minimum amount of workspace needed depends on M, */
156 /*          N and NRHS. As long as LWORK is at least */
157 /*              12*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2, */
158 /*          if M is greater than or equal to N or */
159 /*              12*M + 2*M*SMLSIZ + 8*M*NLVL + M*NRHS + (SMLSIZ+1)**2, */
160 /*          if M is less than N, the code will execute correctly. */
161 /*          SMLSIZ is returned by ILAENV and is equal to the maximum */
162 /*          size of the subproblems at the bottom of the computation */
163 /*          tree (usually about 25), and */
164 /*             NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 ) */
165 /*          For good performance, LWORK should generally be larger. */
166
167 /*          If LWORK = -1, then a workspace query is assumed; the routine */
168 /*          only calculates the optimal size of the array WORK and the */
169 /*          minimum size of the array IWORK, and returns these values as */
170 /*          the first entries of the WORK and IWORK arrays, and no error */
171 /*          message related to LWORK is issued by XERBLA. */
172
173 /*  IWORK   (workspace) INTEGER array, dimension (MAX(1,LIWORK)) */
174 /*          LIWORK >= max(1, 3*MINMN*NLVL + 11*MINMN), */
175 /*          where MINMN = MIN( M,N ). */
176 /*          On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK. */
177
178 /*  INFO    (output) INTEGER */
179 /*          = 0:  successful exit */
180 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
181 /*          > 0:  the algorithm for computing the SVD failed to converge; */
182 /*                if INFO = i, i off-diagonal elements of an intermediate */
183 /*                bidiagonal form did not converge to zero. */
184
185 /*  Further Details */
186 /*  =============== */
187
188 /*  Based on contributions by */
189 /*     Ming Gu and Ren-Cang Li, Computer Science Division, University of */
190 /*       California at Berkeley, USA */
191 /*     Osni Marques, LBNL/NERSC, USA */
192
193 /*  ===================================================================== */
194
195 /*     .. Parameters .. */
196 /*     .. */
197 /*     .. Local Scalars .. */
198 /*     .. */
199 /*     .. External Subroutines .. */
200 /*     .. */
201 /*     .. External Functions .. */
202 /*     .. */
203 /*     .. Intrinsic Functions .. */
204 /*     .. */
205 /*     .. Executable Statements .. */
206
207 /*     Test the input arguments. */
208
209     /* Parameter adjustments */
210     a_dim1 = *lda;
211     a_offset = 1 + a_dim1;
212     a -= a_offset;
213     b_dim1 = *ldb;
214     b_offset = 1 + b_dim1;
215     b -= b_offset;
216     --s;
217     --work;
218     --iwork;
219
220     /* Function Body */
221     *info = 0;
222     minmn = min(*m,*n);
223     maxmn = max(*m,*n);
224     lquery = *lwork == -1;
225     if (*m < 0) {
226         *info = -1;
227     } else if (*n < 0) {
228         *info = -2;
229     } else if (*nrhs < 0) {
230         *info = -3;
231     } else if (*lda < max(1,*m)) {
232         *info = -5;
233     } else if (*ldb < max(1,maxmn)) {
234         *info = -7;
235     }
236
237 /*     Compute workspace. */
238 /*     (Note: Comments in the code beginning "Workspace:" describe the */
239 /*     minimal amount of workspace needed at that point in the code, */
240 /*     as well as the preferred amount for good performance. */
241 /*     NB refers to the optimal block size for the immediately */
242 /*     following subroutine, as returned by ILAENV.) */
243
244     if (*info == 0) {
245         minwrk = 1;
246         maxwrk = 1;
247         liwork = 1;
248         if (minmn > 0) {
249             smlsiz = ilaenv_(&c__9, "SGELSD", " ", &c__0, &c__0, &c__0, &c__0);
250             mnthr = ilaenv_(&c__6, "SGELSD", " ", m, n, nrhs, &c_n1);
251 /* Computing MAX */
252             i__1 = (integer) (log((real) minmn / (real) (smlsiz + 1)) / log(
253                     2.f)) + 1;
254             nlvl = max(i__1,0);
255             liwork = minmn * 3 * nlvl + minmn * 11;
256             mm = *m;
257             if (*m >= *n && *m >= mnthr) {
258
259 /*              Path 1a - overdetermined, with many more rows than */
260 /*                        columns. */
261
262                 mm = *n;
263 /* Computing MAX */
264                 i__1 = maxwrk, i__2 = *n + *n * ilaenv_(&c__1, "SGEQRF", 
265                         " ", m, n, &c_n1, &c_n1);
266                 maxwrk = max(i__1,i__2);
267 /* Computing MAX */
268                 i__1 = maxwrk, i__2 = *n + *nrhs * ilaenv_(&c__1, "SORMQR", 
269                         "LT", m, nrhs, n, &c_n1);
270                 maxwrk = max(i__1,i__2);
271             }
272             if (*m >= *n) {
273
274 /*              Path 1 - overdetermined or exactly determined. */
275
276 /* Computing MAX */
277                 i__1 = maxwrk, i__2 = *n * 3 + (mm + *n) * ilaenv_(&c__1, 
278                         "SGEBRD", " ", &mm, n, &c_n1, &c_n1);
279                 maxwrk = max(i__1,i__2);
280 /* Computing MAX */
281                 i__1 = maxwrk, i__2 = *n * 3 + *nrhs * ilaenv_(&c__1, "SORMBR"
282 , "QLT", &mm, nrhs, n, &c_n1);
283                 maxwrk = max(i__1,i__2);
284 /* Computing MAX */
285                 i__1 = maxwrk, i__2 = *n * 3 + (*n - 1) * ilaenv_(&c__1, 
286                         "SORMBR", "PLN", n, nrhs, n, &c_n1);
287                 maxwrk = max(i__1,i__2);
288 /* Computing 2nd power */
289                 i__1 = smlsiz + 1;
290                 wlalsd = *n * 9 + (*n << 1) * smlsiz + (*n << 3) * nlvl + *n *
291                          *nrhs + i__1 * i__1;
292 /* Computing MAX */
293                 i__1 = maxwrk, i__2 = *n * 3 + wlalsd;
294                 maxwrk = max(i__1,i__2);
295 /* Computing MAX */
296                 i__1 = *n * 3 + mm, i__2 = *n * 3 + *nrhs, i__1 = max(i__1,
297                         i__2), i__2 = *n * 3 + wlalsd;
298                 minwrk = max(i__1,i__2);
299             }
300             if (*n > *m) {
301 /* Computing 2nd power */
302                 i__1 = smlsiz + 1;
303                 wlalsd = *m * 9 + (*m << 1) * smlsiz + (*m << 3) * nlvl + *m *
304                          *nrhs + i__1 * i__1;
305                 if (*n >= mnthr) {
306
307 /*                 Path 2a - underdetermined, with many more columns */
308 /*                           than rows. */
309
310                     maxwrk = *m + *m * ilaenv_(&c__1, "SGELQF", " ", m, n, &
311                             c_n1, &c_n1);
312 /* Computing MAX */
313                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m << 1) * 
314                             ilaenv_(&c__1, "SGEBRD", " ", m, m, &c_n1, &c_n1);
315                     maxwrk = max(i__1,i__2);
316 /* Computing MAX */
317                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *nrhs * 
318                             ilaenv_(&c__1, "SORMBR", "QLT", m, nrhs, m, &c_n1);
319                     maxwrk = max(i__1,i__2);
320 /* Computing MAX */
321                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m - 1) * 
322                             ilaenv_(&c__1, "SORMBR", "PLN", m, nrhs, m, &c_n1);
323                     maxwrk = max(i__1,i__2);
324                     if (*nrhs > 1) {
325 /* Computing MAX */
326                         i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs;
327                         maxwrk = max(i__1,i__2);
328                     } else {
329 /* Computing MAX */
330                         i__1 = maxwrk, i__2 = *m * *m + (*m << 1);
331                         maxwrk = max(i__1,i__2);
332                     }
333 /* Computing MAX */
334                     i__1 = maxwrk, i__2 = *m + *nrhs * ilaenv_(&c__1, "SORMLQ"
335 , "LT", n, nrhs, m, &c_n1);
336                     maxwrk = max(i__1,i__2);
337 /* Computing MAX */
338                     i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + wlalsd;
339                     maxwrk = max(i__1,i__2);
340                 } else {
341
342 /*                 Path 2 - remaining underdetermined cases. */
343
344                     maxwrk = *m * 3 + (*n + *m) * ilaenv_(&c__1, "SGEBRD", 
345                             " ", m, n, &c_n1, &c_n1);
346 /* Computing MAX */
347                     i__1 = maxwrk, i__2 = *m * 3 + *nrhs * ilaenv_(&c__1, 
348                             "SORMBR", "QLT", m, nrhs, n, &c_n1);
349                     maxwrk = max(i__1,i__2);
350 /* Computing MAX */
351                     i__1 = maxwrk, i__2 = *m * 3 + *m * ilaenv_(&c__1, "SORM"
352                             "BR", "PLN", n, nrhs, m, &c_n1);
353                     maxwrk = max(i__1,i__2);
354 /* Computing MAX */
355                     i__1 = maxwrk, i__2 = *m * 3 + wlalsd;
356                     maxwrk = max(i__1,i__2);
357                 }
358 /* Computing MAX */
359                 i__1 = *m * 3 + *nrhs, i__2 = *m * 3 + *m, i__1 = max(i__1,
360                         i__2), i__2 = *m * 3 + wlalsd;
361                 minwrk = max(i__1,i__2);
362             }
363         }
364         minwrk = min(minwrk,maxwrk);
365         work[1] = (real) maxwrk;
366         iwork[1] = liwork;
367
368         if (*lwork < minwrk && ! lquery) {
369             *info = -12;
370         }
371     }
372
373     if (*info != 0) {
374         i__1 = -(*info);
375         xerbla_("SGELSD", &i__1);
376         return 0;
377     } else if (lquery) {
378         return 0;
379     }
380
381 /*     Quick return if possible. */
382
383     if (*m == 0 || *n == 0) {
384         *rank = 0;
385         return 0;
386     }
387
388 /*     Get machine parameters. */
389
390     eps = slamch_("P");
391     sfmin = slamch_("S");
392     smlnum = sfmin / eps;
393     bignum = 1.f / smlnum;
394     slabad_(&smlnum, &bignum);
395
396 /*     Scale A if max entry outside range [SMLNUM,BIGNUM]. */
397
398     anrm = slange_("M", m, n, &a[a_offset], lda, &work[1]);
399     iascl = 0;
400     if (anrm > 0.f && anrm < smlnum) {
401
402 /*        Scale matrix norm up to SMLNUM. */
403
404         slascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda, 
405                 info);
406         iascl = 1;
407     } else if (anrm > bignum) {
408
409 /*        Scale matrix norm down to BIGNUM. */
410
411         slascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda, 
412                 info);
413         iascl = 2;
414     } else if (anrm == 0.f) {
415
416 /*        Matrix all zero. Return zero solution. */
417
418         i__1 = max(*m,*n);
419         slaset_("F", &i__1, nrhs, &c_b81, &c_b81, &b[b_offset], ldb);
420         slaset_("F", &minmn, &c__1, &c_b81, &c_b81, &s[1], &c__1);
421         *rank = 0;
422         goto L10;
423     }
424
425 /*     Scale B if max entry outside range [SMLNUM,BIGNUM]. */
426
427     bnrm = slange_("M", m, nrhs, &b[b_offset], ldb, &work[1]);
428     ibscl = 0;
429     if (bnrm > 0.f && bnrm < smlnum) {
430
431 /*        Scale matrix norm up to SMLNUM. */
432
433         slascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb, 
434                  info);
435         ibscl = 1;
436     } else if (bnrm > bignum) {
437
438 /*        Scale matrix norm down to BIGNUM. */
439
440         slascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb, 
441                  info);
442         ibscl = 2;
443     }
444
445 /*     If M < N make sure certain entries of B are zero. */
446
447     if (*m < *n) {
448         i__1 = *n - *m;
449         slaset_("F", &i__1, nrhs, &c_b81, &c_b81, &b[*m + 1 + b_dim1], ldb);
450     }
451
452 /*     Overdetermined case. */
453
454     if (*m >= *n) {
455
456 /*        Path 1 - overdetermined or exactly determined. */
457
458         mm = *m;
459         if (*m >= mnthr) {
460
461 /*           Path 1a - overdetermined, with many more rows than columns. */
462
463             mm = *n;
464             itau = 1;
465             nwork = itau + *n;
466
467 /*           Compute A=Q*R. */
468 /*           (Workspace: need 2*N, prefer N+N*NB) */
469
470             i__1 = *lwork - nwork + 1;
471             sgeqrf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, 
472                      info);
473
474 /*           Multiply B by transpose(Q). */
475 /*           (Workspace: need N+NRHS, prefer N+NRHS*NB) */
476
477             i__1 = *lwork - nwork + 1;
478             sormqr_("L", "T", m, nrhs, n, &a[a_offset], lda, &work[itau], &b[
479                     b_offset], ldb, &work[nwork], &i__1, info);
480
481 /*           Zero out below R. */
482
483             if (*n > 1) {
484                 i__1 = *n - 1;
485                 i__2 = *n - 1;
486                 slaset_("L", &i__1, &i__2, &c_b81, &c_b81, &a[a_dim1 + 2], 
487                         lda);
488             }
489         }
490
491         ie = 1;
492         itauq = ie + *n;
493         itaup = itauq + *n;
494         nwork = itaup + *n;
495
496 /*        Bidiagonalize R in A. */
497 /*        (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB) */
498
499         i__1 = *lwork - nwork + 1;
500         sgebrd_(&mm, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
501                 work[itaup], &work[nwork], &i__1, info);
502
503 /*        Multiply B by transpose of left bidiagonalizing vectors of R. */
504 /*        (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB) */
505
506         i__1 = *lwork - nwork + 1;
507         sormbr_("Q", "L", "T", &mm, nrhs, n, &a[a_offset], lda, &work[itauq], 
508                 &b[b_offset], ldb, &work[nwork], &i__1, info);
509
510 /*        Solve the bidiagonal least squares problem. */
511
512         slalsd_("U", &smlsiz, n, nrhs, &s[1], &work[ie], &b[b_offset], ldb, 
513                 rcond, rank, &work[nwork], &iwork[1], info);
514         if (*info != 0) {
515             goto L10;
516         }
517
518 /*        Multiply B by right bidiagonalizing vectors of R. */
519
520         i__1 = *lwork - nwork + 1;
521         sormbr_("P", "L", "N", n, nrhs, n, &a[a_offset], lda, &work[itaup], &
522                 b[b_offset], ldb, &work[nwork], &i__1, info);
523
524     } else /* if(complicated condition) */ {
525 /* Computing MAX */
526         i__1 = *m, i__2 = (*m << 1) - 4, i__1 = max(i__1,i__2), i__1 = max(
527                 i__1,*nrhs), i__2 = *n - *m * 3, i__1 = max(i__1,i__2);
528         if (*n >= mnthr && *lwork >= (*m << 2) + *m * *m + max(i__1,wlalsd)) {
529
530 /*        Path 2a - underdetermined, with many more columns than rows */
531 /*        and sufficient workspace for an efficient algorithm. */
532
533             ldwork = *m;
534 /* Computing MAX */
535 /* Computing MAX */
536             i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), i__3 = 
537                     max(i__3,*nrhs), i__4 = *n - *m * 3;
538             i__1 = (*m << 2) + *m * *lda + max(i__3,i__4), i__2 = *m * *lda + 
539                     *m + *m * *nrhs, i__1 = max(i__1,i__2), i__2 = (*m << 2) 
540                     + *m * *lda + wlalsd;
541             if (*lwork >= max(i__1,i__2)) {
542                 ldwork = *lda;
543             }
544             itau = 1;
545             nwork = *m + 1;
546
547 /*        Compute A=L*Q. */
548 /*        (Workspace: need 2*M, prefer M+M*NB) */
549
550             i__1 = *lwork - nwork + 1;
551             sgelqf_(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &i__1, 
552                      info);
553             il = nwork;
554
555 /*        Copy L to WORK(IL), zeroing out above its diagonal. */
556
557             slacpy_("L", m, m, &a[a_offset], lda, &work[il], &ldwork);
558             i__1 = *m - 1;
559             i__2 = *m - 1;
560             slaset_("U", &i__1, &i__2, &c_b81, &c_b81, &work[il + ldwork], &
561                     ldwork);
562             ie = il + ldwork * *m;
563             itauq = ie + *m;
564             itaup = itauq + *m;
565             nwork = itaup + *m;
566
567 /*        Bidiagonalize L in WORK(IL). */
568 /*        (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB) */
569
570             i__1 = *lwork - nwork + 1;
571             sgebrd_(m, m, &work[il], &ldwork, &s[1], &work[ie], &work[itauq], 
572                     &work[itaup], &work[nwork], &i__1, info);
573
574 /*        Multiply B by transpose of left bidiagonalizing vectors of L. */
575 /*        (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) */
576
577             i__1 = *lwork - nwork + 1;
578             sormbr_("Q", "L", "T", m, nrhs, m, &work[il], &ldwork, &work[
579                     itauq], &b[b_offset], ldb, &work[nwork], &i__1, info);
580
581 /*        Solve the bidiagonal least squares problem. */
582
583             slalsd_("U", &smlsiz, m, nrhs, &s[1], &work[ie], &b[b_offset], 
584                     ldb, rcond, rank, &work[nwork], &iwork[1], info);
585             if (*info != 0) {
586                 goto L10;
587             }
588
589 /*        Multiply B by right bidiagonalizing vectors of L. */
590
591             i__1 = *lwork - nwork + 1;
592             sormbr_("P", "L", "N", m, nrhs, m, &work[il], &ldwork, &work[
593                     itaup], &b[b_offset], ldb, &work[nwork], &i__1, info);
594
595 /*        Zero out below first M rows of B. */
596
597             i__1 = *n - *m;
598             slaset_("F", &i__1, nrhs, &c_b81, &c_b81, &b[*m + 1 + b_dim1], 
599                     ldb);
600             nwork = itau + *m;
601
602 /*        Multiply transpose(Q) by B. */
603 /*        (Workspace: need M+NRHS, prefer M+NRHS*NB) */
604
605             i__1 = *lwork - nwork + 1;
606             sormlq_("L", "T", n, nrhs, m, &a[a_offset], lda, &work[itau], &b[
607                     b_offset], ldb, &work[nwork], &i__1, info);
608
609         } else {
610
611 /*        Path 2 - remaining underdetermined cases. */
612
613             ie = 1;
614             itauq = ie + *m;
615             itaup = itauq + *m;
616             nwork = itaup + *m;
617
618 /*        Bidiagonalize A. */
619 /*        (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) */
620
621             i__1 = *lwork - nwork + 1;
622             sgebrd_(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
623                     work[itaup], &work[nwork], &i__1, info);
624
625 /*        Multiply B by transpose of left bidiagonalizing vectors. */
626 /*        (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB) */
627
628             i__1 = *lwork - nwork + 1;
629             sormbr_("Q", "L", "T", m, nrhs, n, &a[a_offset], lda, &work[itauq]
630 , &b[b_offset], ldb, &work[nwork], &i__1, info);
631
632 /*        Solve the bidiagonal least squares problem. */
633
634             slalsd_("L", &smlsiz, m, nrhs, &s[1], &work[ie], &b[b_offset], 
635                     ldb, rcond, rank, &work[nwork], &iwork[1], info);
636             if (*info != 0) {
637                 goto L10;
638             }
639
640 /*        Multiply B by right bidiagonalizing vectors of A. */
641
642             i__1 = *lwork - nwork + 1;
643             sormbr_("P", "L", "N", n, nrhs, m, &a[a_offset], lda, &work[itaup]
644 , &b[b_offset], ldb, &work[nwork], &i__1, info);
645
646         }
647     }
648
649 /*     Undo scaling. */
650
651     if (iascl == 1) {
652         slascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb, 
653                  info);
654         slascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
655                 minmn, info);
656     } else if (iascl == 2) {
657         slascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb, 
658                  info);
659         slascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
660                 minmn, info);
661     }
662     if (ibscl == 1) {
663         slascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb, 
664                  info);
665     } else if (ibscl == 2) {
666         slascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb, 
667                  info);
668     }
669
670 L10:
671     work[1] = (real) maxwrk;
672     iwork[1] = liwork;
673     return 0;
674
675 /*     End of SGELSD */
676
677 } /* sgelsd_ */