00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015
00016
00017
00018 static integer c__1 = 1;
00019 static integer c_n1 = -1;
00020 static integer c__0 = 0;
00021 static doublereal c_b31 = 0.;
00022 static integer c__2 = 2;
00023 static doublereal c_b54 = 1.;
00024
00025 int dgelsy_(integer *m, integer *n, integer *nrhs,
00026 doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
00027 jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
00028 lwork, integer *info)
00029 {
00030
00031 integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2;
00032 doublereal d__1, d__2;
00033
00034
00035 integer i__, j;
00036 doublereal c1, c2, s1, s2;
00037 integer nb, mn, nb1, nb2, nb3, nb4;
00038 doublereal anrm, bnrm, smin, smax;
00039 integer iascl, ibscl;
00040 extern int dcopy_(integer *, doublereal *, integer *,
00041 doublereal *, integer *);
00042 integer ismin, ismax;
00043 extern int dtrsm_(char *, char *, char *, char *,
00044 integer *, integer *, doublereal *, doublereal *, integer *,
00045 doublereal *, integer *), dlaic1_(
00046 integer *, integer *, doublereal *, doublereal *, doublereal *,
00047 doublereal *, doublereal *, doublereal *, doublereal *);
00048 doublereal wsize;
00049 extern int dgeqp3_(integer *, integer *, doublereal *,
00050 integer *, integer *, doublereal *, doublereal *, integer *,
00051 integer *), dlabad_(doublereal *, doublereal *);
00052 extern doublereal dlamch_(char *), dlange_(char *, integer *,
00053 integer *, doublereal *, integer *, doublereal *);
00054 extern int dlascl_(char *, integer *, integer *,
00055 doublereal *, doublereal *, integer *, integer *, doublereal *,
00056 integer *, integer *), dlaset_(char *, integer *, integer
00057 *, doublereal *, doublereal *, doublereal *, integer *),
00058 xerbla_(char *, integer *);
00059 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
00060 integer *, integer *);
00061 doublereal bignum;
00062 integer lwkmin;
00063 extern int dormqr_(char *, char *, integer *, integer *,
00064 integer *, doublereal *, integer *, doublereal *, doublereal *,
00065 integer *, doublereal *, integer *, integer *);
00066 doublereal sminpr, smaxpr, smlnum;
00067 extern int dormrz_(char *, char *, integer *, integer *,
00068 integer *, integer *, doublereal *, integer *, doublereal *,
00069 doublereal *, integer *, doublereal *, integer *, integer *);
00070 integer lwkopt;
00071 logical lquery;
00072 extern int dtzrzf_(integer *, integer *, doublereal *,
00073 integer *, doublereal *, doublereal *, integer *, integer *);
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 a_dim1 = *lda;
00217 a_offset = 1 + a_dim1;
00218 a -= a_offset;
00219 b_dim1 = *ldb;
00220 b_offset = 1 + b_dim1;
00221 b -= b_offset;
00222 --jpvt;
00223 --work;
00224
00225
00226 mn = min(*m,*n);
00227 ismin = mn + 1;
00228 ismax = (mn << 1) + 1;
00229
00230
00231
00232 *info = 0;
00233 lquery = *lwork == -1;
00234 if (*m < 0) {
00235 *info = -1;
00236 } else if (*n < 0) {
00237 *info = -2;
00238 } else if (*nrhs < 0) {
00239 *info = -3;
00240 } else if (*lda < max(1,*m)) {
00241 *info = -5;
00242 } else {
00243
00244 i__1 = max(1,*m);
00245 if (*ldb < max(i__1,*n)) {
00246 *info = -7;
00247 }
00248 }
00249
00250
00251
00252 if (*info == 0) {
00253 if (mn == 0 || *nrhs == 0) {
00254 lwkmin = 1;
00255 lwkopt = 1;
00256 } else {
00257 nb1 = ilaenv_(&c__1, "DGEQRF", " ", m, n, &c_n1, &c_n1);
00258 nb2 = ilaenv_(&c__1, "DGERQF", " ", m, n, &c_n1, &c_n1);
00259 nb3 = ilaenv_(&c__1, "DORMQR", " ", m, n, nrhs, &c_n1);
00260 nb4 = ilaenv_(&c__1, "DORMRQ", " ", m, n, nrhs, &c_n1);
00261
00262 i__1 = max(nb1,nb2), i__1 = max(i__1,nb3);
00263 nb = max(i__1,nb4);
00264
00265 i__1 = mn << 1, i__2 = *n + 1, i__1 = max(i__1,i__2), i__2 = mn +
00266 *nrhs;
00267 lwkmin = mn + max(i__1,i__2);
00268
00269 i__1 = lwkmin, i__2 = mn + (*n << 1) + nb * (*n + 1), i__1 = max(
00270 i__1,i__2), i__2 = (mn << 1) + nb * *nrhs;
00271 lwkopt = max(i__1,i__2);
00272 }
00273 work[1] = (doublereal) lwkopt;
00274
00275 if (*lwork < lwkmin && ! lquery) {
00276 *info = -12;
00277 }
00278 }
00279
00280 if (*info != 0) {
00281 i__1 = -(*info);
00282 xerbla_("DGELSY", &i__1);
00283 return 0;
00284 } else if (lquery) {
00285 return 0;
00286 }
00287
00288
00289
00290 if (mn == 0 || *nrhs == 0) {
00291 *rank = 0;
00292 return 0;
00293 }
00294
00295
00296
00297 smlnum = dlamch_("S") / dlamch_("P");
00298 bignum = 1. / smlnum;
00299 dlabad_(&smlnum, &bignum);
00300
00301
00302
00303 anrm = dlange_("M", m, n, &a[a_offset], lda, &work[1]);
00304 iascl = 0;
00305 if (anrm > 0. && anrm < smlnum) {
00306
00307
00308
00309 dlascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda,
00310 info);
00311 iascl = 1;
00312 } else if (anrm > bignum) {
00313
00314
00315
00316 dlascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda,
00317 info);
00318 iascl = 2;
00319 } else if (anrm == 0.) {
00320
00321
00322
00323 i__1 = max(*m,*n);
00324 dlaset_("F", &i__1, nrhs, &c_b31, &c_b31, &b[b_offset], ldb);
00325 *rank = 0;
00326 goto L70;
00327 }
00328
00329 bnrm = dlange_("M", m, nrhs, &b[b_offset], ldb, &work[1]);
00330 ibscl = 0;
00331 if (bnrm > 0. && bnrm < smlnum) {
00332
00333
00334
00335 dlascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb,
00336 info);
00337 ibscl = 1;
00338 } else if (bnrm > bignum) {
00339
00340
00341
00342 dlascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb,
00343 info);
00344 ibscl = 2;
00345 }
00346
00347
00348
00349
00350 i__1 = *lwork - mn;
00351 dgeqp3_(m, n, &a[a_offset], lda, &jpvt[1], &work[1], &work[mn + 1], &i__1,
00352 info);
00353 wsize = mn + work[mn + 1];
00354
00355
00356
00357
00358
00359
00360 work[ismin] = 1.;
00361 work[ismax] = 1.;
00362 smax = (d__1 = a[a_dim1 + 1], abs(d__1));
00363 smin = smax;
00364 if ((d__1 = a[a_dim1 + 1], abs(d__1)) == 0.) {
00365 *rank = 0;
00366 i__1 = max(*m,*n);
00367 dlaset_("F", &i__1, nrhs, &c_b31, &c_b31, &b[b_offset], ldb);
00368 goto L70;
00369 } else {
00370 *rank = 1;
00371 }
00372
00373 L10:
00374 if (*rank < mn) {
00375 i__ = *rank + 1;
00376 dlaic1_(&c__2, rank, &work[ismin], &smin, &a[i__ * a_dim1 + 1], &a[
00377 i__ + i__ * a_dim1], &sminpr, &s1, &c1);
00378 dlaic1_(&c__1, rank, &work[ismax], &smax, &a[i__ * a_dim1 + 1], &a[
00379 i__ + i__ * a_dim1], &smaxpr, &s2, &c2);
00380
00381 if (smaxpr * *rcond <= sminpr) {
00382 i__1 = *rank;
00383 for (i__ = 1; i__ <= i__1; ++i__) {
00384 work[ismin + i__ - 1] = s1 * work[ismin + i__ - 1];
00385 work[ismax + i__ - 1] = s2 * work[ismax + i__ - 1];
00386
00387 }
00388 work[ismin + *rank] = c1;
00389 work[ismax + *rank] = c2;
00390 smin = sminpr;
00391 smax = smaxpr;
00392 ++(*rank);
00393 goto L10;
00394 }
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 if (*rank < *n) {
00406 i__1 = *lwork - (mn << 1);
00407 dtzrzf_(rank, n, &a[a_offset], lda, &work[mn + 1], &work[(mn << 1) +
00408 1], &i__1, info);
00409 }
00410
00411
00412
00413
00414
00415
00416 i__1 = *lwork - (mn << 1);
00417 dormqr_("Left", "Transpose", m, nrhs, &mn, &a[a_offset], lda, &work[1], &
00418 b[b_offset], ldb, &work[(mn << 1) + 1], &i__1, info);
00419
00420 d__1 = wsize, d__2 = (mn << 1) + work[(mn << 1) + 1];
00421 wsize = max(d__1,d__2);
00422
00423
00424
00425
00426
00427 dtrsm_("Left", "Upper", "No transpose", "Non-unit", rank, nrhs, &c_b54, &
00428 a[a_offset], lda, &b[b_offset], ldb);
00429
00430 i__1 = *nrhs;
00431 for (j = 1; j <= i__1; ++j) {
00432 i__2 = *n;
00433 for (i__ = *rank + 1; i__ <= i__2; ++i__) {
00434 b[i__ + j * b_dim1] = 0.;
00435
00436 }
00437
00438 }
00439
00440
00441
00442 if (*rank < *n) {
00443 i__1 = *n - *rank;
00444 i__2 = *lwork - (mn << 1);
00445 dormrz_("Left", "Transpose", n, nrhs, rank, &i__1, &a[a_offset], lda,
00446 &work[mn + 1], &b[b_offset], ldb, &work[(mn << 1) + 1], &i__2,
00447 info);
00448 }
00449
00450
00451
00452
00453
00454 i__1 = *nrhs;
00455 for (j = 1; j <= i__1; ++j) {
00456 i__2 = *n;
00457 for (i__ = 1; i__ <= i__2; ++i__) {
00458 work[jpvt[i__]] = b[i__ + j * b_dim1];
00459
00460 }
00461 dcopy_(n, &work[1], &c__1, &b[j * b_dim1 + 1], &c__1);
00462
00463 }
00464
00465
00466
00467
00468
00469 if (iascl == 1) {
00470 dlascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb,
00471 info);
00472 dlascl_("U", &c__0, &c__0, &smlnum, &anrm, rank, rank, &a[a_offset],
00473 lda, info);
00474 } else if (iascl == 2) {
00475 dlascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb,
00476 info);
00477 dlascl_("U", &c__0, &c__0, &bignum, &anrm, rank, rank, &a[a_offset],
00478 lda, info);
00479 }
00480 if (ibscl == 1) {
00481 dlascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb,
00482 info);
00483 } else if (ibscl == 2) {
00484 dlascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb,
00485 info);
00486 }
00487
00488 L70:
00489 work[1] = (doublereal) lwkopt;
00490
00491 return 0;
00492
00493
00494
00495 }