2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013, by the GROMACS development team, led by
5 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 * others, as listed in the AUTHORS file in the top-level source
7 * directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
36 #include <types/simple.h>
39 #include "gmx_lapack.h"
40 #include "lapack_limits.h"
44 F77_FUNC(dgesdd,DGESDD)(const char *jobz,
59 int a_dim1, a_offset, u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;
65 int idum[1], ierr, itau;
66 int minmn, wrkbl, itaup, itauq, mnthr;
69 int wntqn, wntqo, wntqs;
72 int minwrk, ldwrku, maxwrk, ldwkvt;
73 double smlnum,minval, safemin;
82 a_offset = 1 + a_dim1;
86 u_offset = 1 + u_dim1;
89 vt_offset = 1 + vt_dim1;
95 minmn = (*m < *n) ? *m : *n;
96 mnthr = (int) (minmn * 11. / 6.);
97 wntqa = (*jobz=='a' || *jobz=='A');
98 wntqs = (*jobz=='s' || *jobz=='S');
99 wntqas = wntqa || wntqs;
100 wntqn = (*jobz=='o' || *jobz=='O');
101 wntqo = (*jobz=='n' || *jobz=='N');
105 lquery = *lwork == -1;
107 if (*info == 0 && *m > 0 && *n > 0) {
113 bdspac = *n * 3 * *n + (*n << 2);
119 i__1 = wrkbl, i__2 = bdspac + *n;
120 maxwrk = (i__1 > i__2) ? i__1 : i__2;
121 minwrk = bdspac + *n;
125 i__1 = wrkbl, i__2 = *n + (*m << 5);
126 wrkbl = (i__1 > i__2) ? i__1 : i__2;
127 i__1 = wrkbl, i__2 = bdspac + *n * 3;
128 wrkbl = (i__1 > i__2) ? i__1 : i__2;
129 maxwrk = wrkbl + *n * *n;
130 minwrk = bdspac + *n * *n + *n * 3;
134 wrkbl = *n * 3 + (*m + *n*32);
136 i__1 = wrkbl, i__2 = bdspac + *n * 3;
137 maxwrk = (i__1 > i__2) ? i__1 : i__2;
138 minwrk = *n * 3 + ((*m > bdspac) ? *m : bdspac);
140 i__1 = maxwrk, i__2 = bdspac + *n * 3;
141 maxwrk = (i__1 > i__2) ? i__1 : i__2;
142 minwrk = *n * 3 + ((*m > bdspac) ? *m : bdspac);
150 bdspac = *m * 3 * *m + (*m*4);
156 i__1 = wrkbl, i__2 = bdspac + *m;
157 maxwrk = (i__1 > i__2) ? i__1 : i__2;
158 minwrk = bdspac + *m;
162 i__1 = wrkbl, i__2 = *m + (*n*32);
163 wrkbl = (i__1 > i__2) ? i__1 : i__2;
165 i__1 = wrkbl, i__2 = bdspac + *m * 3;
166 wrkbl = (i__1 > i__2) ? i__1 : i__2;
167 maxwrk = wrkbl + *m * *m;
168 minwrk = bdspac + *m * *m + *m * 3;
171 wrkbl = *m * 3 + (*m + *n*32);
173 i__1 = wrkbl, i__2 = bdspac + *m * 3;
174 maxwrk = (i__1 > i__2) ? i__1 : i__2;
175 minwrk = *m * 3 + ((*m > bdspac) ? *m : bdspac);
177 i__1 = wrkbl, i__2 = bdspac + *m * 3;
178 maxwrk = (i__1 > i__2) ? i__1 : i__2;
179 minwrk = *m * 3 + ((*m > bdspac) ? *m : bdspac);
183 work[1] = (double) maxwrk;
193 if (*m == 0 || *n == 0) {
199 eps = GMX_DOUBLE_EPS;
200 minval = GMX_DOUBLE_MIN;
201 safemin = minval / eps;
202 smlnum = sqrt(safemin) / eps;
205 bignum = 1. / smlnum;
208 anrm = F77_FUNC(dlange,DLANGE)("M", m, n, &a[a_offset], lda, dum);
210 if (anrm > 0. && anrm < smlnum) {
212 F77_FUNC(dlascl,DLASCL)("G",&c__0,&c__0,&anrm,&smlnum,m,n,&a[a_offset],lda,&ierr);
213 } else if (anrm > bignum) {
215 F77_FUNC(dlascl,DLASCL)("G",&c__0,&c__0,&anrm,&bignum,m,n,&a[a_offset],lda,&ierr);
226 i__1 = *lwork - nwork + 1;
227 F77_FUNC(dgeqrf,DGEQRF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
232 F77_FUNC(dlaset,DLASET)("L", &i__1, &i__2, &zero, &zero, &a[a_dim1 + 2],
239 i__1 = *lwork - nwork + 1;
240 F77_FUNC(dgebrd,DGEBRD)(n, n, &a[a_offset], lda, &s[1], &work[ie], &work[
241 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
244 F77_FUNC(dbdsdc,DBDSDC)("U", "N", n, &s[1], &work[ie], dum, &c__1, dum, &c__1,
245 dum, idum, &work[nwork], &iwork[1], info);
251 itau = iu + ldwrku * *n;
254 i__1 = *lwork - nwork + 1;
255 F77_FUNC(dgeqrf,DGEQRF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
257 F77_FUNC(dlacpy,DLACPY)("L", m, n, &a[a_offset], lda, &u[u_offset], ldu);
259 i__1 = *lwork - nwork + 1;
260 F77_FUNC(dorgqr,DORGQR)(m, m, n, &u[u_offset], ldu, &work[itau], &work[nwork],
265 F77_FUNC(dlaset,DLASET)("L", &i__1, &i__2, &zero, &zero, &a[a_dim1 + 2],
272 i__1 = *lwork - nwork + 1;
273 F77_FUNC(dgebrd,DGEBRD)(n, n, &a[a_offset], lda, &s[1], &work[ie], &work[
274 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
276 F77_FUNC(dbdsdc,DBDSDC)("U", "I", n, &s[1], &work[ie], &work[iu], n, &vt[
277 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
280 i__1 = *lwork - nwork + 1;
281 F77_FUNC(dormbr,DORMBR)("Q", "L", "N", n, n, n, &a[a_offset], lda, &work[
282 itauq], &work[iu], &ldwrku, &work[nwork], &i__1, &
284 i__1 = *lwork - nwork + 1;
285 F77_FUNC(dormbr,DORMBR)("P", "R", "T", n, n, n, &a[a_offset], lda, &work[
286 itaup], &vt[vt_offset], ldvt, &work[nwork], &i__1, &
289 F77_FUNC(dgemm,DGEMM)("N", "N", m, n, n, &one, &u[u_offset], ldu, &work[iu]
290 , &ldwrku, &zero, &a[a_offset], lda);
292 F77_FUNC(dlacpy,DLACPY)("F", m, n, &a[a_offset], lda, &u[u_offset], ldu);
302 i__1 = *lwork - nwork + 1;
303 F77_FUNC(dgebrd,DGEBRD)(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
304 work[itaup], &work[nwork], &i__1, &ierr);
307 F77_FUNC(dbdsdc,DBDSDC)("U", "N", n, &s[1], &work[ie], dum, &c__1, dum, &c__1,
308 dum, idum, &work[nwork], &iwork[1], info);
311 F77_FUNC(dlaset,DLASET)("F", m, m, &zero, &zero, &u[u_offset], ldu);
312 F77_FUNC(dbdsdc,DBDSDC)("U", "I", n, &s[1], &work[ie], &u[u_offset], ldu, &vt[
313 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
318 F77_FUNC(dlaset,DLASET)("F", &i__1, &i__2, &zero, &one, &u[*n + 1 + (*n +
321 i__1 = *lwork - nwork + 1;
322 F77_FUNC(dormbr,DORMBR)("Q", "L", "N", m, m, n, &a[a_offset], lda, &work[
323 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
324 i__1 = *lwork - nwork + 1;
325 F77_FUNC(dormbr,DORMBR)("P", "R", "T", n, n, m, &a[a_offset], lda, &work[
326 itaup], &vt[vt_offset],ldvt,&work[nwork],&i__1,&ierr);
340 i__1 = *lwork - nwork + 1;
341 F77_FUNC(dgelqf,DGELQF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
346 F77_FUNC(dlaset,DLASET)("U", &i__1, &i__2, &zero, &zero, &a[(a_dim1*2) +
353 i__1 = *lwork - nwork + 1;
354 F77_FUNC(dgebrd,DGEBRD)(m, m, &a[a_offset], lda, &s[1], &work[ie], &work[
355 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
358 F77_FUNC(dbdsdc,DBDSDC)("U", "N", m, &s[1], &work[ie], dum, &c__1, dum, &c__1,
359 dum, idum, &work[nwork], &iwork[1], info);
366 itau = ivt + ldwkvt * *m;
369 i__1 = *lwork - nwork + 1;
370 F77_FUNC(dgelqf,DGELQF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
372 F77_FUNC(dlacpy,DLACPY)("U", m, n, &a[a_offset], lda, &vt[vt_offset], ldvt);
374 i__1 = *lwork - nwork + 1;
375 F77_FUNC(dorglq,DORGLQ)(n, n, m, &vt[vt_offset], ldvt, &work[itau], &work[
376 nwork], &i__1, &ierr);
380 F77_FUNC(dlaset,DLASET)("U", &i__1, &i__2, &zero, &zero, &a[(a_dim1*2) +
387 i__1 = *lwork - nwork + 1;
388 F77_FUNC(dgebrd,DGEBRD)(m, m, &a[a_offset], lda, &s[1], &work[ie], &work[
389 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
391 F77_FUNC(dbdsdc,DBDSDC)("U", "I", m, &s[1], &work[ie], &u[u_offset], ldu, &
392 work[ivt], &ldwkvt, dum, idum, &work[nwork], &iwork[1]
395 i__1 = *lwork - nwork + 1;
396 F77_FUNC(dormbr,DORMBR)("Q", "L", "N", m, m, m, &a[a_offset], lda, &work[
397 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
398 i__1 = *lwork - nwork + 1;
399 F77_FUNC(dormbr,DORMBR)("P", "R", "T", m, m, m, &a[a_offset], lda, &work[
400 itaup], &work[ivt], &ldwkvt, &work[nwork], &i__1, &
403 F77_FUNC(dgemm,DGEMM)("N", "N", m, n, m, &one, &work[ivt], &ldwkvt, &vt[
404 vt_offset], ldvt, &zero, &a[a_offset], lda);
406 F77_FUNC(dlacpy,DLACPY)("F", m, n, &a[a_offset], lda, &vt[vt_offset], ldvt);
417 i__1 = *lwork - nwork + 1;
418 F77_FUNC(dgebrd,DGEBRD)(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
419 work[itaup], &work[nwork], &i__1, &ierr);
422 F77_FUNC(dbdsdc,DBDSDC)("L", "N", m, &s[1], &work[ie], dum, &c__1, dum, &c__1,
423 dum, idum, &work[nwork], &iwork[1], info);
425 F77_FUNC(dlaset,DLASET)("F", n, n, &zero, &zero, &vt[vt_offset], ldvt);
426 F77_FUNC(dbdsdc,DBDSDC)("L", "I", m, &s[1], &work[ie], &u[u_offset], ldu, &vt[
427 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
432 F77_FUNC(dlaset,DLASET)("F", &i__1, &i__2, &zero, &one, &vt[*m + 1 + (*m +
433 1) * vt_dim1], ldvt);
435 i__1 = *lwork - nwork + 1;
436 F77_FUNC(dormbr,DORMBR)("Q", "L", "N", m, m, n, &a[a_offset], lda, &work[
437 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
438 i__1 = *lwork - nwork + 1;
439 F77_FUNC(dormbr,DORMBR)("P", "R", "T", n, n, m, &a[a_offset], lda, &work[
440 itaup], &vt[vt_offset], ldvt, &work[nwork], &i__1, &
450 F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
454 F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
459 work[1] = (double) maxwrk;