2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012, 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>
40 #include "gmx_lapack.h"
41 #include "lapack_limits.h"
44 F77_FUNC(sgesdd,SGESDD)(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 float 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] = (float) maxwrk;
191 if (*m == 0 || *n == 0) {
198 minval = GMX_FLOAT_MIN;
199 safemin = minval / eps;
200 smlnum = sqrt(safemin) / eps;
203 bignum = 1. / smlnum;
206 anrm = F77_FUNC(slange,SLANGE)("M", m, n, &a[a_offset], lda, dum);
208 if (anrm > 0. && anrm < smlnum) {
210 F77_FUNC(slascl,SLASCL)("G",&c__0,&c__0,&anrm,&smlnum,m,n,&a[a_offset],lda,&ierr);
211 } else if (anrm > bignum) {
213 F77_FUNC(slascl,SLASCL)("G",&c__0,&c__0,&anrm,&bignum,m,n,&a[a_offset],lda,&ierr);
224 i__1 = *lwork - nwork + 1;
225 F77_FUNC(sgeqrf,SGEQRF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
230 F77_FUNC(slaset,SLASET)("L", &i__1, &i__2, &zero, &zero, &a[a_dim1 + 2],
237 i__1 = *lwork - nwork + 1;
238 F77_FUNC(sgebrd,SGEBRD)(n, n, &a[a_offset], lda, &s[1], &work[ie], &work[
239 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
242 F77_FUNC(sbdsdc,SBDSDC)("U", "N", n, &s[1], &work[ie], dum, &c__1, dum, &c__1,
243 dum, idum, &work[nwork], &iwork[1], info);
249 itau = iu + ldwrku * *n;
252 i__1 = *lwork - nwork + 1;
253 F77_FUNC(sgeqrf,SGEQRF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
255 F77_FUNC(slacpy,SLACPY)("L", m, n, &a[a_offset], lda, &u[u_offset], ldu);
257 i__1 = *lwork - nwork + 1;
258 F77_FUNC(sorgqr,SORGQR)(m, m, n, &u[u_offset], ldu, &work[itau], &work[nwork],
263 F77_FUNC(slaset,SLASET)("L", &i__1, &i__2, &zero, &zero, &a[a_dim1 + 2],
270 i__1 = *lwork - nwork + 1;
271 F77_FUNC(sgebrd,SGEBRD)(n, n, &a[a_offset], lda, &s[1], &work[ie], &work[
272 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
274 F77_FUNC(sbdsdc,SBDSDC)("U", "I", n, &s[1], &work[ie], &work[iu], n, &vt[
275 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
278 i__1 = *lwork - nwork + 1;
279 F77_FUNC(sormbr,SORMBR)("Q", "L", "N", n, n, n, &a[a_offset], lda, &work[
280 itauq], &work[iu], &ldwrku, &work[nwork], &i__1, &
282 i__1 = *lwork - nwork + 1;
283 F77_FUNC(sormbr,SORMBR)("P", "R", "T", n, n, n, &a[a_offset], lda, &work[
284 itaup], &vt[vt_offset], ldvt, &work[nwork], &i__1, &
287 F77_FUNC(sgemm,SGEMM)("N", "N", m, n, n, &one, &u[u_offset], ldu, &work[iu]
288 , &ldwrku, &zero, &a[a_offset], lda);
290 F77_FUNC(slacpy,SLACPY)("F", m, n, &a[a_offset], lda, &u[u_offset], ldu);
300 i__1 = *lwork - nwork + 1;
301 F77_FUNC(sgebrd,SGEBRD)(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
302 work[itaup], &work[nwork], &i__1, &ierr);
305 F77_FUNC(sbdsdc,SBDSDC)("U", "N", n, &s[1], &work[ie], dum, &c__1, dum, &c__1,
306 dum, idum, &work[nwork], &iwork[1], info);
309 F77_FUNC(slaset,SLASET)("F", m, m, &zero, &zero, &u[u_offset], ldu);
310 F77_FUNC(sbdsdc,SBDSDC)("U", "I", n, &s[1], &work[ie], &u[u_offset], ldu, &vt[
311 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
316 F77_FUNC(slaset,SLASET)("F", &i__1, &i__2, &zero, &one, &u[*n + 1 + (*n +
319 i__1 = *lwork - nwork + 1;
320 F77_FUNC(sormbr,SORMBR)("Q", "L", "N", m, m, n, &a[a_offset], lda, &work[
321 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
322 i__1 = *lwork - nwork + 1;
323 F77_FUNC(sormbr,SORMBR)("P", "R", "T", n, n, m, &a[a_offset], lda, &work[
324 itaup], &vt[vt_offset],ldvt,&work[nwork],&i__1,&ierr);
338 i__1 = *lwork - nwork + 1;
339 F77_FUNC(sgelqf,SGELQF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
344 F77_FUNC(slaset,SLASET)("U", &i__1, &i__2, &zero, &zero, &a[(a_dim1*2) +
351 i__1 = *lwork - nwork + 1;
352 F77_FUNC(sgebrd,SGEBRD)(m, m, &a[a_offset], lda, &s[1], &work[ie], &work[
353 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
356 F77_FUNC(sbdsdc,SBDSDC)("U", "N", m, &s[1], &work[ie], dum, &c__1, dum, &c__1,
357 dum, idum, &work[nwork], &iwork[1], info);
364 itau = ivt + ldwkvt * *m;
367 i__1 = *lwork - nwork + 1;
368 F77_FUNC(sgelqf,SGELQF)(m, n, &a[a_offset], lda, &work[itau], &work[nwork], &
370 F77_FUNC(slacpy,SLACPY)("U", m, n, &a[a_offset], lda, &vt[vt_offset], ldvt);
372 i__1 = *lwork - nwork + 1;
373 F77_FUNC(sorglq,SORGLQ)(n, n, m, &vt[vt_offset], ldvt, &work[itau], &work[
374 nwork], &i__1, &ierr);
378 F77_FUNC(slaset,SLASET)("U", &i__1, &i__2, &zero, &zero, &a[(a_dim1*2) +
385 i__1 = *lwork - nwork + 1;
386 F77_FUNC(sgebrd,SGEBRD)(m, m, &a[a_offset], lda, &s[1], &work[ie], &work[
387 itauq], &work[itaup], &work[nwork], &i__1, &ierr);
389 F77_FUNC(sbdsdc,SBDSDC)("U", "I", m, &s[1], &work[ie], &u[u_offset], ldu, &
390 work[ivt], &ldwkvt, dum, idum, &work[nwork], &iwork[1]
393 i__1 = *lwork - nwork + 1;
394 F77_FUNC(sormbr,SORMBR)("Q", "L", "N", m, m, m, &a[a_offset], lda, &work[
395 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
396 i__1 = *lwork - nwork + 1;
397 F77_FUNC(sormbr,SORMBR)("P", "R", "T", m, m, m, &a[a_offset], lda, &work[
398 itaup], &work[ivt], &ldwkvt, &work[nwork], &i__1, &
401 F77_FUNC(sgemm,SGEMM)("N", "N", m, n, m, &one, &work[ivt], &ldwkvt, &vt[
402 vt_offset], ldvt, &zero, &a[a_offset], lda);
404 F77_FUNC(slacpy,SLACPY)("F", m, n, &a[a_offset], lda, &vt[vt_offset], ldvt);
415 i__1 = *lwork - nwork + 1;
416 F77_FUNC(sgebrd,SGEBRD)(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
417 work[itaup], &work[nwork], &i__1, &ierr);
420 F77_FUNC(sbdsdc,SBDSDC)("L", "N", m, &s[1], &work[ie], dum, &c__1, dum, &c__1,
421 dum, idum, &work[nwork], &iwork[1], info);
423 F77_FUNC(slaset,SLASET)("F", n, n, &zero, &zero, &vt[vt_offset], ldvt);
424 F77_FUNC(sbdsdc,SBDSDC)("L", "I", m, &s[1], &work[ie], &u[u_offset], ldu, &vt[
425 vt_offset], ldvt, dum, idum, &work[nwork], &iwork[1],
430 F77_FUNC(slaset,SLASET)("F", &i__1, &i__2, &zero, &one, &vt[*m + 1 + (*m +
431 1) * vt_dim1], ldvt);
433 i__1 = *lwork - nwork + 1;
434 F77_FUNC(sormbr,SORMBR)("Q", "L", "N", m, m, n, &a[a_offset], lda, &work[
435 itauq], &u[u_offset], ldu, &work[nwork], &i__1, &ierr);
436 i__1 = *lwork - nwork + 1;
437 F77_FUNC(sormbr,SORMBR)("P", "R", "T", n, n, m, &a[a_offset], lda, &work[
438 itaup], &vt[vt_offset], ldvt, &work[nwork], &i__1, &
448 F77_FUNC(slascl,SLASCL)("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
452 F77_FUNC(slascl,SLASCL)("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
457 work[1] = (float) maxwrk;