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 doublereal c_b6 = 0.;
00020 static integer c__0 = 0;
00021 static doublereal c_b11 = 1.;
00022
00023 int dlalsd_(char *uplo, integer *smlsiz, integer *n, integer
00024 *nrhs, doublereal *d__, doublereal *e, doublereal *b, integer *ldb,
00025 doublereal *rcond, integer *rank, doublereal *work, integer *iwork,
00026 integer *info)
00027 {
00028
00029 integer b_dim1, b_offset, i__1, i__2;
00030 doublereal d__1;
00031
00032
00033 double log(doublereal), d_sign(doublereal *, doublereal *);
00034
00035
00036 integer c__, i__, j, k;
00037 doublereal r__;
00038 integer s, u, z__;
00039 doublereal cs;
00040 integer bx;
00041 doublereal sn;
00042 integer st, vt, nm1, st1;
00043 doublereal eps;
00044 integer iwk;
00045 doublereal tol;
00046 integer difl, difr;
00047 doublereal rcnd;
00048 integer perm, nsub;
00049 extern int drot_(integer *, doublereal *, integer *,
00050 doublereal *, integer *, doublereal *, doublereal *);
00051 integer nlvl, sqre, bxst;
00052 extern int dgemm_(char *, char *, integer *, integer *,
00053 integer *, doublereal *, doublereal *, integer *, doublereal *,
00054 integer *, doublereal *, doublereal *, integer *),
00055 dcopy_(integer *, doublereal *, integer *, doublereal *, integer
00056 *);
00057 integer poles, sizei, nsize, nwork, icmpq1, icmpq2;
00058 extern doublereal dlamch_(char *);
00059 extern int dlasda_(integer *, integer *, integer *,
00060 integer *, doublereal *, doublereal *, doublereal *, integer *,
00061 doublereal *, integer *, doublereal *, doublereal *, doublereal *,
00062 doublereal *, integer *, integer *, integer *, integer *,
00063 doublereal *, doublereal *, doublereal *, doublereal *, integer *,
00064 integer *), dlalsa_(integer *, integer *, integer *, integer *,
00065 doublereal *, integer *, doublereal *, integer *, doublereal *,
00066 integer *, doublereal *, integer *, doublereal *, doublereal *,
00067 doublereal *, doublereal *, integer *, integer *, integer *,
00068 integer *, doublereal *, doublereal *, doublereal *, doublereal *,
00069 integer *, integer *), dlascl_(char *, integer *, integer *,
00070 doublereal *, doublereal *, integer *, integer *, doublereal *,
00071 integer *, integer *);
00072 extern integer idamax_(integer *, doublereal *, integer *);
00073 extern int dlasdq_(char *, integer *, integer *, integer
00074 *, integer *, integer *, doublereal *, doublereal *, doublereal *,
00075 integer *, doublereal *, integer *, doublereal *, integer *,
00076 doublereal *, integer *), dlacpy_(char *, integer *,
00077 integer *, doublereal *, integer *, doublereal *, integer *), dlartg_(doublereal *, doublereal *, doublereal *,
00078 doublereal *, doublereal *), dlaset_(char *, integer *, integer *,
00079 doublereal *, doublereal *, doublereal *, integer *),
00080 xerbla_(char *, integer *);
00081 integer givcol;
00082 extern doublereal dlanst_(char *, integer *, doublereal *, doublereal *);
00083 extern int dlasrt_(char *, integer *, doublereal *,
00084 integer *);
00085 doublereal orgnrm;
00086 integer givnum, givptr, smlszp;
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 --d__;
00206 --e;
00207 b_dim1 = *ldb;
00208 b_offset = 1 + b_dim1;
00209 b -= b_offset;
00210 --work;
00211 --iwork;
00212
00213
00214 *info = 0;
00215
00216 if (*n < 0) {
00217 *info = -3;
00218 } else if (*nrhs < 1) {
00219 *info = -4;
00220 } else if (*ldb < 1 || *ldb < *n) {
00221 *info = -8;
00222 }
00223 if (*info != 0) {
00224 i__1 = -(*info);
00225 xerbla_("DLALSD", &i__1);
00226 return 0;
00227 }
00228
00229 eps = dlamch_("Epsilon");
00230
00231
00232
00233 if (*rcond <= 0. || *rcond >= 1.) {
00234 rcnd = eps;
00235 } else {
00236 rcnd = *rcond;
00237 }
00238
00239 *rank = 0;
00240
00241
00242
00243 if (*n == 0) {
00244 return 0;
00245 } else if (*n == 1) {
00246 if (d__[1] == 0.) {
00247 dlaset_("A", &c__1, nrhs, &c_b6, &c_b6, &b[b_offset], ldb);
00248 } else {
00249 *rank = 1;
00250 dlascl_("G", &c__0, &c__0, &d__[1], &c_b11, &c__1, nrhs, &b[
00251 b_offset], ldb, info);
00252 d__[1] = abs(d__[1]);
00253 }
00254 return 0;
00255 }
00256
00257
00258
00259 if (*(unsigned char *)uplo == 'L') {
00260 i__1 = *n - 1;
00261 for (i__ = 1; i__ <= i__1; ++i__) {
00262 dlartg_(&d__[i__], &e[i__], &cs, &sn, &r__);
00263 d__[i__] = r__;
00264 e[i__] = sn * d__[i__ + 1];
00265 d__[i__ + 1] = cs * d__[i__ + 1];
00266 if (*nrhs == 1) {
00267 drot_(&c__1, &b[i__ + b_dim1], &c__1, &b[i__ + 1 + b_dim1], &
00268 c__1, &cs, &sn);
00269 } else {
00270 work[(i__ << 1) - 1] = cs;
00271 work[i__ * 2] = sn;
00272 }
00273
00274 }
00275 if (*nrhs > 1) {
00276 i__1 = *nrhs;
00277 for (i__ = 1; i__ <= i__1; ++i__) {
00278 i__2 = *n - 1;
00279 for (j = 1; j <= i__2; ++j) {
00280 cs = work[(j << 1) - 1];
00281 sn = work[j * 2];
00282 drot_(&c__1, &b[j + i__ * b_dim1], &c__1, &b[j + 1 + i__ *
00283 b_dim1], &c__1, &cs, &sn);
00284
00285 }
00286
00287 }
00288 }
00289 }
00290
00291
00292
00293 nm1 = *n - 1;
00294 orgnrm = dlanst_("M", n, &d__[1], &e[1]);
00295 if (orgnrm == 0.) {
00296 dlaset_("A", n, nrhs, &c_b6, &c_b6, &b[b_offset], ldb);
00297 return 0;
00298 }
00299
00300 dlascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, &c__1, &d__[1], n, info);
00301 dlascl_("G", &c__0, &c__0, &orgnrm, &c_b11, &nm1, &c__1, &e[1], &nm1,
00302 info);
00303
00304
00305
00306
00307 if (*n <= *smlsiz) {
00308 nwork = *n * *n + 1;
00309 dlaset_("A", n, n, &c_b6, &c_b11, &work[1], n);
00310 dlasdq_("U", &c__0, n, n, &c__0, nrhs, &d__[1], &e[1], &work[1], n, &
00311 work[1], n, &b[b_offset], ldb, &work[nwork], info);
00312 if (*info != 0) {
00313 return 0;
00314 }
00315 tol = rcnd * (d__1 = d__[idamax_(n, &d__[1], &c__1)], abs(d__1));
00316 i__1 = *n;
00317 for (i__ = 1; i__ <= i__1; ++i__) {
00318 if (d__[i__] <= tol) {
00319 dlaset_("A", &c__1, nrhs, &c_b6, &c_b6, &b[i__ + b_dim1], ldb);
00320 } else {
00321 dlascl_("G", &c__0, &c__0, &d__[i__], &c_b11, &c__1, nrhs, &b[
00322 i__ + b_dim1], ldb, info);
00323 ++(*rank);
00324 }
00325
00326 }
00327 dgemm_("T", "N", n, nrhs, n, &c_b11, &work[1], n, &b[b_offset], ldb, &
00328 c_b6, &work[nwork], n);
00329 dlacpy_("A", n, nrhs, &work[nwork], n, &b[b_offset], ldb);
00330
00331
00332
00333 dlascl_("G", &c__0, &c__0, &c_b11, &orgnrm, n, &c__1, &d__[1], n,
00334 info);
00335 dlasrt_("D", n, &d__[1], info);
00336 dlascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, nrhs, &b[b_offset],
00337 ldb, info);
00338
00339 return 0;
00340 }
00341
00342
00343
00344 nlvl = (integer) (log((doublereal) (*n) / (doublereal) (*smlsiz + 1)) /
00345 log(2.)) + 1;
00346
00347 smlszp = *smlsiz + 1;
00348
00349 u = 1;
00350 vt = *smlsiz * *n + 1;
00351 difl = vt + smlszp * *n;
00352 difr = difl + nlvl * *n;
00353 z__ = difr + (nlvl * *n << 1);
00354 c__ = z__ + nlvl * *n;
00355 s = c__ + *n;
00356 poles = s + *n;
00357 givnum = poles + (nlvl << 1) * *n;
00358 bx = givnum + (nlvl << 1) * *n;
00359 nwork = bx + *n * *nrhs;
00360
00361 sizei = *n + 1;
00362 k = sizei + *n;
00363 givptr = k + *n;
00364 perm = givptr + *n;
00365 givcol = perm + nlvl * *n;
00366 iwk = givcol + (nlvl * *n << 1);
00367
00368 st = 1;
00369 sqre = 0;
00370 icmpq1 = 1;
00371 icmpq2 = 0;
00372 nsub = 0;
00373
00374 i__1 = *n;
00375 for (i__ = 1; i__ <= i__1; ++i__) {
00376 if ((d__1 = d__[i__], abs(d__1)) < eps) {
00377 d__[i__] = d_sign(&eps, &d__[i__]);
00378 }
00379
00380 }
00381
00382 i__1 = nm1;
00383 for (i__ = 1; i__ <= i__1; ++i__) {
00384 if ((d__1 = e[i__], abs(d__1)) < eps || i__ == nm1) {
00385 ++nsub;
00386 iwork[nsub] = st;
00387
00388
00389
00390
00391 if (i__ < nm1) {
00392
00393
00394
00395 nsize = i__ - st + 1;
00396 iwork[sizei + nsub - 1] = nsize;
00397 } else if ((d__1 = e[i__], abs(d__1)) >= eps) {
00398
00399
00400
00401 nsize = *n - st + 1;
00402 iwork[sizei + nsub - 1] = nsize;
00403 } else {
00404
00405
00406
00407
00408
00409 nsize = i__ - st + 1;
00410 iwork[sizei + nsub - 1] = nsize;
00411 ++nsub;
00412 iwork[nsub] = *n;
00413 iwork[sizei + nsub - 1] = 1;
00414 dcopy_(nrhs, &b[*n + b_dim1], ldb, &work[bx + nm1], n);
00415 }
00416 st1 = st - 1;
00417 if (nsize == 1) {
00418
00419
00420
00421
00422 dcopy_(nrhs, &b[st + b_dim1], ldb, &work[bx + st1], n);
00423 } else if (nsize <= *smlsiz) {
00424
00425
00426
00427 dlaset_("A", &nsize, &nsize, &c_b6, &c_b11, &work[vt + st1],
00428 n);
00429 dlasdq_("U", &c__0, &nsize, &nsize, &c__0, nrhs, &d__[st], &e[
00430 st], &work[vt + st1], n, &work[nwork], n, &b[st +
00431 b_dim1], ldb, &work[nwork], info);
00432 if (*info != 0) {
00433 return 0;
00434 }
00435 dlacpy_("A", &nsize, nrhs, &b[st + b_dim1], ldb, &work[bx +
00436 st1], n);
00437 } else {
00438
00439
00440
00441 dlasda_(&icmpq1, smlsiz, &nsize, &sqre, &d__[st], &e[st], &
00442 work[u + st1], n, &work[vt + st1], &iwork[k + st1], &
00443 work[difl + st1], &work[difr + st1], &work[z__ + st1],
00444 &work[poles + st1], &iwork[givptr + st1], &iwork[
00445 givcol + st1], n, &iwork[perm + st1], &work[givnum +
00446 st1], &work[c__ + st1], &work[s + st1], &work[nwork],
00447 &iwork[iwk], info);
00448 if (*info != 0) {
00449 return 0;
00450 }
00451 bxst = bx + st1;
00452 dlalsa_(&icmpq2, smlsiz, &nsize, nrhs, &b[st + b_dim1], ldb, &
00453 work[bxst], n, &work[u + st1], n, &work[vt + st1], &
00454 iwork[k + st1], &work[difl + st1], &work[difr + st1],
00455 &work[z__ + st1], &work[poles + st1], &iwork[givptr +
00456 st1], &iwork[givcol + st1], n, &iwork[perm + st1], &
00457 work[givnum + st1], &work[c__ + st1], &work[s + st1],
00458 &work[nwork], &iwork[iwk], info);
00459 if (*info != 0) {
00460 return 0;
00461 }
00462 }
00463 st = i__ + 1;
00464 }
00465
00466 }
00467
00468
00469
00470 tol = rcnd * (d__1 = d__[idamax_(n, &d__[1], &c__1)], abs(d__1));
00471
00472 i__1 = *n;
00473 for (i__ = 1; i__ <= i__1; ++i__) {
00474
00475
00476
00477
00478 if ((d__1 = d__[i__], abs(d__1)) <= tol) {
00479 dlaset_("A", &c__1, nrhs, &c_b6, &c_b6, &work[bx + i__ - 1], n);
00480 } else {
00481 ++(*rank);
00482 dlascl_("G", &c__0, &c__0, &d__[i__], &c_b11, &c__1, nrhs, &work[
00483 bx + i__ - 1], n, info);
00484 }
00485 d__[i__] = (d__1 = d__[i__], abs(d__1));
00486
00487 }
00488
00489
00490
00491 icmpq2 = 1;
00492 i__1 = nsub;
00493 for (i__ = 1; i__ <= i__1; ++i__) {
00494 st = iwork[i__];
00495 st1 = st - 1;
00496 nsize = iwork[sizei + i__ - 1];
00497 bxst = bx + st1;
00498 if (nsize == 1) {
00499 dcopy_(nrhs, &work[bxst], n, &b[st + b_dim1], ldb);
00500 } else if (nsize <= *smlsiz) {
00501 dgemm_("T", "N", &nsize, nrhs, &nsize, &c_b11, &work[vt + st1], n,
00502 &work[bxst], n, &c_b6, &b[st + b_dim1], ldb);
00503 } else {
00504 dlalsa_(&icmpq2, smlsiz, &nsize, nrhs, &work[bxst], n, &b[st +
00505 b_dim1], ldb, &work[u + st1], n, &work[vt + st1], &iwork[
00506 k + st1], &work[difl + st1], &work[difr + st1], &work[z__
00507 + st1], &work[poles + st1], &iwork[givptr + st1], &iwork[
00508 givcol + st1], n, &iwork[perm + st1], &work[givnum + st1],
00509 &work[c__ + st1], &work[s + st1], &work[nwork], &iwork[
00510 iwk], info);
00511 if (*info != 0) {
00512 return 0;
00513 }
00514 }
00515
00516 }
00517
00518
00519
00520 dlascl_("G", &c__0, &c__0, &c_b11, &orgnrm, n, &c__1, &d__[1], n, info);
00521 dlasrt_("D", n, &d__[1], info);
00522 dlascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, nrhs, &b[b_offset], ldb,
00523 info);
00524
00525 return 0;
00526
00527
00528
00529 }