1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2008, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Groningen Machine for Chemical Simulation
43 #include "gromacs/legacyheaders/gmx_fatal.h"
44 #include "gromacs/legacyheaders/smalloc.h"
45 #include "gromacs/legacyheaders/vec.h"
47 #include "gmx_lapack.h"
49 double **alloc_matrix(int n, int m)
54 /* There's always time for more pointer arithmetic! */
55 /* This is necessary in order to be able to work with LAPACK */
58 for (i = 1; (i < n); i++)
65 void free_matrix(double **a)
74 void matrix_multiply(FILE *fp, int n, int m, double **x, double **y, double **z)
81 fprintf(fp, "Multiplying %d x %d matrix with a %d x %d matrix\n",
86 for (i = 0; (i < n); i++)
88 for (j = 0; (j < m); j++)
90 fprintf(fp, " %7g", x[i][j]);
96 for (i = 0; (i < m); i++)
98 for (j = 0; (j < m); j++)
101 for (k = 0; (k < n); k++)
103 z[i][j] += x[k][i]*y[j][k];
109 static void dump_matrix(FILE *fp, const char *title, int n, double **a)
114 fprintf(fp, "%s\n", title);
115 for (i = 0; (i < n); i++)
118 for (j = 0; (j < n); j++)
120 fprintf(fp, " %8.2f", a[i][j]);
124 fprintf(fp, "Prod a[i][i] = %g\n", d);
127 int matrix_invert(FILE *fp, int n, double **a)
129 int i, j, m, lda, *ipiv, lwork, info;
130 double **test = NULL, **id, *work;
135 fprintf(fp, "Inverting %d square matrix\n", n);
136 test = alloc_matrix(n, n);
137 for (i = 0; (i < n); i++)
139 for (j = 0; (j < n); j++)
141 test[i][j] = a[i][j];
144 dump_matrix(fp, "before inversion", n, a);
152 F77_FUNC(dgetrf, DGETRF) (&n, &m, a[0], &lda, ipiv, &info);
156 dump_matrix(fp, "after dgetrf", n, a);
163 F77_FUNC(dgetri, DGETRI) (&n, a[0], &lda, ipiv, work, &lwork, &info);
167 dump_matrix(fp, "after dgetri", n, a);
178 id = alloc_matrix(n, n);
179 matrix_multiply(fp, n, n, test, a, id);
180 dump_matrix(fp, "And here is the product of A and Ainv", n, id);
191 double multi_regression(FILE *fp, int nrow, double *y, int ncol,
192 double **xx, double *a0)
194 int row, niter, i, j;
195 double ax, chi2, **a, **at, **ata, *atx;
197 a = alloc_matrix(nrow, ncol);
198 at = alloc_matrix(ncol, nrow);
199 ata = alloc_matrix(ncol, ncol);
200 for (i = 0; (i < nrow); i++)
202 for (j = 0; (j < ncol); j++)
204 at[j][i] = a[i][j] = xx[j][i];
207 matrix_multiply(fp, nrow, ncol, a, at, ata);
208 if ((row = matrix_invert(fp, ncol, ata)) != 0)
210 gmx_fatal(FARGS, "Matrix inversion failed. Incorrect row = %d.\nThis probably indicates that you do not have sufficient data points, or that some parameters are linearly dependent.",
215 for (i = 0; (i < ncol); i++)
218 for (j = 0; (j < nrow); j++)
220 atx[i] += at[i][j]*y[j];
223 for (i = 0; (i < ncol); i++)
226 for (j = 0; (j < ncol); j++)
228 a0[i] += ata[i][j]*atx[j];
232 for (j = 0; (j < nrow); j++)
235 for (i = 0; (i < ncol); i++)
239 chi2 += sqr(y[j]-ax);