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.
38 #include "gmx_lapack.h"
39 #include "lapack_limits.h"
41 #include <types/simple.h>
44 F77_FUNC(sbdsdc,SBDSDC)(const char *uplo,
59 int u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;
68 int ivt, difl, difr, ierr, perm, mlvl, sqre;
69 int poles, iuplo, nsize, start;
73 int givnum, givptr, qstart, smlsiz, wstart, smlszp;
82 u_offset = 1 + u_dim1;
85 vt_offset = 1 + vt_dim1;
92 k = iu = z__ = ic = is = ivt = difl = difr = perm = 0;
93 poles = givnum = givptr = givcol = 0;
95 smlsiz = DBDSDC_SMALLSIZE;
98 iuplo = (*uplo=='U' || *uplo=='u') ? 1 : 2;
122 q[1] = (d__[1]>0) ? 1.0 : -1.0;
123 q[smlsiz * *n + 1] = 1.;
124 } else if (icompq == 2) {
125 u[u_dim1 + 1] = (d__[1]>0) ? 1.0 : -1.0;
126 vt[vt_dim1 + 1] = 1.;
128 d__[1] = fabs(d__[1]);
135 F77_FUNC(scopy,SCOPY)(n, &d__[1], &c_1, &q[1], &c_1);
137 F77_FUNC(scopy,SCOPY)(&i__1, &e[1], &c_1, &q[*n + 1], &c_1);
141 wstart = (*n << 1) - 1;
143 for (i__ = 1; i__ <= i__1; ++i__) {
144 F77_FUNC(slartg,SLARTG)(&d__[i__], &e[i__], &cs, &sn, &r__);
146 e[i__] = sn * d__[i__ + 1];
147 d__[i__ + 1] = cs * d__[i__ + 1];
149 q[i__ + (*n << 1)] = cs;
150 q[i__ + *n * 3] = sn;
151 } else if (icompq == 2) {
153 work[nm1 + i__] = -sn;
158 F77_FUNC(slasdq,SLASDQ)("U",&c_0,n,&c_0,&c_0,&c_0,&d__[1],&e[1],&vt[vt_offset],ldvt,
159 &u[u_offset], ldu, &u[u_offset], ldu, &work[wstart], info);
164 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &u[u_offset], ldu);
165 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &vt[vt_offset], ldvt);
166 F77_FUNC(slasdq,SLASDQ)("U",&c_0,n,n,n,&c_0,&d__[1],&e[1],&vt[vt_offset],ldvt,
167 &u[u_offset],ldu,&u[u_offset],ldu,&work[wstart],info);
168 } else if (icompq == 1) {
171 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &q[iu + (qstart - 1) * *n], n);
172 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &q[ivt + (qstart - 1) * *n], n);
173 F77_FUNC(slasdq,SLASDQ)("U", &c_0, n, n, n, &c_0, &d__[1], &e[1],
174 &q[ivt + (qstart - 1) * *n], n, &q[iu + (qstart - 1) * *n],
175 n, &q[iu + (qstart - 1) * *n], n, &work[wstart], info);
181 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &u[u_offset], ldu);
182 F77_FUNC(slaset,SLASET)("A", n, n, &zero, &one, &vt[vt_offset], ldvt);
185 orgnrm = F77_FUNC(slanst,SLANST)("M", n, &d__[1], &e[1]);
186 if ( fabs(orgnrm)<GMX_FLOAT_MIN) {
189 F77_FUNC(slascl,SLASCL)("G", &c_0, &c_0, &orgnrm, &one, n, &c_1, &d__[1], n, &ierr);
190 F77_FUNC(slascl,SLASCL)("G", &c_0, &c_0, &orgnrm, &one, &nm1, &c_1, &e[1], &nm1, &ierr);
194 mlvl = (int) (log((float) (*n) / (float) (smlsiz + 1)) /
203 z__ = difr + (mlvl << 1);
207 givnum = poles + (mlvl << 1);
212 givcol = perm + mlvl;
216 for (i__ = 1; i__ <= i__1; ++i__) {
217 if (fabs(d__[i__]) < eps)
218 d__[i__] = (d__[i__]>0) ? eps : -eps;
225 for (i__ = 1; i__ <= i__1; ++i__) {
226 if (fabs(e[i__]) < eps || i__ == nm1) {
228 nsize = i__ - start + 1;
229 } else if (fabs(e[i__]) >= eps) {
230 nsize = *n - start + 1;
232 nsize = i__ - start + 1;
234 u[*n + *n * u_dim1] = (d__[*n]>0) ? 1.0 : -1.0;
235 vt[*n + *n * vt_dim1] = 1.;
236 } else if (icompq == 1) {
237 q[*n + (qstart - 1) * *n] = (d__[*n]>0) ? 1.0 : -1.0;
238 q[*n + (smlsiz + qstart - 1) * *n] = 1.;
240 d__[*n] = fabs(d__[*n]);
243 F77_FUNC(slasd0,SLASD0)(&nsize, &sqre, &d__[start], &e[start],
244 &u[start + start * u_dim1], ldu,
245 &vt[start + start * vt_dim1],
246 ldvt, &smlsiz, &iwork[1], &work[wstart], info);
248 F77_FUNC(slasda,SLASDA)(&icompq, &smlsiz, &nsize, &sqre, &d__[start],
249 &e[start], &q[start + (iu + qstart - 2) * *n], n,
250 &q[start + (ivt + qstart - 2) * *n], &iq[start + k * *n],
251 &q[start + (difl + qstart - 2) * *n],
252 &q[start + (difr + qstart - 2) * *n],
253 &q[start + (z__ + qstart - 2) * *n],
254 &q[start + (poles + qstart - 2) * *n],
255 &iq[start + givptr * *n], &iq[start + givcol * *n], n,
256 &iq[start + perm * *n],
257 &q[start + (givnum + qstart - 2) * *n],
258 &q[start + (ic + qstart - 2) * *n],
259 &q[start + (is + qstart - 2) * *n], &work[wstart],
268 F77_FUNC(slascl,SLASCL)("G", &c_0, &c_0, &one, &orgnrm, n, &c_1, &d__[1], n, &ierr);
271 for (ii = 2; ii <= i__1; ++ii) {
276 for (j = ii; j <= i__2; ++j) {
287 } else if (icompq == 2) {
288 F77_FUNC(sswap,SSWAP)(n, &u[i__ * u_dim1 + 1],&c_1,&u[kk*u_dim1+1],&c_1);
289 F77_FUNC(sswap,SSWAP)(n, &vt[i__ + vt_dim1], ldvt, &vt[kk + vt_dim1], ldvt);
291 } else if (icompq == 1) {
302 if (iuplo == 2 && icompq == 2) {
303 F77_FUNC(slasr,SLASR)("L", "V", "B", n, n, &work[1], &work[*n], &u[u_offset], ldu);