1
/*===========================================================================
2
Copyright (C) 1991-2009 European Southern Observatory (ESO)
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public
15
License along with this program; if not, write to the Free
16
Software Foundation, Inc., 675 Massachusetts Ave, Cambridge,
19
Correspondence concerning ESO-MIDAS should be addressed as follows:
20
Internet e-mail: midas@eso.org
21
Postal address: European Southern Observatory
22
Data Management Division
23
Karl-Schwarzschild-Strasse 2
24
D 85748 Garching bei Muenchen
26
===========================================================================*/
29
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34
.AUTHOR Cristian Levin - ESO La Silla
35
.PURPOSE Miscelanous mathematical algorithms:
36
- linear square fitting.
37
- fast polynomial evaluation.
38
- search of the median.
39
- polynomial interpolation.
40
.KEYWORDS interpolation, fitting, polynomial evaluation.
41
.COMMENTS Most of this routines were taken as they are from
42
the book "Numerical Recipes in C" -- 1st edition.
43
.VERSION 1.0 1-Apr-1991 Implementation
46
------------------------------------------------------------*/
51
/******************************************************
53
* lfit(): general linear least squares solution.
55
******************************************************/
56
void lfit( x, y, ndata, a, mfit, funcs )
57
int ndata, mfit; /* IN: no. of values, no. of coefficients */
58
double x[], y[], a[]; /* IN: (Xi,Yi) OUT: (Ai) */
62
double **covar, **beta, *afunc;
63
void spec_gaussj(), free_dmatrix(), free_dvector();
64
double **dmatrix(), *dvector();
66
beta = dmatrix( 1, mfit, 1, 1 );
67
covar = dmatrix( 1, mfit, 1, mfit );
68
afunc = dvector( 1, mfit );
70
for ( j = 1; j <= mfit; j++ ) {
71
for ( k = 1; k <= mfit; k++ )
76
for ( i = 1; i <= ndata; i++ ) {
77
(*funcs)( x[i], afunc, mfit );
78
for ( j = 1; j <= mfit; j++ ) {
79
for ( k = 1; k <= j; k++ )
80
covar[j][k] += afunc[j] * afunc[k];
81
beta[j][1] += y[i] * afunc[j];
85
for ( j = 2; j <= mfit; j++ )
86
for ( k = 1; k <= j-1; k++ )
87
covar[k][j] = covar[j][k];
89
spec_gaussj( covar, mfit, beta, 1 ); /* Matrix solution */
91
for ( j = 1; j <= mfit; j++ ) /* solution to coefficients a */
94
free_dvector( afunc, 1, mfit );
95
free_dmatrix( beta, 1, mfit, 1, 1 );
96
free_dmatrix( covar, 1, mfit, 1, mfit );
100
/******************************************************************
102
* spec_gaussj(): linear equation solution by Gauss-Jordan elimination
104
******************************************************************/
106
#define SWAP(a, b) {float temp = (a); (a) = (b); (b) = temp; }
108
void spec_gaussj( a, n, b, m )
109
double **a, /* IN : a[1..n][1..n] */
110
**b; /* IN/OUT: b[1..n][1..m] */
113
int *indxc, *indxr, *ipiv; /* for bookeeping in the pivoting */
114
int i, icol, irow, j, k;
116
double big, dum, pivinv;
117
void nrerror(), free_ivector();
121
indxc = ivector( 1, n );
122
indxr = ivector( 1, n );
123
ipiv = ivector( 1, n );
125
for ( i = 1; i <= n; i++ )
128
for ( i = 1; i <= n; i++ ) { /* main loop over columns to be reduced */
130
for ( j = 1; j <= n; j++ )
132
for ( k = 1; k <= n; k++ ) {
133
if ( ipiv[k] == 0 ) {
134
if ( fabs(a[j][k]) >= big ) {
140
else if ( ipiv[k] > 1 ) {
141
nrerror( "Tolerance too small for fitting" );
147
if ( irow != icol ) {
148
for ( j = 1; j <= n; j++ ) SWAP( a[irow][j], a[icol][j] );
149
for ( j = 1; j <= m; j++ ) SWAP( b[irow][j], b[icol][j] );
154
if ( a[icol][icol] == 0.0 ) {
155
nrerror( "Tolerance too small for fitting" );
159
pivinv = 1.0 / a[icol][icol];
161
for ( j = 1; j <= n; j++ ) a[icol][j] *= pivinv;
162
for ( j = 1; j <= m; j++ ) b[icol][j] *= pivinv;
164
for ( j = 1; j <= n; j++ )
168
for ( k = 1; k <= n; k++ ) a[j][k] -= a[icol][k] * dum;
169
for ( k = 1; k <= m; k++ ) b[j][k] -= b[icol][k] * dum;
173
for ( i = n; i >= 1; i-- )
174
if ( indxr[i] != indxc[i] )
175
for ( k = 1; k <= n; k++ )
176
SWAP( a[k][indxr[i]], a[k][indxc[i]] );
178
free_ivector( ipiv, 1, n );
179
free_ivector( indxc, 1, n );
180
free_ivector( indxr, 1, n );
183
/********************************************************************
185
* polint(): polynomial interpolation or extrapolation from N input
186
* points, using the Neville's algorithm.
188
********************************************************************/
190
void polint( xa, ya, n, x, y, dy )
191
float xa[], ya[], x, *y, *dy;
195
float den, dif, dift, ho, hp, w;
196
float *c, *d, *fvector();
197
void nrerror(), free_vector();
199
dif = fabs(x - xa[1]);
202
for ( i = 1; i <= n; i++ ) { /* find the index ns of the closest */
203
if ( (dift = fabs(x - xa[i])) < dif ) { /* table entry. */
207
c[i] = ya[i]; /* initialize the tableau of c's and d's */
210
*y = ya[ns--]; /* initial aprox. of y */
211
for ( m = 1; m < n; m++ ) {
212
for ( i = 1; i <= n-m; i++ ) {
216
if ( (den = ho - hp) == 0.0 ) {
217
nrerror( "Error in polynomial interpolation" );
224
*y += (*dy = (2*ns < (n-m) ? c[ns+1] : d[ns--]));
230
/************************************************************
232
* eval_fpoly(), eval_dpoly(): fast polynomial evaluation.
234
************************************************************/
236
float eval_fpoly(x, a, n)
238
float *a; /* coefficients (range: 1..n) */
244
for ( i = n; i >= 1; i-- )
250
double eval_dpoly(x, a, n)
252
double *a; /* coefficients (range: 1..n) */
258
for ( i = n; i >= 1; i-- )
264
/************************************************************
266
* median(): efficient search of the median.
268
************************************************************/
278
n2p = (n2 = n/2) + 1;
279
return((n % 2) ? x[n2p] : 0.5 * (x[n2] + x[n2p]));
282
/************************************************************
284
* piksrt(): sorting by straight insertion.
286
************************************************************/
298
while (i > 0 && arr[i] > a) {