Data Fitting and Uncertainty
Data Fitting and Uncertainty
Data Fitting and Uncertainty
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong><br />
A practical Introduction to Weighted Least Squares <strong>and</strong> beyond<br />
1. Edition<br />
July 2010<br />
by<br />
Tilo Strutz<br />
Appendix S - The Source Code
Appendix S<br />
The Source Code<br />
S.1 Licence <strong>and</strong> Disclaimer<br />
The source code was written, assembled <strong>and</strong> tested carefully by the author. Nevertheless<br />
the code might contain minor errors. It is not guaranteed that this<br />
software will work under arbitrary conditions <strong>and</strong> especially using odd data as<br />
input. Theauthor<strong>and</strong>thepublishertakenoresponsibility<strong>and</strong>offernowarranties<br />
on this software. In case that you recognise bugs or unexpected behaviour of the<br />
fitting procedure using this software, please report to the author directly or via<br />
the publisher.<br />
Copyright c○ 2010<br />
Tilo Strutz (the author). All rights reserved.<br />
1. The usage of the source code for academic use is free.<br />
2. The redistribution of source code either in original form, modified form,<br />
binary form, or part of other software is not allowed without explicit permission<br />
given by the author.<br />
3. All advertising materials or publications mentioning features or use of this<br />
software must cite the source properly as<br />
”Strutz, T.: <strong>Data</strong> fitting <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010”.<br />
4. Ifcommercialusageisplanned, pleasecontactthe authortoget information<br />
about details of a corresponding commercial licence.<br />
THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY<br />
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED<br />
TO,THEIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESS<br />
FORAPARTICULARPURPOSEAREDISCLAIMED.INNOEVENTSHALL<br />
THE AUTHOR OR THE PUBLISHER BE LIABLE FOR ANY DIRECT, IN-<br />
DIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<br />
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF<br />
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;<br />
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THE-<br />
ORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR<br />
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY<br />
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF<br />
THE POSSIBILITY OF SUCH DAMAGE.<br />
1
2 S The Source Code<br />
S.2 Main functions<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: fitting.c<br />
3: * Function....: data fitting with least squares<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 28.09.2009, 08.01.2010, 10.03.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #ifndef WIN32<br />
18: #include <br />
19: #endif<br />
20: #include "get_option.h"<br />
21: #include "errmsg.h"<br />
22: #include "matrix_utils.h"<br />
23: #include "functions.h"<br />
24: #include "functions_NIST.h"<br />
25: #include "macros.h"<br />
26: #include "prototypes.h"<br />
27: #include "defines.h"<br />
28:<br />
29: /* #define OUTPUT_DEVIATES */<br />
30:<br />
31: /* model functions */<br />
32: #define CONSTANT 0 /* constant value */<br />
33: #define LINEAR 1 /* f(x|a) = a1 + SUM_j a_j * x_(j-1) */<br />
34: #define COSINE_LIN 2 /* cosine linear */<br />
35: #define COSINE 5 /* cosine nonlinear */<br />
36: #define EXPONENTIAL 6 /* exponential */<br />
37: #define LOGARITHM 7 /* */<br />
38: #define GAUSSIAN_2 8 /* superposition of two Gaussians */<br />
39: #define EXPONENTIAL2 9 /* exponential 2 */<br />
40: #define EXPONENTIAL2_LIN 10 /* exponential 2, linearised */<br />
41: #define GEN_LAPLACE 11 /* generalised Laplacian distribution */<br />
42: #define COSINE_TREND 12 /* cosine with linear trend */<br />
43: #define GAUSSIAN_1 13 /* Gaussian */<br />
44: #define POLYNOM_2NDORD 16 /* 2nd order polynomial */<br />
45: #define POLYNOM_3RDORD 17 /* 3rd order polynomial */<br />
46: #define POLYNOMIAL 18 /* multi-order polynomial */<br />
47: #define POLYNOMIAL_REG 19 /* regularised */<br />
48: #define QUAD_SURFACE 20 /* parabolic 2D surface */<br />
49: #define COORD_TRANSF 21 /* rotation + translation */<br />
50: #define TRIGONOMETRIC1 22 /* trigonometric polynom, 1st order */<br />
51: #define TRIGONOMETRIC2 23 /* trigonometric polynom, 2st order */<br />
52: #define CIRCLE 24 /* circle */<br />
53: #define CIRCLE_LIN 25 /* circle, linearised */<br />
54: #define CIRCLE_TLS 26 /* circle, total least squares */<br />
55: #define NN_3x3x1 30 /* NeuralNet 3x3x1 */<br />
56: #define NN_3x2x1 31 /* NeuralNet 3x2x1 */<br />
57: #define NN_1x2x1 32 /* NeuralNet 1x2x1 */<br />
58: #define NN_2x2x1 33 /* NeuralNet 2x2x1 */<br />
59: #define NN_1x3x1 34 /* NeuralNet 1x3x1 */<br />
60: #define NIST_THURBER 40 /* NIST data set */<br />
61: #define NIST_MGH09 41 /* NIST data set */<br />
62: #define NIST_RAT42 42 /* NIST data set */<br />
63: #define NIST_RAT43 43 /* NIST data set */<br />
64: #define NIST_ECKERLE4 44 /* NIST data set */<br />
65: #define NIST_MGH10 45 /* NIST data set */<br />
66: #define NIST_BENNETT5 46 /* NIST data set */<br />
67: #define NIST_BOXBOD 47 /* NIST data set */<br />
68:<br />
69: /* defined in singvaldec.c */<br />
70: double euclid_dist( double a, double b);<br />
71:<br />
72: /*---------------------------------------------------------------<br />
73: * main()<br />
74: *--------------------------------------------------------------*/<br />
75: int<br />
76: main( int argc, char *argv[])<br />
77: {<br />
78: char *rtn = "main";<br />
79: char *field; /* used for reading text files */<br />
80: char *inname = NULL; /* filename of input data */<br />
81: char *outname = NULL; /* filename of results */<br />
82: /* string with list of columns containing conditions */<br />
83: char *column_cond_str=NULL;<br />
84: /* used for reading text files */<br />
85: char line[MAXLINELENGTH+1], *ptr;<br />
86: /* pointer to model function */<br />
87: double (*funct) (int, double*, double*) = NULL;<br />
88: /* pointer to its derivative */<br />
89: double (*funct_deriv) (double(*)(int,double*,double*),<br />
90: int,int,int,double*,double*) = NULL;<br />
91: double (*funct_deriv2) (double(*)(int,double*,double*),<br />
92: int,int,int,int,double*,double*) = NULL;<br />
93: /* pointer to initialisation function */<br />
94: int (*init) (int, double*,double*,double*,<br />
95: unsigned char*,FILE*) = NULL;<br />
96: int err = 0, i, j, o;<br />
97: int cnt; /* counter for observations */<br />
98: int column_cond[MAX_CONDITIONS], col, ch;<br />
99: int column_obs = 0; /* column containing the observations */<br />
100: int cond_dim = 1; /* dimensionality of conditions */<br />
101: int obs_dim = 1; /* dimensionality of observations */<br />
102: int type = 0; /* type of model function */<br />
103: int N; /* number of observations */<br />
104: int M; /* number of model parameters */<br />
105: int M_flag=0; /* flag for model LINEAR, POLYNOMIAL_REG */<br />
106: int numerical_flag = 0; /* force numerical derivation */<br />
107: int scale_flag = 0; /* enable scaling of conditions */<br />
108: int forget_flag = 0; /* enables reset of weights after<br />
109: * outlier removal */<br />
110: int num_outlier = 0; /* number of outliers */<br />
111: int out_mode = 0; /*<br />
112: * 0 .. no outlier removal<br />
113: * 1 .. enable Chauvenet’s outlier detection<br />
114: * 2 .. enable distance outlier detection<br />
115: */<br />
116: int weight_mode = 0;/*<br />
117: * 0 .. use equal weights (no weighting)<br />
118: * 1 .. enable deviates based weighting<br />
119: * 2 .. weighting by binning<br />
120: */<br />
121: int obs_per_bin = 50; /* observations per bin for<br />
122: * weight_mode = 2<br />
123: */<br />
124: int algo_mode = 1; /*<br />
125: * 0 .. use simple matrix inversion, M linear = 1;<br />
174: ls_flag->svd = 1; /* use SVD for linear systema as default */<br />
175: ls_flag->LM = 1; /* use Levenberg-Marquardt as default */<br />
176: ls_flag->chisq_target = 0;<br />
177: ls_flag->trueH = 0;<br />
178: ITERAT_MAX = 2000; /* declared in ls.c */<br />
179:<br />
180: #ifdef TESTT<br />
181: {<br />
182: double **a, **b;<br />
183: double det;<br />
184: a = matrix( 5, 5); /* matrix */<br />
185: b = matrix( 5, 5); /* matrix */<br />
186:<br />
187: a[0][0] = 2.; a[0][1] = 2.; a[0][2] = 3.; a[0][3] = 4.; a[0][4] = 5.;<br />
188: a[1][0] = 2.; a[1][1] = 3.; a[1][2] = 5.; a[1][3] = 5.; a[1][4] = 5.;<br />
189: a[2][0] = 1.; a[2][1] = 4.; a[2][2] = 4.; a[2][3] = 4.; a[2][4] = 2.;
S.2 Main functions 3<br />
190: a[3][0] = 1.; a[3][1] = 2.; a[3][2] = 1.; a[3][3] = 5.; a[3][4] = 3.; 286: ls_flag->chisq_target = 1;<br />
191: a[4][0] = 3.; a[4][1] = 3.; a[4][2] = 3.; a[4][3] = 2.; a[4][4] = 6.; 287: break;<br />
192:<br />
288: case ’x’:<br />
193: det = inverse_5x5( a, b);<br />
289: out_mode = atoi( OptArg);<br />
194: fprintf( stderr, "\n det = %f\n", det);<br />
290: /* 0 ... no removal; 1 ... Chauvenet’s;<br />
195: for ( i = 0; i < 5; i++)<br />
291: * 2 ... distance based;<br />
196: {<br />
292: */<br />
197: for ( j = 0; j < 5; j++)<br />
293: break;<br />
198: {<br />
294: case ’s’:<br />
199: fprintf( stderr, " %6.2f", b[i][j]);<br />
295: ls_flag->svd = 0;<br />
200: }<br />
296: /* disable special SVD function for solving linear model<br />
201: fprintf( stderr, "\n ");<br />
297: */<br />
202: }<br />
298: break;<br />
203:<br />
299: case ’f’:<br />
204: free_matrix( &a);<br />
300: forget_flag = 1;<br />
205: free_matrix( &b);<br />
301: /* forget weights after outlier removal<br />
206: exit( 1);<br />
302: */<br />
207: }<br />
303: break;<br />
208: #endif<br />
304: case ’?’:<br />
209: /* check comm<strong>and</strong>-line parameters */<br />
305: default:<br />
210: while (( optstr =<br />
306: usage( argv[0]); /* provides help */<br />
211: ( char*)get_option( argc, (const char **)argv)) != NULL) 307: err = 11;<br />
212: {<br />
308: goto endfunc;<br />
213: switch (optstr[1])<br />
309: }<br />
214: {<br />
310: }<br />
215: case ’a’:<br />
311:<br />
216: switch (optstr[2])<br />
312: /* check, whether all m<strong>and</strong>atory options were given */<br />
217: {<br />
313: err = check_opt( argv[0]);<br />
218: case ’\0’:<br />
314: if (err)<br />
219: algo_mode = atoi( OptArg);<br />
315: goto endfunc;<br />
220: /* 0 .. use simple matrix inversion, M trueH = 1;<br />
356: /* loop until all columns are read or<br />
261: break;<br />
357: * maximal number of columns is reached<br />
262: case ’I’: /* maximum number of iterations */<br />
358: */<br />
263: ITERAT_MAX = atoi( OptArg);<br />
359: ptr = &(column_cond_str[i]);<br />
264: break;<br />
360: sscanf( ptr, "%d", &(column_cond[col]));<br />
265: case ’M’: /* number of parameters (type == LINEAR) */ 361: do<br />
266: M = atoi( OptArg);<br />
362: { /* go to next number */<br />
267: M_flag = 1;<br />
363: i++;<br />
268: break;<br />
364: ch = column_cond_str[i];<br />
269: case ’L’: /* use plain Gauss-Newton */<br />
365: } while( ch != ’\0’ && ch != ’,’);<br />
270: ls_flag->LM = 0;<br />
366: i++;<br />
271: break;<br />
367: col++;<br />
272: case ’w’:<br />
368: } while ( ch != ’\0’ && col < MAX_CONDITIONS);<br />
273: weight_mode = atoi( OptArg);<br />
369: for ( i = col; i < MAX_CONDITIONS; i++)<br />
274: /* 0 ... equal weights; 1 ... deviates based; 370: {<br />
275: * 2 ... Bin-wise<br />
371: column_cond[i] = column_cond[i-1]+1;<br />
276: */<br />
372: }<br />
277: break;<br />
373: }<br />
278: case ’i’:<br />
374:<br />
279: inname = OptArg;<br />
375: /*<br />
280: break;<br />
376: * open the input file<br />
281: case ’o’:<br />
377: * determine the number of data sets<br />
282: outname = OptArg;<br />
378: */<br />
283: break;<br />
379: in = fopen( inname, "rt");<br />
284: case ’t’:<br />
380: if (in == NULL)<br />
285: chisq_target = atof( OptArg);<br />
381: {
4 S The Source Code<br />
382: err = errmsg( ERR_OPEN_READ, rtn, inname, 0);<br />
383: goto endfunc;<br />
384: }<br />
385: /* open out file */<br />
386: out = fopen( outname, "wt");<br />
387: if (out == NULL)<br />
388: {<br />
389: err = errmsg( ERR_OPEN_WRITE, rtn, outname, 0);<br />
390: goto endfunc;<br />
391: }<br />
392:<br />
393: fprintf( out, "# %s ===============================", rtn);<br />
394: fprintf( out, "\n# use data file: %s", inname);<br />
395:<br />
396: /* determine number of observations by counting of valid lines */<br />
397: N = 0;<br />
398: while (( ptr = fgets( line, MAXLINELENGTH, in)) != NULL)<br />
399: {<br />
400: /* skip comment lines (starting with ’#’) <strong>and</strong> empty ones */<br />
401: if ( is_data_line( line, MAXLINELENGTH) )<br />
402: {<br />
403: N++;<br />
404: if (strlen( line) == MAXLINELENGTH-1)<br />
405: {<br />
406: fprintf( stderr,<br />
407: "\n lines of input file are too long (>%d)",<br />
408: MAXLINELENGTH);<br />
409: fprintf( stderr, ", increase MAXLINELENGTH");<br />
410: }<br />
411: }<br />
412: }<br />
413: fclose( in);<br />
414:<br />
415: fprintf( stderr, "\n datafile contains %d data points\n", N);<br />
416:<br />
417: /*<br />
418: * set number of parameters <strong>and</strong> redirect pointer to functions<br />
419: */<br />
420: switch (type)<br />
421: {<br />
422: case CONSTANT:<br />
423: /* y = a1 */<br />
424: fprintf( out, "\n# constant function");<br />
425: printf( "\n constant function");<br />
426: if (numerical_flag)<br />
427: funct_deriv = f_deriv;/* use numerical differentiation */<br />
428: else<br />
429: funct_deriv = fconstant_deriv;<br />
430: M = 1;<br />
431: break;<br />
432:<br />
433: case LINEAR:<br />
434: /* f(x|a) = a1 + Sum_j(a_j*x_j) */<br />
435: fprintf( out, "\n# linear in x, order %d", M-1);<br />
436: printf( "\n linear in x, order %d", M-1);<br />
437: if (numerical_flag)<br />
438: funct_deriv = f_deriv;/* use numerical differentiation */<br />
439: else<br />
440: funct_deriv = flin_deriv;<br />
441: /* M is set via program parameter */<br />
442: cond_dim = M - 1; /* first parameter a1 is just an offset<br />
443: * w/o corresponding condition<br />
444: */<br />
445: break;<br />
446: case COSINE_LIN:<br />
447: /*<br />
448: * f(x|b) = b1 + b2 * cos( x - b3)<br />
449: * f(x|a) = a1 + a2 * cos( x) + a3 * sin( x)<br />
450: * a2 = b2 * cos(b3), a3 = b2 * sin(b3)<br />
451: * a1 = b1<br />
452: */<br />
453: fprintf( out, "\n# cosine (linear)");<br />
454: printf( "\n cosine (linear)");<br />
455: if (numerical_flag)<br />
456: funct_deriv = f_deriv;/* use numerical differentiation */<br />
457: else<br />
458: funct_deriv = fcosine_deriv;<br />
459: M = 3;<br />
460: break;<br />
461: case COSINE:<br />
462: /*<br />
463: * f(x|a) = a1 + a2 * cos( x - a3)<br />
464: */<br />
465: fprintf( out, "\n# cosine nonlinear");<br />
466: printf( "\n cosine nonlinear");<br />
467: if (numerical_flag)<br />
468: funct_deriv = f_deriv;/* use numerical differentiation */<br />
469: else<br />
470: funct_deriv = fcosine_nonlin_deriv;<br />
471: funct = fcosine_nonlin;<br />
472: init = init_cosine_nonlin;<br />
473: M = 3;<br />
474: ls_flag->linear = 0; /* nonlinear */<br />
475: break;<br />
476: case COSINE_TREND:<br />
477: /*<br />
478: * f(x|a) = a1 + a2 * x + a3 * cos( x - a4)<br />
479: */<br />
480: fprintf( out, "\n# cosine with trend");<br />
481: printf( "\n cosine with trend");<br />
482: if (numerical_flag)<br />
483: funct_deriv = f_deriv;/* use numerical differentiation */<br />
484: else<br />
485: funct_deriv = fcosine_trend_deriv;<br />
486: funct = fcosine_trend;<br />
487: init = init_cosine_trend;<br />
488: M = 4;<br />
489: ls_flag->linear = 0; /* nonlinear */<br />
490: break;<br />
491: case LOGARITHM:<br />
492: /* f(x|a) = a1 + a2 * exp( a3 * x) */<br />
493: fprintf( out, "\n# log( a1 * x)");<br />
494: printf( "\n log( a1 * x)");<br />
495: if (numerical_flag)<br />
496: funct_deriv = f_deriv;/* use numerical differentiation */<br />
497: else<br />
498: funct_deriv = flogarithmic_deriv; /* */<br />
499: funct_deriv2 = flogarithmic_deriv2; /* */<br />
500: funct = flogarithmic;<br />
501: init = init_logarithmic;<br />
502: M = 1;<br />
503: ls_flag->linear = 0; /* nonlinear */<br />
504: break;<br />
505: case EXPONENTIAL:<br />
506: /* f(x|a) = a1 + a2 * exp( a3 * x) */<br />
507: fprintf( out, "\n# exponential");<br />
508: printf( "\n exponential");<br />
509: funct_deriv = f_deriv; /* use numerical differentiation */<br />
510: funct = fexponential;<br />
511: init = init_exponential;<br />
512: M = 3;<br />
513: ls_flag->linear = 0; /* nonlinear */<br />
514: break;<br />
515: case GEN_LAPLACE:<br />
516: /* f(x|a) = a1 * exp( -|x|^a2 * a3) */<br />
517: fprintf( out, "\n# gen. Laplacian");<br />
518: printf( "\n gen. Laplacian");<br />
519: if (numerical_flag)<br />
520: funct_deriv = f_deriv;/* use numerical differentiation */<br />
521: else<br />
522: funct_deriv = fgen_laplace_deriv;<br />
523: funct_deriv = f_deriv;<br />
524: funct_deriv2 = NULL;<br />
525: funct = fgen_laplace;<br />
526: init = init_gen_laplace;<br />
527: M = 3;<br />
528: ls_flag->linear = 0; /* nonlinear */<br />
529: break;<br />
530: case GAUSSIAN_1:<br />
531: /*<br />
532: * f(x|a) = a1 * exp( a2 * (x-a3)^2) +<br />
533: */<br />
534: fprintf( out, "\n# single Gaussian");<br />
535: printf( "\n single Gaussian");<br />
536: if (numerical_flag)<br />
537: funct_deriv = f_deriv;/* use numerical differentiation */<br />
538: else<br />
539: funct_deriv = fgauss_deriv;<br />
540: funct_deriv2 = fgauss_deriv2;<br />
541: funct = fgauss1;<br />
542: init = init_gauss;<br />
543: M = 3;<br />
544: ls_flag->linear = 0; /* nonlinear */<br />
545: break;<br />
546: case GAUSSIAN_2:<br />
547: /*<br />
548: * f(x|a) = a1 * exp( a2 * (x-a3)^2) +<br />
549: * a4 * exp( a5 * (x-a6)^2)<br />
550: */<br />
551: fprintf( out, "\n# two Gaussians");<br />
552: printf( "\n two Gaussians");<br />
553: funct_deriv = f_deriv; /* use numerical differentiation */<br />
554: funct = fgauss2;<br />
555: init = init_gauss2;<br />
556: M = 6;<br />
557: ls_flag->linear = 0; /* nonlinear */<br />
558: break;<br />
559: case EXPONENTIAL2:<br />
560: /* f(x|a) = a2 * exp( a3 * x) */<br />
561: fprintf( out, "\n# exponential 2");<br />
562: printf( "\n exponential 2");<br />
563: if (numerical_flag)<br />
564: funct_deriv = f_deriv;/* use numerical differentiation */<br />
565: else<br />
566: funct_deriv = fexpon2_deriv;<br />
567: funct = fexpon2;<br />
568: init = init_expon2;<br />
569: M = 2;<br />
570: ls_flag->linear = 0; /* nonlinear */<br />
571: break;<br />
572: case EXPONENTIAL2_LIN:<br />
573: /* ln(f(x|a)) = ln(a2) + a3 * x */
S.2 Main functions 5<br />
574: fprintf( out, "\n# exponential 2, linearised");<br />
575: printf( "\n exponential 2, linearised");<br />
576: if (numerical_flag)<br />
577: funct_deriv = f_deriv;/* use numerical differentiation */<br />
578: else<br />
579: funct_deriv = flin_deriv;<br />
580: M = 2;<br />
581: break;<br />
582: case POLYNOM_2NDORD:<br />
583: /*<br />
584: * f(x|a) = a1 + a2 * x + a3 * x^2<br />
585: */<br />
586: fprintf( out, "\n# polynomial of 2nd order");<br />
587: printf( "\n polynomial of 2nd order");<br />
588: if (numerical_flag)<br />
589: funct_deriv = f_deriv;/* use numerical differentiation */<br />
590: else<br />
591: funct_deriv = fpolynom2_deriv;<br />
592: M = 3;<br />
593: break;<br />
594: case POLYNOM_3RDORD:<br />
595: /*<br />
596: * f(x|a) = a1 + a2 * x + a3 * x^2 + a4 * x^3<br />
597: */<br />
598: fprintf( out, "\n# polynomial of 3rd order");<br />
599: printf( "\n polynomial of 3rd order");<br />
600: if (numerical_flag)<br />
601: funct_deriv = f_deriv;/* use numerical differentiation */<br />
602: else<br />
603: funct_deriv = fpolynom3_deriv;<br />
604: M = 4;<br />
605: break;<br />
606: case POLYNOMIAL:<br />
607: /*<br />
608: * f(x|a) = a1 + a2 * x + a3 * x^2 + ...<br />
609: */<br />
610: fprintf( out, "\n# polynomial of %dth order", M-1);<br />
611: printf( "\n polynomial of %dth order", M-1);<br />
612: if (numerical_flag)<br />
613: funct_deriv = f_deriv;/* use numerical differentiation */<br />
614: else<br />
615: funct_deriv = fpolynomial_deriv;<br />
616: /* M is set via program parameter */<br />
617: break;<br />
618: case POLYNOMIAL_REG:<br />
619: /*<br />
620: * f(x|a) = a1 + a2 * x + a3 * x^2 + ...<br />
621: */<br />
622: if (M == 2)<br />
623: {<br />
624: fprintf( out, "\n# polynomial of 1st order");<br />
625: printf( "\n polynomial of 1st order");<br />
626: }<br />
627: else if (M==3)<br />
628: {<br />
629: fprintf( out, "\n# polynomial of 2nd order");<br />
630: printf( "\n polynomial of 2nd order");<br />
631: }<br />
632: else if (M==3)<br />
633: {<br />
634: fprintf( out, "\n# polynomial of 3rd order");<br />
635: printf( "\n polynomial of 3rd order");<br />
636: }<br />
637: else<br />
638: {<br />
639: fprintf( out, "\n# polynomial of %dth order", M-1);<br />
640: printf( "\n polynomial of %dth order", M-1);<br />
641: }<br />
642: fprintf( out, ", regularised (nonlinear)");<br />
643: printf( ", regularised (nonlinear)");<br />
644:<br />
645: if (numerical_flag)<br />
646: funct_deriv = f_deriv;/* use numerical differentiation */<br />
647: else<br />
648: funct_deriv = fpolynomial_deriv;<br />
649: funct = fpolynomial;<br />
650: init = init_polynomial;<br />
651: /* M is set via program parameter */<br />
652: ls_flag->linear = 0; /* nonlinear */<br />
653: break;<br />
654: case QUAD_SURFACE:<br />
655: /*<br />
656: * f(x|a) = a1 + a2*x1 + a3*x1^2 + a4*x2 +a5*x2^2<br />
657: */<br />
658: fprintf( out, "\n# quadratic surface");<br />
659: printf( "\n quadratic surface");<br />
660: if (numerical_flag)<br />
661: funct_deriv = f_deriv;/* use numerical differentiation */<br />
662: else<br />
663: funct_deriv = fquadsurface_deriv;<br />
664: cond_dim = 2;<br />
665: M = 5;<br />
666: break;<br />
667: case COORD_TRANSF:<br />
668: /*<br />
669: * f1(x|a) = a1 + cos(a3) * x1 - sin(a3) * x2<br />
670: * f2(x|a) = a2 + sin(a3) * x1 + cos(a3) * x2<br />
671: */<br />
672: fprintf( out, "\n# rotation");<br />
673: printf( "\n rotation");<br />
674: funct_deriv = f_deriv; /* use numerical differentiation */<br />
675: funct = frotation;<br />
676: init = init_rotation;<br />
677: M = 3;<br />
678: cond_dim = 2;<br />
679: obs_dim = 2;<br />
680: ls_flag->linear = 0; /* nonlinear */<br />
681: break;<br />
682: case TRIGONOMETRIC1:<br />
683: /*<br />
684: * f(x|a) = a1 + a2*cos(a3*x-a4)<br />
685: */<br />
686: fprintf( out, "\n# trigonometric 1st order");<br />
687: printf( "\n trigonometric 1st order");<br />
688: funct_deriv = f_deriv; /* use numerical differentiation */<br />
689: funct = ftrigonometric1;<br />
690: init = init_trigonometric1;<br />
691: M = 4;<br />
692: cond_dim = 1;<br />
693: obs_dim = 1;<br />
694: ls_flag->linear = 0; /* nonlinear */<br />
695: break;<br />
696: case TRIGONOMETRIC2:<br />
697: /*<br />
698: * f(x|a) = a1 + a2*cos(a3*x-a4) + a5*cos(2*a3*x-a6)<br />
699: */<br />
700: fprintf( out, "\n# trigonometric 2nd order");<br />
701: printf( "\n trigonometric 2nd order");<br />
702: funct_deriv = f_deriv; /* use numerical differentiation */<br />
703: funct = ftrigonometric2;<br />
704: init = init_trigonometric2;<br />
705: M = 6;<br />
706: cond_dim = 1;<br />
707: obs_dim = 1;<br />
708: ls_flag->linear = 0; /* nonlinear */<br />
709: break;<br />
710: case CIRCLE:<br />
711: /*<br />
712: * f(x|a) = 0 = (x1 - a1)^2 + (x2 - a2)^2 - a3*a3<br />
713: */<br />
714: fprintf( out, "\n# circle");<br />
715: printf( "\n circle");<br />
716: if (numerical_flag)<br />
717: funct_deriv = f_deriv;/* use numerical differentiation */<br />
718: else<br />
719: funct_deriv = fcircle_deriv;<br />
720: funct = fcircle;<br />
721: init = init_circle;<br />
722: M = 3;<br />
723: cond_dim = 2;<br />
724: obs_dim = 1;<br />
725: ls_flag->linear = 0; /* nonlinear */<br />
726: break;<br />
727: case CIRCLE_TLS:<br />
728: /*<br />
729: * f(x|a) = 0 = (sqrt[(x1 - a1)^2 + (x2 - a2)^2] - a3)^2<br />
730: */<br />
731: fprintf( out, "\n# circle, TLS");<br />
732: printf( "\n circle, TLS");<br />
733: if (numerical_flag)<br />
734: funct_deriv = f_deriv;/* use numerical differentiation */<br />
735: else<br />
736: funct_deriv = fcircleTLS_deriv;<br />
737: funct = fcircleTLS;<br />
738: init = init_circle;<br />
739: M = 3;<br />
740: cond_dim = 2;<br />
741: obs_dim = 1;<br />
742: ls_flag->linear = 0; /* nonlinear */<br />
743: break;<br />
744: case CIRCLE_LIN:<br />
745: /*<br />
746: * f(x|a) = 0 = (x1 - a1)^2 + (x2 - a2)^2 - a3*a3<br />
747: * f(x|b) = x1^2 + x2^2 = b1*x1 + b2*x2 - b3<br />
748: * b1 = 2*a1, b2 = 2*a2, b3 = a1^2 + a2^2 - a3^2<br />
749: */<br />
750: fprintf( out, "\n# circle, linearised");<br />
751: printf( "\n circle, linearised");<br />
752: if (numerical_flag)<br />
753: funct_deriv = f_deriv;/* use numerical differentiation */<br />
754: else<br />
755: funct_deriv = fcirclelin_deriv;<br />
756: init = init_circlelin;<br />
757: M = 3;<br />
758: cond_dim = 2;<br />
759: obs_dim = 1;<br />
760: ls_flag->linear = 1; /* linear */<br />
761: break;<br />
762: case NN_3x3x1:<br />
763: /*<br />
764: * f(x|a) = neural network 3x3x1<br />
765: */
6 S The Source Code<br />
766: fprintf( out, "\n# NN 3x3x1");<br />
767: printf( "\n NN 3x3x1");<br />
768: funct_deriv = f_deriv; /* use numerical differentiation */<br />
769: funct = fNN_3_3;<br />
770: init = init_NN3x3x1;<br />
771: M = 16;<br />
772: cond_dim = 3;<br />
773: obs_dim = 1;<br />
774: ls_flag->linear = 0; /* nonlinear */<br />
775: break;<br />
776: case NN_3x2x1:<br />
777: /*<br />
778: * f(x|a) = neural network 3x2x1<br />
779: */<br />
780: fprintf( out, "\n# NN 3x2x1");<br />
781: printf( "\n NN 3x2x1");<br />
782: funct_deriv = f_deriv; /* use numerical differentiation */<br />
783: funct = fNN_3_2;<br />
784: init = init_NN;<br />
785: M = 11;<br />
786: cond_dim = 3;<br />
787: obs_dim = 1;<br />
788: ls_flag->linear = 0; /* nonlinear */<br />
789: break;<br />
790: case NN_1x2x1:<br />
791: /*<br />
792: * f(x|a) = neural network 1x2x1<br />
793: */<br />
794: fprintf( out, "\n# NN 1x2x1");<br />
795: printf( "\n NN 1x2x1");<br />
796: funct_deriv = f_deriv; /* use numerical differentiation */<br />
797: funct = fNN_1_2;<br />
798: init = init_NN;<br />
799: M = 7;<br />
800: cond_dim = 1;<br />
801: obs_dim = 1;<br />
802: ls_flag->linear = 0; /* nonlinear */<br />
803: break;<br />
804: case NN_2x2x1:<br />
805: /*<br />
806: * f(x|a) = neural network 2x2x1<br />
807: */<br />
808: fprintf( out, "\n# NN 2x2x1");<br />
809: printf( "\n NN 2x2x1");<br />
810: funct_deriv = f_deriv; /* use numerical differentiation */<br />
811: funct = fNN_2_2;<br />
812: init = init_NN;<br />
813: M = 9;<br />
814: cond_dim = 2;<br />
815: obs_dim = 1;<br />
816: ls_flag->linear = 0; /* nonlinear */<br />
817: break;<br />
818: case NN_1x3x1:<br />
819: /*<br />
820: * f(x|a) = neural network 1x2x1<br />
821: */<br />
822: fprintf( out, "\n# NN 1x3x1");<br />
823: printf( "\n NN 1x3x1");<br />
824: funct_deriv = f_deriv; /* use numerical differentiation */<br />
825: funct = fNN_1_3;<br />
826: init = init_NN1x3x1;<br />
827: M = 10;<br />
828: cond_dim = 1;<br />
829: obs_dim = 1;<br />
830: ls_flag->linear = 0; /* nonlinear */<br />
831: break;<br />
832: case NIST_THURBER:<br />
833: /*<br />
834: * f(x|a) =(a1 + a2*x + a3*x**2 + a4*x**3) /<br />
835: * (1 + a5*x + a6*x**2 + a7*x**3)<br />
836: */<br />
837: fprintf( out, "\n# NIST_THURBER");<br />
838: printf( "\n NIST_THURBER");<br />
839: if (numerical_flag)<br />
840: funct_deriv = f_deriv;/* use numerical differentiation */<br />
841: else<br />
842: funct_deriv = fNIST_thurber_deriv;<br />
843: funct = fNIST_thurber;<br />
844: init = init_NIST_thurber;<br />
845: M = 7;<br />
846: cond_dim = 1;<br />
847: obs_dim = 1;<br />
848: ls_flag->linear = 0; /* nonlinear */<br />
849: break;<br />
850: case NIST_MGH09:<br />
851: /*<br />
852: * f(x|a) =a1 * (x**2 + a2*x) / (x*x + a3*x + a4)<br />
853: */<br />
854: fprintf( out, "\n# NIST_MGH09");<br />
855: printf( "\n NIST_MGH09");<br />
856: if (numerical_flag)<br />
857: funct_deriv = f_deriv;/* use numerical differentiation */<br />
858: else<br />
859: funct_deriv = fNIST_MGH09_deriv;<br />
860: funct = fNIST_MGH09;<br />
861: init = init_NIST_MGH09;<br />
862: M = 4;<br />
863: cond_dim = 1;<br />
864: obs_dim = 1;<br />
865: ls_flag->linear = 0; /* nonlinear */<br />
866: break;<br />
867: case NIST_RAT42:<br />
868: /*<br />
869: * f(x|a) = a1 / (1 + exp(a2 - a3*x))<br />
870: */<br />
871: fprintf( out, "\n# NIST_Rat42");<br />
872: printf( "\n NIST_Rat42");<br />
873: if (numerical_flag)<br />
874: funct_deriv = f_deriv;/* use numerical differentiation */<br />
875: else<br />
876: funct_deriv = fNIST_Rat42_deriv;<br />
877: funct = fNIST_Rat42;<br />
878: init = init_NIST_Rat42;<br />
879: M = 3;<br />
880: cond_dim = 1;<br />
881: obs_dim = 1;<br />
882: ls_flag->linear = 0; /* nonlinear */<br />
883: break;<br />
884: case NIST_RAT43:<br />
885: /*<br />
886: * f(x|a) = a1 / [1 + exp(a2 - a3*x)]^(1/a4)<br />
887: */<br />
888: fprintf( out, "\n# NIST_Rat43");<br />
889: printf( "\n NIST_Rat43");<br />
890: if (numerical_flag)<br />
891: funct_deriv = f_deriv;/* use numerical differentiation */<br />
892: else<br />
893: funct_deriv = fNIST_Rat43_deriv;<br />
894: funct = fNIST_Rat43;<br />
895: init = init_NIST_Rat43;<br />
896: M = 4;<br />
897: cond_dim = 1;<br />
898: obs_dim = 1;<br />
899: ls_flag->linear = 0; /* nonlinear */<br />
900: break;<br />
901: case NIST_ECKERLE4:<br />
902: /*<br />
903: * f(x|a) = a1 / a2 * exp(-0.5*((x -a3)/ a2)^2)<br />
904: */<br />
905: fprintf( out, "\n# NIST_ECKERLE4");<br />
906: printf( "\n NIST_ECKERLE4");<br />
907: if (numerical_flag)<br />
908: funct_deriv = f_deriv;/* use numerical differentiation */<br />
909: else<br />
910: funct_deriv = fNIST_Eckerle4_deriv;<br />
911: funct = fNIST_Eckerle4;<br />
912: init = init_NIST_Eckerle4;<br />
913: M = 3;<br />
914: cond_dim = 1;<br />
915: obs_dim = 1;<br />
916: ls_flag->linear = 0; /* nonlinear */<br />
917: break;<br />
918: case NIST_MGH10:<br />
919: /*<br />
920: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
921: */<br />
922: fprintf( out, "\n# NIST_MGH10");<br />
923: printf( "\n NIST_MGH10");<br />
924: if (numerical_flag)<br />
925: funct_deriv = f_deriv;/* use numerical differentiation */<br />
926: else<br />
927: funct_deriv = fNIST_MGH10_deriv;<br />
928: funct_deriv2 = fNIST_MGH10_deriv2;<br />
929: funct = fNIST_MGH10;<br />
930: init = init_NIST_MGH10;<br />
931: M = 3;<br />
932: cond_dim = 1;<br />
933: obs_dim = 1;<br />
934: ls_flag->linear = 0; /* nonlinear */<br />
935: break;<br />
936: case NIST_BENNETT5:<br />
937: /*<br />
938: * f(x|a) = a1 * (x+a2)^(-1/a3)<br />
939: */<br />
940: fprintf( out, "\n# NIST_BENNETT5");<br />
941: printf( "\n NIST_BENNETT5");<br />
942: if (numerical_flag)<br />
943: funct_deriv = f_deriv;/* use numerical differentiation */<br />
944: else<br />
945: funct_deriv = fNIST_Bennett5_deriv; /* */<br />
946: funct = fNIST_Bennett5;<br />
947: init = init_NIST_Bennett5;<br />
948: M = 3;<br />
949: cond_dim = 1;<br />
950: obs_dim = 1;<br />
951: ls_flag->linear = 0; /* nonlinear */<br />
952: break;<br />
953: case NIST_BOXBOD:<br />
954: /* f(x|a) = a1 *(1 - exp( -a2 * x) */<br />
955: fprintf( out, "\n# NIST_BOXBOD");<br />
956: printf( "\n NIST_BOXBOD");<br />
957: if (numerical_flag)
S.2 Main functions 7<br />
958: funct_deriv = f_deriv;/* use numerical differentiation */<br />
959: else<br />
960: funct_deriv = fNIST_BoxBOD_deriv;<br />
961: funct = fNIST_BoxBOD;<br />
962: init = init_NIST_BoxBOD;<br />
963: M = 2;<br />
964: ls_flag->linear = 0; /* nonlinear */<br />
965: break;<br />
966: default:<br />
967: err = errmsg( ERR_NOT_DEFINED, rtn, "-m ", type);<br />
968: usage( argv[0]);<br />
969: goto endfunc;<br />
970: }<br />
971: /* if column for observation is not given explicitely by a<br />
972: * comm<strong>and</strong>-line parameter, then assume the column following<br />
973: * the conditions<br />
974: */<br />
975: if (column_obs == 0) column_obs = cond_dim + 1;<br />
976: printf( "\n");<br />
977: fflush( stdout);<br />
978:<br />
979: if (M > 5 && algo_mode == 0)<br />
980: {<br />
981: fprintf( stderr, "\n too much parameters (%d) ", M);<br />
982: fprintf( stderr, "for st<strong>and</strong>ard matrix inversion");<br />
983: usage( argv[0]);<br />
984: err = 42;<br />
985: goto endfunc;<br />
986: }<br />
987:<br />
988: if (M > M_MAX)<br />
989: {<br />
990: fprintf( stderr, "\n too much parameters (%d) ", M);<br />
991: fprintf( stderr, "maximum is %d", M_MAX);<br />
992: err = 43;<br />
993: goto endfunc;<br />
994: }<br />
995:<br />
996: if (N < M)<br />
997: {<br />
998: fprintf( stderr, "\nToo less observations (%d) compared ", N);<br />
999: fprintf( stderr, "to number of model parameters (%d)\n", M);<br />
1000: err = 44;<br />
1001: goto endfunc;<br />
1002: }<br />
1003: fprintf( out, "\n# Number of observations: %d", N);<br />
1004: fprintf( out, "\n# Number of parameters : %d", M);<br />
1005:<br />
1006: if (ls_flag->linear && ls_flag->svd && algo_mode != 1)<br />
1007: {<br />
1008: fprintf( stderr, "\n# option ’-a %d’ is ignored, ", algo_mode);<br />
1009: fprintf( stderr, "since special SVD approach is used!");<br />
1010: algo_mode = 1;<br />
1011: }<br />
1012: if (ls_flag->trueH && funct_deriv2 == NULL)<br />
1013: {<br />
1014: fprintf( stderr,<br />
1015: "\n### function for 2nd derivativ was not initialised!");<br />
1016: err = 45;<br />
1017: goto endfunc;<br />
1018: }<br />
1019:<br />
1020: /*<br />
1021: * allocate memory<br />
1022: */<br />
1023: jacob = matrix( N * obs_dim, M); /* Jacobian */<br />
1024: covar = matrix( M, M); /* covariance matrix */<br />
1025:<br />
1026: obs = vector( N * obs_dim); /* observations */<br />
1027: datac = vector( N * obs_dim); /* calculated data using<br />
1028: f(x|a) */<br />
1029: cond = vector( N * cond_dim); /* conditions x */<br />
1030: weights = vector( N * obs_dim); /* weights */<br />
1031: weights_old = vector( N * obs_dim); /* weights one step back<br />
1032: */<br />
1033: deviate = vector( N * obs_dim); /* remaining differences */<br />
1034: /* remaining absolute differences */<br />
1035: deviates_abs = vector( N * obs_dim);<br />
1036: deltasq = vector( N * obs_dim); /* remaining squared<br />
1037: differences */<br />
1038:<br />
1039: /* open input file again */<br />
1040: in = fopen( inname, "rt");<br />
1041: if (in == NULL)<br />
1042: {<br />
1043: err = errmsg( ERR_OPEN_READ, rtn, inname, 0);<br />
1044: perror( "\nReason");<br />
1045: goto endfunc;<br />
1046: }<br />
1047:<br />
1048: fprintf( out, "\n# condition columns: ");<br />
1049: for (j = 0; j < cond_dim; j++)<br />
1050: {<br />
1051: fprintf( out, "%d ", column_cond[j]);<br />
1052: }<br />
1053:<br />
1054: fprintf( out, "\n# observations column: ");<br />
1055: for (o = 0; o < obs_dim; o++)<br />
1056: {<br />
1057: fprintf( out, "%d ", column_obs + o);<br />
1058: }<br />
1059: fprintf( out, "\n#");<br />
1060: if (!ls_flag->linear || (ls_flag->linear && !ls_flag->svd) )<br />
1061: {<br />
1062: fprintf( out, "\n# algorithm for inversion: ");<br />
1063: if (algo_mode == 0)<br />
1064: fprintf( out, "Cofactor");<br />
1065: else if (algo_mode == 1)<br />
1066: fprintf( out, "SVD");<br />
1067: else if (algo_mode == 2)<br />
1068: fprintf( out, "LU decomposition");<br />
1069: if (forget_flag)<br />
1070: fprintf( out, "\n# reset weights after outlier removal");<br />
1071: }<br />
1072: if (ls_flag->linear)<br />
1073: {<br />
1074: fprintf( out, "\n# fitting a linear system");<br />
1075: if (ls_flag->svd)<br />
1076: fprintf( out, "\n# use special SVD based algorithm");<br />
1077: }<br />
1078: else<br />
1079: {<br />
1080: fprintf( out, "\n# fitting a nonlinear system");<br />
1081: if (ls_flag->LM)<br />
1082: fprintf( out, "\n# use Levenberg-Marquardt method");<br />
1083: else<br />
1084: fprintf( out, "\n# use Gauss-Newton method");<br />
1085: if (ls_flag->chisq_target)<br />
1086: fprintf( out, "\n# chisq must be lower than %f", chisq_target);<br />
1087: }<br />
1088: /* write LS flags in output */<br />
1089:<br />
1090: /* read the conditions <strong>and</strong> observations */<br />
1091: for (i = 0; i < N; i++)<br />
1092: {<br />
1093: /* jump over comments <strong>and</strong> empty lines */<br />
1094: do<br />
1095: {<br />
1096: ptr = fgets( line, MAXLINELENGTH, in);<br />
1097: } while ( !is_data_line( line, MAXLINELENGTH) );<br />
1098:<br />
1099: /* loop over all conditions */<br />
1100: for (j = 0; j < cond_dim; j++)<br />
1101: {<br />
1102: /* if 0 was given, then assume that conditions are just<br />
1103: * serial numbers 1,2,3,...<br />
1104: */<br />
1105: if (column_cond[j] == 0)<br />
1106: {<br />
1107: if (cond_dim > 1)<br />
1108: {<br />
1109: fprintf( stderr,<br />
1110: "\n There is more than one condition (%d)!", cond_dim);<br />
1111: fprintf( stderr,<br />
1112: "\n Columns of conditions must be given via ’-cc’!\n");<br />
1113: goto endfunc;<br />
1114: }<br />
1115: cond[cond_dim * i + j] = i+1;<br />
1116: }<br />
1117: else<br />
1118: {<br />
1119: /* get string starting from desired column */<br />
1120: field = get_nth_field( line, column_cond[j]);<br />
1121: if (field != NULL)<br />
1122: {<br />
1123: /* multidimensional conditions are stored one after each<br />
1124: other */<br />
1125: sscanf( field, "%lf", &( cond[cond_dim * i + j]));<br />
1126: }<br />
1127: else<br />
1128: {<br />
1129: fprintf( stderr, "\n\n === %d th column does not exist",<br />
1130: column_cond[j]);<br />
1131: err = 13;<br />
1132: goto endfunc;<br />
1133: }<br />
1134: }<br />
1135: }<br />
1136: /* loop over all observations */<br />
1137: for (o = 0; o < obs_dim; o++)<br />
1138: {<br />
1139: /* get string starting from desired column */<br />
1140: field = get_nth_field( line, column_obs + o);<br />
1141: if (field != NULL)<br />
1142: {<br />
1143: sscanf( field, "%lf", &( obs[obs_dim * i + o]));<br />
1144: }<br />
1145: else<br />
1146: {<br />
1147: fprintf( stderr, "\n\n === %d th column does not exist",<br />
1148: column_obs);<br />
1149: err = 13;
8 S The Source Code<br />
1150: goto endfunc;<br />
1151: }<br />
1152: }<br />
1153: }<br />
1154: fclose( in);<br />
1155:<br />
1156: /*---------------------------------------------<br />
1157: * scaling of conditions, if enabled<br />
1158: */<br />
1159: if (scale_flag)<br />
1160: {<br />
1161: /* get maximum absolute value */<br />
1162: double max_cond, abs_cond;<br />
1163: switch (type)<br />
1164: {<br />
1165: case LINEAR:<br />
1166: max_cond = fabs( cond[0]);<br />
1167: for (i = 1; i < N*cond_dim; i++)<br />
1168: {<br />
1169: abs_cond = fabs( cond[i]);<br />
1170: if ( max_cond < abs_cond) max_cond = abs_cond;<br />
1171: }<br />
1172: scale_fac = 1./max_cond;<br />
1173:<br />
1174: /* do scaling */<br />
1175: for (i = 0; i < N*cond_dim; i++)<br />
1176: {<br />
1177: cond[i] *= scale_fac;<br />
1178: }<br />
1179: fprintf( out, "\n# scaling activated");<br />
1180: fprintf( out, ", scale_fac = %f", scale_fac);<br />
1181: /* For cond_dim > 1 it would be even better to scale each<br />
1182: * condition separately. This would require cond_dim<br />
1183: * different scaling factors<br />
1184: */<br />
1185: break;<br />
1186: case POLYNOMIAL:<br />
1187: /* scaling has no positive effect for these nonlinear<br />
1188: * model functions */<br />
1189: case NIST_RAT42:<br />
1190: case NIST_ECKERLE4:<br />
1191: case NIST_MGH10:<br />
1192: max_cond = fabs( cond[0]);<br />
1193: for (i = 1; i < N; i++)<br />
1194: {<br />
1195: abs_cond = fabs( cond[i]);<br />
1196: if ( max_cond < abs_cond) max_cond = abs_cond;<br />
1197: }<br />
1198: scale_fac = 1./max_cond;<br />
1199:<br />
1200: /* do scaling */<br />
1201: for (i = 0; i < N; i++)<br />
1202: {<br />
1203: cond[i] *= scale_fac;<br />
1204: }<br />
1205: fprintf( out, "\n# scaling activated");<br />
1206: fprintf( out, ", scale_fac = %f", scale_fac);<br />
1207: break;<br />
1208: default:<br />
1246: for (i = 0; i < N * obs_dim; i++)<br />
1247: {<br />
1248: /* sum of all weights must be equal to N minus number of<br />
1249: * outliers<br />
1250: */<br />
1251: weights[i] = 1.0;<br />
1252:<br />
1253: }<br />
weights_old[i] = 1.0;<br />
1254: mean_weights = 1;<br />
1255:<br />
1256: /*<br />
1257: * pre-processing if necessary<br />
1258:<br />
1259:<br />
*/<br />
1260: /* linearisation */<br />
1261: if (type == EXPONENTIAL2_LIN)<br />
1262: {<br />
1263: /* ln(f(x|a)) = ln(a1) + (a2 * x) */<br />
1264: /* estimates for parameters */<br />
1265: for (i = 0; i < N; i++)<br />
1266: {<br />
1267: if (obs[i] linear)<br />
1283: {<br />
1284:<br />
1285:<br />
init( N, obs, cond, a, a_flag, out);<br />
1286: fprintf( out, "\n# initial Parameters\n# ");<br />
1287: /* write initial parameters to output */<br />
1288: for (i = 0; i < M; i++)<br />
1289: {<br />
1290: fprintf( out, "a%d=%.9f, ", i+1, a[i]);<br />
1291: }<br />
1292: for (i = M; i < M_MAX; i++)<br />
1293: {<br />
1294: /* zero out unnecessary parameters<br />
1295: * required for POLYNOMIAL_REG<br />
1296: */<br />
1297: a[i] = 0.;<br />
1298: }<br />
1299: /* If scaling is enabled, all initial parameters, which are set<br />
1300: * independently on the condition values, must be corrected<br />
1301: */<br />
1302: if (scale_flag)<br />
1303: {<br />
1304: switch ( type)<br />
1209: fprintf( out, "\n# scaling not supported for ’-m %d’", type); 1305: {<br />
1210: fprintf( stderr,<br />
1306: /* scaling has no positive effect for these nonlinear<br />
1211: "\n#### scaling not supported for ’-m %d’###\n", type); 1307: * model functions */<br />
1212: }<br />
1308: case NIST_RAT42:<br />
1213: }<br />
1309: a[2] /= scale_fac;<br />
1214:<br />
1310: break;<br />
1215: /* check input data */<br />
1311: case NIST_ECKERLE4:<br />
1216: if (type == COSINE_LIN || type == COSINE)<br />
1312: a[0] *= scale_fac;<br />
1217: {<br />
1313: a[1] *= scale_fac;<br />
1218: /* conditions in degree ? */<br />
1314: a[2] *= scale_fac;<br />
1219: double max_cond, abs_cond;<br />
1315: break;<br />
1220: max_cond = fabs( cond[0]);<br />
1316: case NIST_MGH10:<br />
1221: for (i = 1; i < N; i++)<br />
1317: a[1] *= scale_fac;<br />
1222: {<br />
1318: a[2] *= scale_fac;<br />
1223: abs_cond = fabs( cond[i]);<br />
1319: break;<br />
1224: if ( max_cond < abs_cond) max_cond = abs_cond; 1320: }<br />
1225: }<br />
1321: fprintf( out, "\n# scaled\n# ");<br />
1226: if ( max_cond < 2*M_PI)<br />
1322: /* write initial parameters to output */<br />
1227: {<br />
1323: for (i = 0; i < M; i++)<br />
1228: fprintf( stderr, "\n======================================"); 1324: {<br />
1229: fprintf( stderr, "\n== range of degrees is very small!! =="); 1325: fprintf( out, "a%d=%.9f, ", i+1, a[i]);<br />
1230: fprintf( stderr, "\n== Mismatch with radians?? =="); 1326: }<br />
1231: fprintf( stderr, "\n== Please check.\n =="); 1327: }<br />
1232: fprintf( stderr, "\n======================================"); 1328: }<br />
1233: }<br />
1329:<br />
1234: }<br />
1330: /*<br />
1235:<br />
1331: * prepare Jacobian matrix containing<br />
1236: /* prepare input data */<br />
1332: * first derivatives of target function<br />
1237: if (type == CIRCLE_LIN)<br />
1333: */<br />
1238: {<br />
1334: for (i = 0; i < N * obs_dim; i++)<br />
1239: for ( i = 0; i < N; i++)<br />
1335: {<br />
1240: {<br />
1336: for (j = 0; j < M; j++)<br />
1241: obs[i] = cond[2*i] * cond[2*i] + cond[2*i+1] * cond[2*i+1]; 1337: {<br />
1242: }<br />
1338: jacob[i][j] = funct_deriv( funct, i, j, M, cond, a);<br />
1243: }<br />
1339: }<br />
1244:<br />
1340: }<br />
1245: /* initialize weights */<br />
1341:
S.2 Main functions 9<br />
1342: /* debugging output, because of interleaved observations */<br />
1343: if (type == COORD_TRANSF)<br />
1344: {<br />
1345: fprintf( out, "\n#\n#== Obs ===== Jacobian =================");<br />
1346: for (i = 0; i < MIN(10,N); i++)<br />
1347: {<br />
1348: fprintf( out, "\n# %8.1f", obs[i]);<br />
1349: for (j = 0; j < M; j++)<br />
1350: {<br />
1351: fprintf( out, " %8.1f", jacob[i][j]);<br />
1352: }<br />
1353: }<br />
1354: }<br />
1355:<br />
1356: /*<br />
1357: * estimation of weights if required<br />
1358: */<br />
1359: iter_stop = 0;<br />
1360: if (weight_mode == 0)<br />
1361: {<br />
1362: iter_stop = 1; /* only one run */<br />
1363: iter_final = 1; /* only one run for ls <strong>and</strong> outlier removal */<br />
1364: }<br />
1365: else if (weight_mode == 2)<br />
1366: {<br />
1367: /* weights can be estimated beforeh<strong>and</strong> via binning */<br />
1368: est_weights2( N * obs_dim, cond, obs, weights,<br />
1369: obs_per_bin, out);<br />
1370: iter_stop = 1; /* only one run */<br />
1371: iter_final = 1; /* only one run of least squares */<br />
1372: }<br />
1373: else<br />
1374: iter_final = 0;<br />
1375:<br />
1376: /* outlier detection has not be performed yet */<br />
1377: out_detect_flag = 0;<br />
1378:<br />
1379:<br />
1380: /* ----------------------------------------------------- */<br />
1381: /* loop for weights estimation */<br />
1382: for (iter = 0;<br />
1383: (iter linear)<br />
1413: {<br />
1414: /* separate for linear <strong>and</strong> nonlinear, because funct() is<br />
1415: not defined for linear models */<br />
1416: for (i = 0; i < N * obs_dim; i++)<br />
1417: {<br />
1418: /* get calculated data points dependent on current<br />
1419: parameters */<br />
1420: datac[i] = 0.0;<br />
1421: for (j = 0; j < M; j++)<br />
1422: {<br />
1423: datac[i] += a[j] * jacob[i][j];<br />
1424: }<br />
1425: deviate[i] = obs[i] - datac[i];<br />
1426: deviates_abs[i] = fabs( deviate[i]);<br />
1427: /* weighted <strong>and</strong> squared differences */<br />
1428: deltasq[i] = deviate[i] * deviate[i];<br />
1429: if (weights[i] > 0.)<br />
1430: {<br />
1431: /* exclude outliers, i.e. weigths == 0 */<br />
1432: chisq += weights[i] * deltasq[i];<br />
1433: energy += deltasq[i];<br />
1434: mean += deviates_abs[i];<br />
1435: cnt++;<br />
1436: }<br />
1437: }<br />
1438: }<br />
1439: else /* if not linear */<br />
1440: {<br />
1441: for (i = 0; i < N * obs_dim; i++)<br />
1442: {<br />
1443: /* get calculated data points dependent on current<br />
1444: parameters */<br />
1445: datac[i] = funct( i, cond, a);<br />
1446:<br />
1447: deviate[i] = obs[i] - datac[i];<br />
1448: deviates_abs[i] = fabs( deviate[i]);<br />
1449: /* weighted <strong>and</strong> squared differences */<br />
1450: deltasq[i] = deviate[i] * deviate[i];<br />
1451: if (weights[i] > 0.)<br />
1452: {<br />
1453: /* exclude outliers in final iteration*/<br />
1454: chisq += weights[i] * deltasq[i];<br />
1455: energy += deltasq[i];<br />
1456: mean += deviates_abs[i];<br />
1457: cnt++;<br />
1458: }<br />
1459: }<br />
1460: }<br />
1461: num_outliers = N * obs_dim - cnt;<br />
1462:<br />
1463: /* estimate of k, w_i= k/sigma^2_i */<br />
1464: gfit = chisq / (double)( cnt - M); /* goodness of fit */<br />
1465: mean = mean / (double)( cnt);<br />
1466: variance = energy / (double)cnt - mean * mean;<br />
1467:<br />
1468: fprintf( out, "\n#\n# %s\n# Parameters: ", rtn);<br />
1469: for (i = 0; i < M; i++)<br />
1470: {<br />
1471: fprintf( out, "a%d=%.6f, ", i+1, a[i]);<br />
1472: }<br />
1473:<br />
1474: fprintf( out, "\n#\n# | chisq: %f", chisq);<br />
1475: fprintf( out, "\n# | mean of |deviates|: %f", mean);<br />
1476: fprintf( out, "\n# | variance of |deviates|: %f", variance);<br />
1477: fprintf( out, "\n# | goodnes of fit: %f", gfit);<br />
1478: fprintf( out, "\n# | number of outliers: %d", num_outliers);<br />
1479:<br />
1480:<br />
1481: /* estimate weights, but not in last iteration */<br />
1482: if (!iter_stop && weight_mode)<br />
1483: {<br />
1484: fprintf( out, "\n#\n# enter weight estimation");<br />
1485: /* estimation of weights based on absolute deviates */<br />
1486: if (weight_mode == 1)<br />
1487: {<br />
1488: est_weights1( N * obs_dim, deviates_abs, weights, out);<br />
1489: }<br />
1490: /* no iterative weighting in weight_mode == 2 */<br />
1491:<br />
1492: fprintf( out, "\n#\n# %s\n# i observ ", rtn);<br />
1493: fprintf( out, "calc deviates weights");<br />
1494:<br />
1495: /* get mean of weights <strong>and</strong> output current values */<br />
1496: mean_weights = 0;<br />
1497: cnt = 0;<br />
1498: for (i = 0; i < N * obs_dim; i++)<br />
1499: {<br />
1500: mean_weights += weights[i]; /* compute sum of all weights */<br />
1501: if (i < MAX_LINES) /* limits the number of output lines */<br />
1502: {<br />
1503: fprintf( out, "\n# %2d %12.5f %12.5f %12.5f %14f", i,<br />
1504: obs[i], datac[i], deviates_abs[i], weights[i]);<br />
1505: }<br />
1506: if (weights[i] > 0.0)<br />
1507: {<br />
1508: cnt++; /* count used observations */<br />
1509: }<br />
1510: }<br />
1511: /* mean of all weights > 0.; it is used later on */<br />
1512: mean_weights /= (double)cnt;<br />
1513:<br />
1514: /* compare new <strong>and</strong> old weights */<br />
1515: sum = 0;<br />
1516: for (i = 0; i < N * obs_dim; i++)<br />
1517: {<br />
1518: /* watch changes of weights */<br />
1519: sum += fabs( weights[i] - weights_old[i]);<br />
1520: weights_old[i] = weights[i]; /* remember for next<br />
1521: iteration */<br />
1522: }<br />
1523: sum /= (double)N *obs_dim; /* mean difference in<br />
1524: weights */<br />
1525: /* criterion of convergence */<br />
1526: if (sum < 0.0001)<br />
1527: {<br />
1528: if (!iter_stop)<br />
1529: {<br />
1530: iter_final = 1; /* go to last iteration */<br />
1531: }<br />
1532: iter_stop = 1; /* last iteration has been performed */<br />
1533:
10 S The Source Code<br />
1534: fprintf( out, "\n#\n# convergence of weights");<br />
1535: } /* if (sum < 0.0001)*/<br />
1536:<br />
1537: if (iter == iter_wmax && !iter_stop)<br />
1538: {<br />
1539: fprintf( out,<br />
1540: "\n#\n# maximum number of iterations reached");<br />
1541: fprintf( out, "\n# no convergence of weights");<br />
1542: iter_final = 1; /* go to last iteration */<br />
1543: } /* if (iter == iter_wmax && !iter_stop)*/<br />
1544: } /* if (!iter_stop && weight_mode) */<br />
1545:<br />
1546: #ifdef OUTPUT_DEVIATES<br />
1547: /* write deviates in separate file */<br />
1548: if (iter_stop == 1)<br />
1549: {<br />
1550: char dev_name[500];<br />
1551: int i, len;<br />
1552: FILE *out_dev;<br />
1553:<br />
1554: len = strlen(outname);<br />
1555: /* copy filename w/o extension */<br />
1556: for (i = 0; i 0)<br />
1627: {<br />
1628: iter_final = 1;<br />
1629: if (forget_flag == 1)<br />
1630: {<br />
1631: fprintf( out, "\n#forget weights");<br />
1632: /* set all weights to 1. */<br />
1633: for (i = 0; i < N * obs_dim; i++)<br />
1634: {<br />
1635: if (weights[i] > 0.0)<br />
1636: weights[i] = (float)1.0;<br />
1637: }<br />
1638: mean_weights = 1.0;<br />
1639: }<br />
1640: }<br />
1641: } /* if out_mode */<br />
1642: } /* for iter */<br />
1643: /* ----------------------------------------------------- */<br />
1644:<br />
1645: /*<br />
1646: * evaluation of results<br />
1647: */<br />
1648:<br />
1649: /*<br />
1650: * since the weights are already normalised to their<br />
1651: * mean value (w = k/sigma^2), gfit is also equal to<br />
1652: * the variance of observations<br />
1653: */<br />
1654:<br />
1655: /* uncertainty in observations */<br />
1656: uncertainty = sqrt( gfit/ mean_weights);<br />
1657:<br />
1658: fprintf( out, "\n#\n# evaluation of results");<br />
1659: fprintf( out, "\n# number of outliers: %d", num_outliers);<br />
1660: fprintf( out, "\n# parameters:");<br />
1661: for (j = 0; j < M; j++)<br />
1662: {<br />
1663: fprintf( out, " a%d=%f", j+1, a[j]);<br />
1664: }<br />
1665: fprintf( out, "\n# chi square.................: %.12G", chisq);<br />
1666: fprintf( out, "\n# goodness of fit............: %.12G", gfit);<br />
1667: fprintf( out, "\n# uncertainty in observations: %.12G",<br />
1668: uncertainty);<br />
1669: fprintf( out, "\n#\n# (co)variance of parameters:");<br />
1670: {<br />
1671: int flag = 0;<br />
1672: for (i = 0; i < M; i++)<br />
1673: {<br />
1674: fprintf( out, "\n#");<br />
1675: for (j = 0; j < M; j++)<br />
1676: {<br />
1677: fprintf( out, " %15.9G", covar[i][j]);<br />
1678: if ( (i == j) && (covar[i][j] < 0.) ) flag = 1;<br />
1679: }<br />
1680: }<br />
1681: if (flag)<br />
1682: {<br />
1683: printf( "\n# negative parameter variance");<br />
1684: printf( "\n# probably ill-conditioned problem");<br />
1685: if (!ls_flag->svd)<br />
1686: {<br />
1687: printf( "\n# solution is probably wrong");<br />
1688: printf( "\n# disable option ’-s’");<br />
1689: fprintf( out, "\n#### solution is probably wrong #");<br />
1690: fprintf( out, "\n#### disable option ’-s’");<br />
1691: }<br />
1692: fprintf( out, "\n#### negative parameter variance #");<br />
1693: fprintf( out, "\n#### probably ill-conditioned problem #");<br />
1694: }<br />
1695: }<br />
1696: fprintf( out, "\n\n# (co)variance of parameters multiplied");<br />
1697: fprintf( out, " with goodness of fit");<br />
1698: for (i = 0; i < M; i++)<br />
1699: {<br />
1700: fprintf( out, "\n#");<br />
1701: for (j = 0; j < M; j++)<br />
1702: {<br />
1703: covar[i][j] *= gfit;<br />
1704: fprintf( out, " %12.6G", covar[i][j]);<br />
1705: }<br />
1706: }<br />
1707: fprintf( out, "\n\n# resulting uncertainty of parameters \n#");<br />
1708: for (j = 0; j < M; j++)<br />
1709: {<br />
1710: if (covar[j][j] >= 0)<br />
1711: fprintf( out, " %15.9G", sqrt( covar[j][j] ));<br />
1712: else<br />
1713: fprintf( out, " ?? ");<br />
1714: }<br />
1715:<br />
1716:<br />
1717: /*-------------------------------------------------------<br />
1718: * post-processing<br />
1719: */<br />
1720:<br />
1721: /* correction of parameters, before determination of relative<br />
1722: * uncertainty, because of phase shift<br />
1723: */<br />
1724: if (type == COSINE) /* nonlinear cosine model */<br />
1725: {
S.2 Main functions 11<br />
1726: if (a[1] < 0 ) /* avoid negative amplitude/radius */ 1822: fprintf( stderr,<br />
1727: {<br />
1823: "\n#### scaling not supported for ’-m %d’###\n", type);<br />
1728: a[1] = -a[1];<br />
1824: }<br />
1729: a[2] = a[2] - 180; /* phase shift of 180 degrees */ 1825: /* unscale conditions for output */<br />
1730: }<br />
1826: for (i = 0; i < N*cond_dim; i++)<br />
1731: fprintf( out, "\n#\n# corrected Parameters\n# "); 1827: {<br />
1732: for (j = 0; j < M; j++)<br />
1828: cond[i] /= scale_fac;<br />
1733: {<br />
1829: }<br />
1734: fprintf( out, "a%d=%16.12G, ", j + 1, a[j]); 1830: }<br />
1735: }<br />
1831:<br />
1736: fprintf( out, "\n#");<br />
1832: fprintf( out, "\n#\n# Final_Parameters ");<br />
1737: }<br />
1833: for (i = 0; i < M; i++)<br />
1738: else if (type == TRIGONOMETRIC2)<br />
1834: {<br />
1739: {<br />
1835: fprintf( out, "a%d= %.12G ", i+1, a[i]);<br />
1740: if (a[3] > 2*M_PI) a[3] -= 2*M_PI;<br />
1836: }<br />
1741: else if (a[3] < 0) a[3] += 2*M_PI;<br />
1837: if (type == POLYNOMIAL)<br />
1742: if (a[5] > 2*M_PI) a[6] -= 2*M_PI;<br />
1838: {<br />
1743: else if (a[5] < 0) a[6] += 2*M_PI;<br />
1839: fprintf( out, "\n# f%d(x) = %.14G", M, a[0]);<br />
1744: fprintf( out, "\n#\n# corrected Parameters\n# "); 1840: if (M > 1)<br />
1745: for (j = 0; j < M; j++)<br />
1841: {<br />
1746: {<br />
1842: fprintf( out, " + %.14G*x", a[1]);<br />
1747: fprintf( out, "a%d=%16.12G, ", j + 1, a[j]); 1843: }<br />
1748: }<br />
1844: for ( j = 2; j < M; j++)<br />
1749: fprintf( out, "\n#");<br />
1845: {<br />
1750: }<br />
1846: fprintf( out, " + %.14G * x**%d", a[j], j);<br />
1751:<br />
1847: }<br />
1752: /* check the uncertainty in parameters */<br />
1848: }<br />
1753: {<br />
1849:<br />
1754: int flag = 0;<br />
1850: /* map parameters to original model function */<br />
1755: double val;<br />
1851: if (type == COSINE_LIN)<br />
1756: fprintf( out, "\n#");<br />
1852: {<br />
1757:<br />
1853: double r0, phi0;<br />
1758: for (j = 0; j < M; j++)<br />
1854:<br />
1759: {<br />
1855: /* f(x|b) = b1 + r0 * cos( x - phi0) * f(x|a) = a1 + a2 *<br />
1760: if (covar[j][j] >= 0)<br />
1856: cos( x) + a3 * sin( x) */<br />
1761: {<br />
1857: r0 = sqrt( a[1] * a[1] + a[2] * a[2]); /* radius a2 */<br />
1762: val = sqrt( covar[j][j]) * 100. / fabs(a[j]); 1858: phi0 = 0;<br />
1763: fprintf( out, "%15.5G%%", val);<br />
1859: if (r0 > 0.)<br />
1764: if (val > 10) flag++;<br />
1860: {<br />
1765: }<br />
1861: double pc1, pc2, ps1, ps2;<br />
1766: else<br />
1862: double d11, d12, d21, d22;<br />
1767: {<br />
1863:<br />
1768: fprintf( out, " ?? %%");<br />
1864: /* solve ambiguity of angles */<br />
1769: }<br />
1865: pc1 = acos( a[1] / r0); /* 1st solution */<br />
1770: }<br />
1866: pc2 = -pc1; /* 2nd solution */<br />
1771:<br />
1867: ps1 = asin( a[2] / r0); /* 3rd solution */<br />
1772: if (flag)<br />
1868: if (ps1 < 0) /* 4th solution */<br />
1773: {<br />
1869: ps2 = -M_PI - ps1;<br />
1774: fprintf( out,<br />
1870: else<br />
1775: "\n# %d parameter(s) have relative high uncertainty !", 1871: ps2 = M_PI - ps1;<br />
1776: flag);<br />
1872:<br />
1777: fprintf( stdout,<br />
1873: d11 = fabs( pc1 - ps1); /* two of four must be equal */<br />
1778: "\n# %d parameter(s) have relative high uncertainty !", 1874: d12 = fabs( pc1 - ps2); /* take differences */<br />
1779: flag);<br />
1875: d21 = fabs( pc2 - ps1);<br />
1780: fprintf( stdout, "\n# Please inspect file %s !", outname); 1876: d22 = fabs( pc2 - ps2);<br />
1781: }<br />
1877: /* look for smallest difference */<br />
1782: }<br />
1878: if (d11 < d12 && d11 < d21 && d11 < d22)<br />
1783:<br />
1879: {<br />
1784: if (num_outliers)<br />
1880: phi0 = 0.5 * (pc1 + ps1);<br />
1785: {<br />
1881: }<br />
1786: fprintf( stdout, "\n# detection of %d outliers!", num_outliers); 1882: if (d12 < d11 && d12 < d21 && d12 < d22)<br />
1787: }<br />
1883: {<br />
1788:<br />
1884: phi0 = 0.5 * (pc1 + ps2);<br />
1789: /* unscale the parameters */<br />
1885: }<br />
1790: if (scale_flag)<br />
1886: if (d21 < d11 && d21 < d12 && d21 < d22)<br />
1791: {<br />
1887: {<br />
1792: /* correction of parameters */<br />
1888: phi0 = 0.5 * (pc2 + ps1);<br />
1793: fprintf( out, "\n# undo the scaling");<br />
1889: }<br />
1794: switch (type)<br />
1890: if (d22 < d11 && d22 < d12 && d22 < d21)<br />
1795: {<br />
1891: {<br />
1796: case LINEAR:<br />
1892: phi0 = 0.5 * (pc2 + ps2);<br />
1797: for ( j = 1; j < M; j++)<br />
1893: }<br />
1798: {<br />
1894: a[1] = r0;<br />
1799: a[j] *= scale_fac;<br />
1895: a[2] = phi0 * 180 / M_PI;<br />
1800: }<br />
1896: }<br />
1801: break;<br />
1897: fprintf( out, "\n#\n# corrected Parameters ");<br />
1802: case POLYNOMIAL:<br />
1898: fprintf( out, "according to f(x)=b1+b2*cos(x-b3)\n# ");<br />
1803: for ( j = 1; j < M; j++)<br />
1899: for (j = 0; j < M; j++)<br />
1804: {<br />
1900: {<br />
1805: a[j] *= pow( scale_fac, (double)j);<br />
1901: fprintf( out, "b%d=%.9f, ", j + 1, a[j]);<br />
1806: }<br />
1902: }<br />
1807: break;<br />
1903: fprintf( out, "\n#");<br />
1808: case NIST_RAT42:<br />
1904: }<br />
1809: a[2] *= scale_fac;<br />
1905: else if (type == EXPONENTIAL2_LIN)<br />
1810: break;<br />
1906: {<br />
1811: case NIST_ECKERLE4:<br />
1907: /* convert observations back */<br />
1812: a[0] /= scale_fac;<br />
1908: for (i = 0; i < N; i++)<br />
1813: a[1] /= scale_fac;<br />
1909: {<br />
1814: a[2] /= scale_fac;<br />
1910: obs[i] = exp( obs[i]);<br />
1815: break;<br />
1911: }<br />
1816: case NIST_MGH10:<br />
1912: a[0] = exp( a[0]);<br />
1817: a[1] /= scale_fac;<br />
1913:<br />
1818: a[2] /= scale_fac;<br />
1914: fprintf( out, "\n#\n# corrected Parameters\n# ");<br />
1819: break;<br />
1915: for (j = 0; j < M; j++)<br />
1820: default:<br />
1916: {<br />
1821: fprintf( out, "\n# scaling not supported for ’-m %d’", type); 1917: fprintf( out, "a%d=%.9f, ", j + 1, a[j]);
12 S The Source Code<br />
1918: }<br />
1919: fprintf( out, "\n#\n# uncertainties of corrected Parameters ");<br />
1920: fprintf( out, "are not available yet\n# ");<br />
1921:<br />
1922: for (i = 0; i < N; i++)<br />
1923: {<br />
1924: /* get calculated data points dependent on corrected<br />
1925: parameters */<br />
1926: datac[i] = fexpon2( i, cond, a);<br />
1927: }<br />
1928: }<br />
1929: else if (type == COORD_TRANSF)<br />
1930: {<br />
1931: /* print angle in degrees */<br />
1932:<br />
1933: fprintf( out, " (%.4f degrees)", a[2] * 180. / M_PI);<br />
1934: }<br />
1935: else if (type == CIRCLE || type == CIRCLE_TLS)<br />
1936: {<br />
1937: /* evaluate result in terms of mean squared distance<br />
1938: * of points to circle<br />
1939: */<br />
1940: double eval = 0, d, delta;<br />
1941:<br />
1942: cnt = 0;<br />
1943: for ( i = 0; i < N; i++)<br />
1944: {<br />
1945: if (weights[i] > 0.)<br />
1946: {<br />
1947: d = euclid_dist( (cond[2*i]-a[0]), (cond[2*i+1]-a[1]));<br />
1948: /* orthogonal distance to curve of circle */<br />
1949: delta = d - a[2];<br />
1950: eval += delta * delta; /* sum up squared distances */<br />
1951: cnt++;<br />
1952: }<br />
1953: }<br />
1954: fprintf( out, "\n# mean squared distance to circle: %.6f\n#",<br />
1955: eval/cnt);<br />
1956: }<br />
1957: else if (type == CIRCLE_LIN)<br />
1958: {<br />
1959: double a1, a2, a3;<br />
1960: double eval = 0, d, delta;<br />
1961: /* convert parameters back */<br />
1962: a1 = 0.5 * a[0];<br />
1963: a2 = 0.5 * a[1];<br />
1964: a3 = sqrt( a1*a1 + a2*a2 - a[2]);<br />
1965:<br />
1966: fprintf( out, "\n#\n# corrected Parameters\n# ");<br />
1967: fprintf( out, "a1=%.9f, ", a1);<br />
1968: fprintf( out, "a2=%.9f, ", a2);<br />
1969: fprintf( out, "a3=%.9f", a3);<br />
1970: fprintf( out, "\n#");<br />
1971:<br />
1972: /* evaluate result in terms of mean squared distance<br />
1973: * of points to circle<br />
1974: */<br />
1975: cnt = 0;<br />
1976: for ( i = 0; i < N; i++)<br />
1977: {<br />
1978: if (weights[i] > 0.)<br />
1979: {<br />
1980: d = euclid_dist( (cond[2*i]-a1), (cond[2*i+1]-a2));<br />
1981: /* orthogonal distance to curve of circle */<br />
1982: delta = d - a3;<br />
1983: eval += delta * delta; /* sum up squared distances */<br />
1984: cnt++;<br />
1985: }<br />
1986: }<br />
1987: fprintf( out, "\n# mean squared distance to circle: %.6f\n#",<br />
1988: eval/cnt);<br />
1989: }<br />
1990:<br />
1991: /* ----------------------------------------- */<br />
1992: fprintf( out, "\n# ");<br />
1993: for (j = 0; j < cond_dim; j++)<br />
1994: {<br />
1995: fprintf( out, "cond%d ", j + 1);<br />
1996: }<br />
1997: fprintf( out, "observed fitted weight uncertainty ");<br />
1998: fprintf( out, "glob.uncertainty difference");<br />
1999:<br />
2000: /*<br />
2001: * estimated weight should be w = 1/sigma^2<br />
2002: * thus estimated uncertainty is sigma = 1/ sqrt(weight)<br />
2003: * make nice output<br />
2004: */<br />
2005: if (type == COORD_TRANSF)<br />
2006: {<br />
2007: fprintf( out, " observed2 fitted2 weight2 ");<br />
2008: fprintf( out, "uncertainty2 glob.uncertainty2 difference2");<br />
2009: }<br />
2010:<br />
2011: /*<br />
2012: * output of final results<br />
2013: */<br />
2014: for (i = 0; i < (int)N * obs_dim; i += obs_dim)<br />
2015: {<br />
2016: double uncert;<br />
2017:<br />
2018: fprintf( out, "\n");<br />
2019: for (j = 0; j < cond_dim; j++)<br />
2020: {<br />
2021: fprintf( out, "%12.6f ",<br />
2022: cond[cond_dim * (i / obs_dim) + j]);<br />
2023: }<br />
2024: /* put both fitting results for fixed conditions in same row<br />
2025: */<br />
2026: for (o = 0; o < (int)obs_dim; o++)<br />
2027: {<br />
2028: int k;<br />
2029: k = i + o;<br />
2030: if (weights[k] > 0)<br />
2031: uncert = 1. / sqrt( weights[k]);<br />
2032: else<br />
2033: uncert = 9999.;<br />
2034: fprintf( out, "%12.6f ", obs[k]);<br />
2035: fprintf( out, "%12.6f %11.6f %12.6f %.6f",<br />
2036: datac[k], weights[k], uncert, uncertainty);<br />
2037: fprintf( out, "%+12.6f ", (obs[k] - datac[k]));<br />
2038: }<br />
2039: /* make a empty line to enforce plotting a mesh */<br />
2040: if (type == LINEAR && M == 3 &&<br />
2041: ( cond[cond_dim * i] != cond[cond_dim * (i + 1)]))<br />
2042: {<br />
2043: /* plane approximation */<br />
2044: fprintf( out, "\n");<br />
2045: }<br />
2046: if (type == QUAD_SURFACE &&<br />
2047: ( cond[cond_dim * i+1] != cond[cond_dim * (i + 1)+1]))<br />
2048: {<br />
2049: /* surface approximation */<br />
2050: fprintf( out, "\n");<br />
2051: }<br />
2052: }<br />
2053: fprintf( out, "\n");<br />
2054:<br />
2055: endfunc:<br />
2056: printf( "\n");<br />
2057: fflush( stdout);<br />
2058:<br />
2059: free_vector( &weights);<br />
2060: free_vector( &weights_old);<br />
2061: free_vector( &obs);<br />
2062: free_vector( &datac);<br />
2063: free_vector( &cond);<br />
2064: free_vector( &deviate);<br />
2065: free_vector( &deviates_abs);<br />
2066: free_vector( &deltasq);<br />
2067: free_matrix( &jacob);<br />
2068: free_matrix( &covar);<br />
2069:<br />
2070: if (argc > 2)<br />
2071: {<br />
2072: if (out != NULL)<br />
2073: fclose( out);<br />
2074: }<br />
2075: if (in != NULL)<br />
2076: fclose( in);<br />
2077:<br />
2078: if (err)<br />
2079: {<br />
2080: fprintf( stderr, "\n failed.\n");<br />
2081: return err;<br />
2082: }<br />
2083: else<br />
2084: {<br />
2085: fprintf( stderr, "\n ready.\n");<br />
2086: return 0;<br />
2087: }<br />
2088: }<br />
2089:<br />
2090: /*---------------------------------------------------------------<br />
2091: * is_data_line()<br />
2092: *--------------------------------------------------------------*/<br />
2093: int<br />
2094: is_data_line( char *line, int N)<br />
2095: {<br />
2096: int i;<br />
2097:<br />
2098: /* scan leading white spaces */<br />
2099: for (i = 0; i < N; i++)<br />
2100: {<br />
2101: if (line[i] != ’ ’ /* space */<br />
2102: && line[i] != ’\t’ /* tab */<br />
2103: )<br />
2104: break;<br />
2105: }<br />
2106: /* check next character */<br />
2107: if (line[i] == ’#’) /* comment */<br />
2108: {<br />
2109: return 0;
S.2 Main functions 13<br />
2110: }<br />
2111: if (line[i] == ’\n’) /* newline */<br />
2112: {<br />
2113: return 0;<br />
2114: }<br />
2115: if (line[i] == ’\r’) /* carrige return (Windows) */<br />
2116: {<br />
2117: return 0;<br />
2118: }<br />
2119:<br />
2120: return 1; /* is data line */<br />
2121: }<br />
2122:<br />
2123: /*---------------------------------------------------------------<br />
2124: * get_nth_field()<br />
2125: * scans a string up to the desired column (field)<br />
2126: *--------------------------------------------------------------*/<br />
2127: char *<br />
2128: get_nth_field( char *line, int n)<br />
2129: {<br />
2130: char *ptr = NULL;<br />
2131: int ch, i = 0, loop_flag, cnt, field_flag;<br />
2132:<br />
2133: if (line == NULL)<br />
2134: return ptr;<br />
2135:<br />
2136: loop_flag = 1;<br />
2137: field_flag = 0;<br />
2138: cnt = 0;<br />
2139: do<br />
2140: {<br />
2141: ch = line[i];<br />
2142: if (ch == ’\0’)<br />
2143: {<br />
2144: loop_flag = 0;<br />
2145: break;<br />
2146: }<br />
2147: if (!field_flag)<br />
2148: {<br />
2149: if (ch != ’ ’ && ch != ’\t’ && ch != ’\r’ && ch != ’\n’)<br />
2150: {<br />
2151: field_flag = 1;<br />
2152: cnt++;<br />
2153: if (cnt == n)<br />
2154: {<br />
2155: /* desired field is found */<br />
2156: ptr = &( line[i]);<br />
2157: loop_flag = 0;<br />
2158: }<br />
2159: }<br />
2160: }<br />
2161: else<br />
2162: {<br />
2163: /* search next white space */<br />
2164: if (ch == ’ ’ || ch == ’\t’ || ch == ’\r’ || ch == ’\n’)<br />
2165: {<br />
2166: field_flag = 0;<br />
2167: }<br />
2168: }<br />
2169: i++;<br />
2170: } while (loop_flag);<br />
2171: return ptr;<br />
2172: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: prototypes.h<br />
3: * Function....: proto typing for different functions<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 27.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef PROTO_H<br />
15: #define PROTO_H<br />
16:<br />
17:<br />
18: typedef struct {<br />
19: int linear; /* linear model */<br />
20: int svd; /* special computation for linear models */<br />
21: int LM; /* 0 .. Gaus-Newton, 1 .. Levenberg-Marquardt */<br />
22: int chisq_target; /* indicates that ’chisq_target’ was set */<br />
23: int trueH; /* use true Hessian matrix */<br />
24: } LS_FLAG;<br />
25:<br />
26: /* least squares routine */<br />
27: int<br />
28: ls( double (*funct) (int,double*,double*),<br />
29: double (*funct_deriv) (double(*)(int,double*,double*),<br />
30: int,int,int,double*,double*),<br />
31: double (*funct_deriv2) (double(*)(int,double*,double*),<br />
32: int,int,int,int,double*,double*),<br />
33: int (*init)(int, double*,double*,double*,<br />
34: unsigned char*,FILE*),<br />
35: int N, int M, double *obs, double *cond, double **jacob,<br />
36: double *weights, double *a, unsigned char* a_flag,<br />
37: int algo_mode, LS_FLAG *ls_flag,<br />
38: double chisq_target, double **covar, FILE *out);<br />
39:<br />
40: int svd_inversion( int N, double **normal, double **normal_i,<br />
41: FILE *out);<br />
42: int<br />
43: solve_lin( int N, int M, double *obs, double *weights,<br />
44: double **jacob, double **covar, double *a,<br />
45: FILE *out);<br />
46:<br />
47: /* parsing of comm<strong>and</strong>-line parameters */<br />
48: char* get_nth_field( char *line, int n);<br />
49: int is_data_line( char *line, int N);<br />
50:<br />
51: /* matrix inversion */<br />
52: int singvaldec( double **a, int N, int M, double w[], double **v);<br />
53: void backsub_LU( double **lu, int N, int *indx, double back[]);<br />
54: int decomp_LU( double **normal, int M, int *indx, int *s);<br />
55: void heap_sort_d_(unsigned long N, double ra[], int idx[]);<br />
56: void heap_sort_d(unsigned long N, double ra[]);<br />
57:<br />
58: /* estimation of weights */<br />
59: void est_weights1( int N, double *deltasq,<br />
60: double *weights, FILE *out);<br />
61: void est_weights2( int N, double *cond, double *obs,<br />
62: double *weights, int obs_per_bin, FILE *out);<br />
63: int outlier_detection1( int N, double sigma_y, double *deltasq,<br />
64: double *weights, double nu, FILE *out);<br />
65: int outlier_detection2( int N, double *deltasq,<br />
66: double *weights, FILE *out);<br />
67:<br />
68: void<br />
69: ls_straightline(<br />
70: int N, /* number of entries */<br />
71: double cond[], /* vector of conditions */<br />
72: double obs[], /* vector of observations */<br />
73: double a[] /* container for parameters to be estimated */<br />
74: );<br />
75:<br />
76: #endif<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: ls.c<br />
3: * Function....: least squares with alternative matrix inversion<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 05.02.2008, 28.09.2009, 25.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include "errmsg.h"<br />
19: #include "matrix_utils.h"<br />
20: #include "defines.h"<br />
21: #include "macros.h"<br />
22: #include "prototypes.h"<br />
23: #include "functions.h"<br />
24: #ifndef WIN32<br />
25: #include <br />
26: #else<br />
27: #include <br />
28: #define r<strong>and</strong>om r<strong>and</strong><br />
29: #endif<br />
30:<br />
31: long ITERAT_MAX;<br />
32: double NU_FAC;<br />
33: //#define QDEBUG<br />
34:<br />
35: /*---------------------------------------------------------------<br />
36: * ls()<br />
37: *<br />
38: *--------------------------------------------------------------*/<br />
39: int<br />
40: ls( double (*funct) (int,double*,double*),<br />
41: double (*funct_deriv) (double(*)(int,double*,double*),<br />
42: int,int,int,double*,double*),<br />
43: double (*funct_deriv2) (double(*)(int,double*,double*),<br />
44: int,int,int,int,double*,double*),<br />
45: int (*init)(int, double*,double*,double*,<br />
46: unsigned char*,FILE*),<br />
47: int N, int M, double *obs, double *cond, double **jacob,
14 S The Source Code<br />
48: double *weights, double *a, unsigned char* a_flag,<br />
49: int algo_mode, LS_FLAG *ls_flag,<br />
50: double chisq_target, double **covar, FILE *out)<br />
51: {<br />
52: char *rtn = "ls";<br />
53: int err = 0, i, j, k, n;<br />
54: int Nfree;<br />
55: int stop_flag; /* supports convergence criterion */<br />
56: int iter_cnt; /* counter for nonlinear iterations */<br />
57: int iter_max=ITERAT_MAX; /* maximum number of iterations */<br />
58: double **cofac = NULL; /* cofactor matrix for matrix<br />
59: inversion */<br />
60: double **normal = NULL; /* N = J^(T) * W * J */<br />
61: double **normal_i = NULL; /* inverse of N */<br />
62: double **tmpmat = NULL; /* temporary matrix */<br />
63: double *tmpvec = NULL; /* J^(T) * W * r */<br />
64: double *datac = NULL; /* calculated values based on parameters<br />
65: */<br />
66: double *da = NULL; /* parameter update deltasq a */<br />
67: double *deltasq = NULL; /* = w * [obs - f(x|a) ] ^2 */<br />
68: double chisq, det, tmp, residual, deriv_2nd, variance;<br />
69: double min_chisq=0, *min_a=NULL; /* remember best result */<br />
70: double mu_fac = 0; /* factor for Levenberg-Marquardt */<br />
71: double max_diag; /* maximum value of Njj */<br />
72: double diag[M_MAX]; /* vector of diagonal of Normal matrix */<br />
73:<br />
74: fprintf( out,<br />
75: "\n# -- %s - start ------------------------------", rtn);<br />
76:<br />
77: /*<br />
78: * allocate memory<br />
79: */<br />
80:<br />
81: /* normal matrix N = J^(T) * W * J, its inverse */<br />
82: normal = matrix( M, M);<br />
83: normal_i = matrix( M, M);<br />
84:<br />
85: cofac = matrix( M, M); /* cofactor matrix */<br />
86: tmpvec = vector( M); /* container for J^(T) * W * G */<br />
87: datac = vector( N); /* calculated data using f(x|a) */<br />
88: deltasq = vector( N); /* remaining differences */<br />
89: da = vector( M); /* model parameter update */<br />
90: min_a = vector( M); /* remember best parameter set */<br />
91:<br />
92: iter_cnt = 1;<br />
93: if (!ls_flag->linear)<br />
94: {<br />
95: /* initialise minimum (best) values */<br />
96: for (j = 0; j < M; j++)<br />
97: {<br />
98: min_a[j] = a[j];<br />
99: }<br />
100: min_chisq = -1.;<br />
101: }<br />
102: else<br />
103: {<br />
104: /* nothing to iterate for linear models */<br />
105: }<br />
106:<br />
107: if (ls_flag->svd && ls_flag->linear)<br />
108: {<br />
109: /* This function exploits the SVD for solving linear problems.<br />
110: * Inverting of the normal matrix is not required, which<br />
111: * sometimes runs into problems when inverting the normal matrix<br />
112: * of difficult model functions as, for example, polynomials of<br />
113: * high order. It returns the estimated parameters in a <strong>and</strong> the<br />
114: * covariance matrix covar<br />
115: */<br />
116: err = solve_lin( N, M, obs, weights, jacob, covar, a, out);<br />
117: if (err)<br />
118: {<br />
119: fprintf( stderr,<br />
120: "\n\n### Unable to solve this linear system!");<br />
121: fprintf( stderr, "\n Abort!\n");<br />
122: goto endfunc;<br />
123: }<br />
124: }<br />
125: else<br />
126: {<br />
127: mu_fac = 0.0001; /* initial factor for Levenberg-Marquard */<br />
128:<br />
129: /* iteration if nonlinear */<br />
130: do<br />
131: {<br />
132: /* feedback on console */<br />
133: printf( "\r\t\t %4d", iter_cnt);<br />
134:<br />
135: #ifdef QDEBUG<br />
136: fprintf( out,<br />
137: "\n#\n#== Obs == Weight == Jacobian =================");<br />
138: for (i = 0; i < N; i++)<br />
139: {<br />
140: fprintf( out, "\n# %8.1f %8.6f", obs[i], weights[i]);<br />
141: for (j = 0; j < M; j++)<br />
142: {<br />
143: fprintf( out, " %8.5f", jacob[i][j]);<br />
144: }<br />
145: }<br />
146: #endif<br />
147:<br />
148: /*<br />
149: * calculate normal matrix N<br />
150: * N = J^(T) * W * J<br />
151: */<br />
152: max_diag = 0;<br />
153: for (j = 0; j < M; j++)<br />
154: {<br />
155: for (i = 0; i < M; i++)<br />
156: {<br />
157: normal[j][i] = 0.;<br />
158: for (n = 0; n < N; n++)<br />
159: {<br />
160: normal[j][i] += jacob[n][j] * jacob[n][i] * weights[n];<br />
161: }<br />
162:<br />
163: }<br />
164: /* only for nonlinear models of importance:<br />
165: * get maximum value on main diagonal<br />
166: */<br />
167: diag[j] = normal[j][j];<br />
168: if (max_diag < normal[j][j])<br />
169: {<br />
170: max_diag = normal[j][j];<br />
171: }<br />
172: }<br />
173: #ifdef QDEBUG<br />
174: fprintf( out, "\n#\n#== normal matrix =================");<br />
175: for (i = 0; i < M; i++)<br />
176: {<br />
177: fprintf( out, "\n# ");<br />
178: for (j = 0; j < M; j++)<br />
179: {<br />
180: fprintf( out, " %12.2f", normal[i][j]);<br />
181: }<br />
182: }<br />
183: fflush( out);<br />
184: #endif<br />
185:<br />
186: /* K = J^(T) * W * r */<br />
187: if (ls_flag->linear)<br />
188: {<br />
189: /* tmpvec = J^(T) * W * y */<br />
190: for (j = 0; j < M; j++)<br />
191: {<br />
192: tmpvec[j] = 0.;<br />
193: for (n = 0; n < N; n++)<br />
194: {<br />
195: tmpvec[j] += jacob[n][j] * obs[n] * weights[n];<br />
196: }<br />
197: }<br />
198: }<br />
199: else /* nonlinear */<br />
200: {<br />
201: /* tmpvec = J^(T) * W * r */<br />
202: /* r contains residuals */<br />
203: for (j = 0; j < M; j++)<br />
204: {<br />
205: tmpvec[j] = 0.;<br />
206: for (i = 0; i < N; i++)<br />
207: {<br />
208: residual = obs[i] - funct( i, cond, a);<br />
209: tmpvec[j] += jacob[i][j] * residual * weights[i];<br />
210: }<br />
211: }<br />
212: if (errno)<br />
213: {<br />
214: perror( "\n### ");<br />
215: fprintf( stderr, " errno = %d", errno);<br />
216: fprintf( out, "\n Error in computation (%d), ", errno);<br />
217: fprintf( out, "see st<strong>and</strong>ard output (console)\n");<br />
218: err = errno;<br />
219: goto endfunc;<br />
220: }<br />
221:<br />
222: /* add Levenberg-Marquardt term on main diagonal */<br />
223: if (ls_flag->LM)<br />
224: {<br />
225: for (j = 0; j < M; j++)<br />
226: {<br />
227: normal[j][j] += mu_fac * max_diag;<br />
228: }<br />
229: }<br />
230: /* add Q term ==> true Hessian matrix */<br />
231: if (ls_flag->trueH)<br />
232: {<br />
233: for (i = 0; i < N; i++)<br />
234: {<br />
235: residual = obs[i] - funct( i, cond, a);<br />
236: for (j = 0; j < M; j++)<br />
237: {<br />
238: for (k = 0; k < M; k++)<br />
239: {
S.2 Main functions 15<br />
240: deriv_2nd = funct_deriv2( funct, j, k, M, i,cond,a);<br />
241: normal[j][k] += deriv_2nd * residual;<br />
242: }<br />
243: }<br />
244: }<br />
245: }<br />
246: }<br />
247:<br />
248: /*<br />
249: * inversion of normal matrix<br />
250: * (cofactor method, LU decomposition, or SVD)<br />
251: *<br />
252: */<br />
253: if (algo_mode == 0)<br />
254: {<br />
255: switch (M)<br />
256: {<br />
257: case 1:<br />
258: /* y = a1 */<br />
259: /* df/da1 = 1 */<br />
260: det = normal[0][0]; /* determinant */<br />
261: if (det != 0)<br />
262: {<br />
263: cofac[0][0] = 1.;<br />
264: }<br />
265: else<br />
266: {<br />
267: err = errmsg( ERR_IS_ZERO, rtn, "determinant", 0);<br />
268: goto endfunc;<br />
269: }<br />
270: break;<br />
271:<br />
272: case 2:<br />
273: det = determinant_2x2( normal); /* determinant */<br />
274: coFactor_2x2( normal, cofac); /* coFactor matrix */<br />
275: break;<br />
276:<br />
277: case 3:<br />
278: det = determinant_3x3( normal); /* determinant */<br />
279: coFactor_3x3( normal, cofac); /* coFactor matrix */<br />
280: break;<br />
281: case 4: /* need 4 Parameters */<br />
282: det = inverse_4x4( normal, cofac);<br />
283: break;<br />
284: case 5: /* need 5 Parameters */<br />
285: det = inverse_5x5( normal, cofac);<br />
286: break;<br />
287:<br />
288: default:<br />
289: fprintf( stderr, "\n too much parameters (%d) ", M);<br />
290: fprintf( stderr, "for st<strong>and</strong>ard matrix inversion");<br />
291: err = errmsg( ERR_CALL, rtn,<br />
292: "check comm<strong>and</strong>-line parameters ", 0);<br />
293: goto endfunc;<br />
294: } /* switch */<br />
295: if (fabs( det) > 1.0e-20)<br />
296: {<br />
297: for (i = 0; i < M; i++)<br />
298: {<br />
299: for (j = 0; j < M; j++)<br />
300: {<br />
301: normal_i[i][j] = cofac[i][j] / det;<br />
302: }<br />
303: }<br />
304: }<br />
305: else<br />
306: {<br />
307: err = errmsg( ERR_IS_ZERO, rtn, "determinant", 0);<br />
308: fprintf( stderr,<br />
309: "\n Please, consider to use option ’-a 1’ ! ");<br />
310: fprintf( out,<br />
311: "\n#\n### determinant is zero ! ");<br />
312: fprintf( out,<br />
313: "\n### Please, consider to use option ’-a 1’ !\n#");<br />
314: goto endfunc;<br />
315: }<br />
316: }<br />
317: else if (algo_mode == 1) /* SVD */<br />
318: {<br />
319: err = svd_inversion( M, normal, normal_i, out);<br />
320: if (err)<br />
321: {<br />
322: /* take best parameter */<br />
323: for (j = 0; j < M; j++)<br />
324: {<br />
325: a[j] = min_a[j];<br />
326: }<br />
327: break;<br />
328: }<br />
329: } /* algo_mode SVD */<br />
330: else if (algo_mode == 2) /* LU decomposition */<br />
331: {<br />
332: int *indx = NULL, s;<br />
333: double *column = NULL;<br />
334:<br />
335: indx = ivector( M);<br />
336: column = vector( M);<br />
337:<br />
338: /* decompose the matrix */<br />
339: err = decomp_LU( normal, M, indx, &s);<br />
340: if (err)<br />
341: {<br />
342: if (err == 6)<br />
343: fprintf( out, ERR_IS_ZERO_MSG, "decomp_LU", "’max_element’");<br />
344: free_ivector( &indx);<br />
345: free_vector( &column);<br />
346: goto endfunc;<br />
347: }<br />
348: /* find inverse by back-substitution of columns */<br />
349: for (j = 0; j < M; j++)<br />
350: {<br />
351: for (i = 0; i < M; i++)<br />
352: column[i] = 0.0;<br />
353: column[j] = 1.0;<br />
354:<br />
355: backsub_LU( normal, M, indx, column);<br />
356:<br />
357: for (i = 0; i < M; i++)<br />
358: normal_i[i][j] = column[i];<br />
359: }<br />
360: free_vector( &column);<br />
361: free_ivector( &indx);<br />
362: } /* LU decomp */<br />
363:<br />
364: #ifdef QDEBUG<br />
365: fprintf( out,<br />
366: "\n#\n#== inverse normal matrix =================");<br />
367: for (i = 0; i < M; i++)<br />
368: {<br />
369: fprintf( out, "\n# ");<br />
370: for (j = 0; j < M; j++)<br />
371: {<br />
372: fprintf( out, " %12.2f", normal_i[i][j]);<br />
373: }<br />
374: }<br />
375: fflush( out);<br />
376: #endif<br />
377:<br />
378: /* final matrix multiplication to get parameter updates */<br />
379: for (j = 0; j < M; j++)<br />
380: {<br />
381: da[j] = 0.;<br />
382: for (i = 0; i < M; i++)<br />
383: {<br />
384: da[j] += normal_i[j][i] * tmpvec[i];<br />
385: }<br />
386: }<br />
387: if (ls_flag->linear)<br />
388: {<br />
389: /* linear: parameter = update */<br />
390: for (j = 0; j < M; j++)<br />
391: {<br />
392: a[j] = da[j];<br />
393: }<br />
394: }<br />
395: else /* nonlinear */<br />
396: {<br />
397: stop_flag = 0;<br />
398:<br />
399: if (iter_cnt < 3000)<br />
400: {<br />
401: fprintf( out, "\n#\n# Iteration of least squares: %d",<br />
402: iter_cnt);<br />
403: fprintf( out, "\n# Updates: ");<br />
404: }<br />
405: for (j = 0; j < M; j++)<br />
406: {<br />
407: if (iter_cnt < 3000)<br />
408: fprintf( out, "da%d=%.14G, ", j+1, da[j]);<br />
409: /* if changes are negigible */<br />
410: if ( //fabs( da[j]) < fabs( a[j]) * TOL ||<br />
411: fabs(da[j]) < TOL) /* case a[j] == 0 */<br />
412: stop_flag++;<br />
413: }<br />
414:<br />
415: /* adjust parameters */<br />
416: for (j = 0; j < M; j++)<br />
417: {<br />
418: /* adjust */<br />
419: a[j] += da[j];<br />
420: }<br />
421:<br />
422: /* update Jacobian matrix for nonlinear models */<br />
423: for (i = 0; i < N; i++)<br />
424: {<br />
425: for (j = 0; j < M; j++)<br />
426: {<br />
427: jacob[i][j] = funct_deriv( funct, i, j, M, cond, a);<br />
428: }<br />
429: }<br />
430: }<br />
431:
16 S The Source Code<br />
432: /* compute weighted <strong>and</strong> squared differences chi-squared */<br />
433: chisq = 0.0;<br />
434: Nfree = -M; /* reduce by number of parameters */<br />
435: if (ls_flag->linear)<br />
436: {<br />
437: for (i = 0; i < N; i++)<br />
438: {<br />
439: /* get calculated data points dependent on current<br />
440: parameters */<br />
441: datac[i] = 0.0;<br />
442: for (j = 0; j < M; j++)<br />
443: {<br />
444: datac[i] += a[j] * jacob[i][j];<br />
445: }<br />
446: tmp = fabs( obs[i] - datac[i]);<br />
447: /* weighted <strong>and</strong> squared differences */<br />
448: deltasq[i] = tmp * tmp;<br />
449: chisq += weights[i] * deltasq[i];<br />
450: if (weights[i] > 0.)<br />
451: Nfree++;<br />
452: }<br />
453: }<br />
454: else /* nonlinear */<br />
455: {<br />
456: for (i = 0; i < N; i++)<br />
457: {<br />
458: /* get calculated data points dependent on current<br />
459: parameters */<br />
460: datac[i] = funct( i, cond, a);<br />
461:<br />
462: tmp = fabs( obs[i] - datac[i]);<br />
463: /* weighted <strong>and</strong> squared differences */<br />
464: deltasq[i] = tmp * tmp;<br />
465: chisq += weights[i] * deltasq[i];<br />
466: if (weights[i] > 0.)<br />
467: Nfree++;<br />
468: }<br />
469: if (min_chisq < 0) /* initial value */<br />
470: {<br />
471: min_chisq = chisq;<br />
472: }<br />
473: else if (min_chisq > chisq)<br />
474: {<br />
475: /* new result is closer to minimum */<br />
476: min_chisq = chisq;<br />
477: /* copy parameters */<br />
478: for (j = 0; j < M; j++)<br />
479: {<br />
480: min_a[j] = a[j];<br />
481: }<br />
482: if (mu_fac > 2. * DBL_EPSILON)<br />
483: mu_fac *= 0.5; /* decrease Lev-Mar parameter */<br />
484: /* improvement */<br />
485: }<br />
486: else<br />
487: {<br />
488: if (ls_flag->LM)<br />
489: {<br />
490: if (iter_cnt < 3000)<br />
491: fprintf( out, "\n#\n# rejection, chisq=%.14G",<br />
492: chisq);<br />
493: if (mu_fac < 1.e+8)<br />
494: {<br />
495: /* increase Lev-Mar parameter */<br />
496: /* should not be a multiple of decreasing factor */<br />
497: /* Thurber.dat was not satisfied with 3. */<br />
498: mu_fac *= 9.;<br />
499: }<br />
500: /* restore old parameters */<br />
501: for (j = 0; j < M; j++)<br />
502: {<br />
503: a[j] = min_a[j];<br />
504: }<br />
505: }<br />
506: else<br />
507: {<br />
508: if (iter_cnt < 3000)<br />
509: fprintf( out, "\n#\n# uphill, chisq=%.14G", chisq);<br />
510: }<br />
511: }<br />
512: } /* if nonliner */<br />
513:<br />
514: variance = min_chisq / (double)Nfree;<br />
515:<br />
516: if (!ls_flag->linear)<br />
517: {<br />
518: if (iter_cnt < 3000)<br />
519: {<br />
520: fprintf( out, "\n#\n# Parameters: ");<br />
521: for (i = 0; i < M; i++)<br />
522: {<br />
523: fprintf( out, "a%d=%.12G, ", i+1, a[i]);<br />
524: }<br />
525:<br />
526: fprintf( out, "\n#\n# chisq: %.14G", min_chisq);<br />
527: if (ls_flag->LM) /* Lev-Marquardt method */<br />
528: {<br />
529: fprintf( out, "\t mu_fac: %e", mu_fac);<br />
530: }<br />
531: }<br />
532: printf( " chisq = %.15G ", min_chisq);<br />
533: /* set break condition */<br />
534: if (min_chisq == 0.0) stop_flag = M;<br />
535: fflush(stdout);<br />
536:<br />
537: /* test of convergence */<br />
538: if (stop_flag == M) /* all adjustments are negligible */<br />
539: {<br />
540: fprintf( out, "\n#\n# convergence after %d iterations",<br />
541: iter_cnt);<br />
542: if (ls_flag->chisq_target)<br />
543: {<br />
544: fprintf( out, "\n# check target (%f) ", chisq_target);<br />
545: /* check, whether maximum target error is reached */<br />
546: if (chisq chisq_target) */<br />
590: else<br />
591: break;<br />
592: } /* if (stop_flag == M) */<br />
593: } /* if (!ls_flag->linear) */<br />
594:<br />
595: iter_cnt++;<br />
596: if (!ls_flag->linear && iter_cnt >= iter_max)<br />
597: {<br />
598: /* take best parameter */<br />
599: for (j = 0; j < M; j++)<br />
600: {<br />
601: a[j] = min_a[j];<br />
602: }<br />
603: fprintf( stderr,<br />
604: "\n\n no convergence after %d iterations",<br />
605: iter_cnt);<br />
606: fprintf( stderr, "\n chisq x 1000 = %f",<br />
607: chisq * 1000);<br />
608: fprintf( out,<br />
609: "\n#\n# no convergence after %d iterations",<br />
610: iter_cnt);<br />
611: fprintf( out, "\n# chisq x 1000 = %f",<br />
612: chisq * 1000);<br />
613:<br />
614: /* ### needs more elaboration ! #####*/<br />
615: if (ls_flag->chisq_target)<br />
616: {<br />
617: fprintf( out, "\n# check target (%f) ", chisq_target);<br />
618: /* check, whether maximum target error is reached */<br />
619: if (chisq
S.2 Main functions 17<br />
624: /* no, lets re-initialise the parameters */<br />
625: fprintf( out, "\n# re-initialise parameters ");<br />
626: /* modifies only values NOT given on comm<strong>and</strong> line! */<br />
627: init( N, obs, cond, a, a_flag, out);<br />
628: /* update Jacobian matrix for nonlinear models */<br />
629: for (i = 0; i < N; i++)<br />
630: {<br />
631: for (j = 0; j < M; j++)<br />
632: {<br />
633: jacob[i][j] = funct_deriv( funct, i, j, M, cond, a);<br />
634: }<br />
635: }<br />
636: iter_cnt = 1;<br />
637: min_chisq = -1;<br />
638: mu_fac = 0.0001;<br />
639: }<br />
640: else<br />
641: break;<br />
642: }<br />
643: }<br />
644: while (!ls_flag->linear);<br />
645: /* iterate if nonlinear */<br />
646: }<br />
647:<br />
648: /*<br />
649: * determination of covariance matrix<br />
650: * if not used solve_lin()<br />
651: */<br />
652: if (!ls_flag->svd || !ls_flag->linear)<br />
653: {<br />
654: /* compute normal w/o mu !!!! */<br />
655: for (j = 0; j < M; j++)<br />
656: {<br />
657: for (i = 0; i < M; i++)<br />
658: {<br />
659: normal[j][i] = 0.;<br />
660: for (n = 0; n < N; n++)<br />
661: {<br />
662: normal[j][i] += jacob[n][j] * jacob[n][i] * weights[n];<br />
663: }<br />
664: }<br />
665: }<br />
666:<br />
667: /* inversion<br />
668: * for ill-conditioned problems (e.g. polynomials of high<br />
669: * order) the inversion of the normal matrix might fail<br />
670: *<br />
671: */<br />
672: err = svd_inversion( M, normal, covar, out);<br />
673: if (err)<br />
674: {<br />
675: /* take best parameter */<br />
676: for (j = 0; j < M; j++)<br />
677: {<br />
678: a[j] = min_a[j];<br />
679: }<br />
680: }<br />
681: }<br />
682: endfunc:<br />
683: fprintf( out,<br />
684: "\n# -- %s - end ------------------------------", rtn);<br />
685:<br />
686: free_vector( &min_a);<br />
687: free_vector( &da);<br />
688: free_vector( &tmpvec);<br />
689: free_vector( &datac);<br />
690: free_vector( &deltasq);<br />
691: free_matrix( &normal);<br />
692: free_matrix( &normal_i);<br />
693: free_matrix( &cofac);<br />
694: free_matrix( &tmpmat);<br />
695:<br />
696: return err;<br />
697: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: ls_straightline.c<br />
3: * Function....: least-squares solution for straight lines<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2007<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16:<br />
17: /*---------------------------------------------------------------<br />
18: * ls_straightline()<br />
19: *--------------------------------------------------------------*/<br />
20: void<br />
21: ls_straightline(<br />
22: int N, /* number of entries */<br />
23: double cond[], /* vector of conditions */<br />
24: double obs[], /* vector of observations */<br />
25: double a[] /* container for parameters to be estimated */<br />
26: )<br />
27: {<br />
28: int i;<br />
29: double Sxx, Sx, Sy, Sxy, tmp;<br />
30:<br />
31: Sx = Sxx = Sy = Sxy = 0.;<br />
32: for (i = 0; i < N; i++)<br />
33: {<br />
34: Sx += cond[i];<br />
35: Sy += obs[i];<br />
36: Sxx += cond[i] * cond[i];<br />
37: Sxy += cond[i] * obs[i];<br />
38: }<br />
39:<br />
40:<br />
41: tmp = N * Sxx - Sx * Sx;<br />
42: a[0] = (Sxx * Sy - Sx * Sxy) / tmp;<br />
43: a[1] = (N * Sxy - Sx * Sy) / tmp;<br />
44: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: solve_lin.c<br />
3: * Function....: solving linear least squares via SVD<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 25.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include "errmsg.h"<br />
18: #include "matrix_utils.h"<br />
19: #include "macros.h"<br />
20: #include "prototypes.h"<br />
21:<br />
22: //#define QDEBUG<br />
23:<br />
24: /*---------------------------------------------------------------<br />
25: * solve_lin()<br />
26: *<br />
27: *--------------------------------------------------------------*/<br />
28: int<br />
29: solve_lin( int N, int M, double *obs, double *weights,<br />
30: double **jacob, double **covar, double *a,<br />
31: FILE *out)<br />
32: {<br />
33: char *rtn = "solve_lin";<br />
34: int i, j, n, err = 0;<br />
35: double thresh, smax;<br />
36: double **tmpmat = NULL; /* temporary matrix */<br />
37: double **tmpmat2 = NULL; /* temporary matrix */<br />
38: double *s = NULL; /* singular values */<br />
39: double **V = NULL; /* V matrix */<br />
40: double **WJ = NULL; /* W*J matrix */<br />
41:<br />
42: V = matrix( M, M); /* V matrix for SVD */<br />
43: s = vector( M); /* singular values for SVD */<br />
44: WJ = matrix( N, M); /* temporary matrix */<br />
45: tmpmat = matrix( M, M); /* temporary matrix */<br />
46: tmpmat2 = matrix( M, N); /* temporary matrix */<br />
47:<br />
48: /* WJ = sqrt(W)*J */<br />
49: for (i = 0; i < N; i++)<br />
50: {<br />
51: for (j = 0; j < M; j++)<br />
52: {<br />
53: WJ[i][j] = sqrt(weights[i]) * jacob[i][j];<br />
54: }<br />
55: }<br />
56:<br />
57: #ifdef QDEBUG<br />
58: fprintf( out, "\n#\n#== Weight * Jacobian =================");<br />
59: for (i = 0; i < N; i++)<br />
60: {<br />
61: fprintf( out, "\n# ");<br />
62: for (j = 0; j < M; j++)<br />
63: {<br />
64: fprintf( out, " %8.5f", WJ[i][j]);<br />
65: }<br />
66: }<br />
67: #endif<br />
68:
18 S The Source Code<br />
69: /* do the SVD */<br />
70: err = singvaldec( WJ, N, M, s, V);<br />
71: if (err)<br />
72: {<br />
73: free_matrix( &V);<br />
74: free_vector( &s);<br />
75: free_matrix( &WJ);<br />
76: free_matrix( &tmpmat);<br />
77: free_matrix( &tmpmat2);<br />
78: goto endfunc;<br />
79: }<br />
80:<br />
81: #ifdef QDEBUG<br />
82: fprintf( out, "\n#\n#== U =================");<br />
83: for (i = 0; i < N; i++)<br />
84: {<br />
85: fprintf( out, "\n# ");<br />
86: for (j = 0; j < M; j++)<br />
87: {<br />
88: fprintf( out, " %8.5f", WJ[i][j]);<br />
89: }<br />
90: }<br />
91: fprintf( out, "\n#\n#== V =================");<br />
92: for (i = 0; i < M; i++)<br />
93: {<br />
94: fprintf( out, "\n# ");<br />
95: for (j = 0; j < M; j++)<br />
96: {<br />
97: fprintf( out, " %8.5f", V[i][j]);<br />
98: }<br />
99: }<br />
100: #endif<br />
101:<br />
102: /* check the singular values */<br />
103: smax = 0.0;<br />
104: for (j = 0; j < M; j++)<br />
105: {<br />
106: if (s[j] > smax) smax = s[j];<br />
107: }<br />
108: if (smax < TOL_S)<br />
109: {<br />
110: fprintf( stderr,<br />
111: "\n###\n### singular matrix, smax = %f",smax);<br />
112: fprintf( out,<br />
113: "\n###\n### singular matrix, smax = %f",smax);<br />
114:<br />
115: err = 1;<br />
116: goto endfunc;<br />
117: }<br />
118: else if (smax > 1.e+31)<br />
119: {<br />
120: fprintf( stderr,<br />
121: "\n###\n### degraded matrix, smax = %f",smax);<br />
122: fprintf( out,<br />
123: "\n###\n### degraded matrix, smax = %f",smax);<br />
124: err = 1;<br />
125: goto endfunc;<br />
126: }<br />
127:<br />
128: thresh = MIN( TOL_S * smax, TOL_S);<br />
129:<br />
130: fprintf( out, "\n#\n# singular values (thresh = %.14G)\n# ",<br />
131: thresh);<br />
132: for (j = 0; j < M; j++)<br />
133: {<br />
134: fprintf( out, "s%d=%.14G, ", j+1, s[j]);<br />
135: }<br />
136:<br />
137: /* invert singular values */<br />
138: for (j = 0; j < M; j++)<br />
139: {<br />
140: /*
S.2 Main functions 19<br />
35: int i;<br />
36: int *idx_dev=NULL;<br />
37: double *dev_sort = NULL;<br />
38: double lambda_L, lambda_L2, lambda_L2_inv;<br />
39: double max_deviate, bound;<br />
40: const double kappa_L = 0.05;<br />
41:<br />
42: fprintf( out, "\n# -- %s - start ----------------------", rtn);<br />
43: /*<br />
44: * memory allocation<br />
45: */<br />
46: idx_dev = ivector( N);<br />
47: dev_sort = vector( N);<br />
48:<br />
49: /* ascending sorting of deviates <strong>and</strong> indices */<br />
50: memcpy( dev_sort, deviates, sizeof(double) * N);<br />
51: for (i = 0; i < N; i++)<br />
52: {<br />
53: if (weights[i] == 0.)<br />
54: {<br />
55: /* weights can already be set to zero by purpose<br />
56: * in the linearisation process<br />
57: * corresponding deviates must be ignored somehow<br />
58: */<br />
59: dev_sort[i] = 0.;<br />
60: }<br />
61: }<br />
62: /* sorting of absolute deviates <strong>and</strong> of an index array */<br />
63: heap_sort_d_( N, dev_sort, idx_dev);<br />
64:<br />
65: /* get max. of all absolute deviates */<br />
66: max_deviate = dev_sort[N-1];<br />
67:<br />
68: fprintf( out, "\n# Number of observations: %d", N);<br />
69: fprintf( out, "\n# max_deviate: %f", max_deviate);<br />
70:<br />
71: /*<br />
72: * check values<br />
73: */<br />
74: if (max_deviate == 0.0)<br />
75: {<br />
76: fprintf( out, "\n#\n# all deviates are equal to zero!");<br />
77: fprintf( out, "\n# nothing to weight, perfect fit!");<br />
78: }<br />
79: else<br />
80: {<br />
81: /*<br />
82: * initialisation of threshold<br />
83: */<br />
84: /* keep half of the values with equal weights */<br />
85: lambda_L = dev_sort[N/2];<br />
86: bound = max_deviate * kappa_L;<br />
87: /* ensure minimum value for this threshold */<br />
88: if (lambda_L < bound)<br />
89: {<br />
90: /* value for worst case, stabilising LS */<br />
91: lambda_L = bound;<br />
92: }<br />
93: lambda_L2 = lambda_L * lambda_L;<br />
94: fprintf( out, "\n# lambda_L = %f", lambda_L);<br />
95:<br />
96: /*<br />
97: * do the weighting<br />
98: */<br />
99: /* inspect unsorted data */<br />
100: lambda_L2_inv = 1. / lambda_L2;<br />
101: for ( i = 0; i < N; i++)<br />
102: {<br />
103: if (weights[i] > 0.)<br />
104: {<br />
105: /* weights can already be set to zero by purpose<br />
106: * in the linearisation process<br />
107: */<br />
108: if (deviates[i] < lambda_L)<br />
109: {<br />
110: /* fixed weight */<br />
111: weights[i] = lambda_L2_inv;<br />
112: }<br />
113: else<br />
114: {<br />
115: /* adapted weight */<br />
116: weights[i] = 1. / (deviates[i] * deviates[i]);<br />
117: }<br />
118: }<br />
119: }<br />
120:<br />
121: } /* if max_deviate > 0 */<br />
122:<br />
123: #ifdef NORM_W<br />
124: /* may not used when evaluating the goodness-of-fit */<br />
125: {<br />
126: int cnt;<br />
127: double sum;<br />
128: /* Normalisation of weights */<br />
129: sum = 0.;<br />
130: cnt = 0;<br />
131: for (i = 0; i < N; i++)<br />
132: {<br />
133: if (weights[i])<br />
134: {<br />
135: sum += weights[i];<br />
136: cnt++;<br />
137: }<br />
138: }<br />
139: for (i = 0; i < N; i++)<br />
140: {<br />
141: weights[i] = weights[i] * cnt / sum;<br />
142: }<br />
143: }<br />
144: #endif<br />
145:<br />
146: /* output information for debugging */<br />
147: fprintf( out, "\n#\n# dev_sort[i] weights[ idx[i] ]");<br />
148: for (i = 0; i < N && i < MAX_LINES_W; i++)<br />
149: {<br />
150: fprintf( out, "\n#%4d %14.9e %16.8f", i,<br />
151: dev_sort[i], weights[ idx_dev[i] ]);<br />
152: }<br />
153:<br />
154: free_vector( &dev_sort);<br />
155: free_ivector( &idx_dev);<br />
156: fprintf( out, "\n# -- %s - end -------------------------",rtn);<br />
157: }<br />
158:<br />
159: /*---------------------------------------------------------------<br />
160: * est_weights2()<br />
161: *<br />
162: * weights estimation based on binning<br />
163: *<br />
164: *--------------------------------------------------------------*/<br />
165: void<br />
166: est_weights2( int N, double *cond, double *obs,<br />
167: double *weights, int obs_per_bin, FILE *out)<br />
168: {<br />
169: char *rtn="est_weights2";<br />
170: int i, n, m0, m, b, cnt;<br />
171: int num_bins;<br />
172: int *idx=NULL;<br />
173: double w, var, diff, a[2], last_cond;<br />
174: double *cond_sort=NULL;<br />
175: double *bin_cond = NULL;<br />
176: double *bin_obs = NULL;<br />
177:<br />
178: fprintf( out,<br />
179: "\n# -- %s - start ------------------------------", rtn);<br />
180:<br />
181: /* vector of conditions in a single bin */<br />
182: bin_cond = vector( obs_per_bin);<br />
183: /* vector of observations in a single bin */<br />
184: bin_obs = vector( obs_per_bin);<br />
185:<br />
186: /* determine the number of bins */<br />
187: num_bins = N / obs_per_bin;<br />
188: /* one bin for the rest */<br />
189: if (N % obs_per_bin) num_bins++;<br />
190:<br />
191: cond_sort = vector(N); /* array for sorted conditions */<br />
192: idx = ivector( N); /* vector for sorted indices */<br />
193:<br />
194: /* copy all conditions */<br />
195: memcpy( cond_sort, cond, sizeof(double)*N);<br />
196:<br />
197: /* ascending sorting of conditions <strong>and</strong> indices */<br />
198: heap_sort_d_( N, cond_sort, idx);<br />
199:<br />
200: /* initialise last condition value; just for output */<br />
201: last_cond = cond_sort[0];<br />
202:<br />
203: fprintf( out, "\n# Number of bins: %d", num_bins);<br />
204: fprintf( out, "\n# bin number_of_observations a1 ");<br />
205: fprintf( out, "a2 last_cond variance");<br />
206:<br />
207: n = 0; /* n... already used observations */<br />
208:<br />
209: /* for all bins */<br />
210: for ( b = 0; b < num_bins; b++)<br />
211: {<br />
212: if ( N-n < obs_per_bin/ 2)<br />
213: {<br />
214: /* applies for the last 2 bins:<br />
215: * if too less remaining observation,<br />
216: * then let bins overlap<br />
217: */<br />
218: m0 = n - obs_per_bin/2;<br />
219: obs_per_bin = N-m0;<br />
220: }<br />
221: else m0 = n;<br />
222:<br />
223: /*<br />
224: * piece-wise linear approximation per bin<br />
225: */<br />
226:
20 S The Source Code<br />
227: /* copy bin related values */<br />
228: cnt = 0;<br />
229: for ( i = 0, m = m0; i < obs_per_bin && m < N; i++, m++)<br />
230: {<br />
231: bin_cond[i] = cond_sort[m];<br />
232: /* bin_cond[i] = cond[ idx[m] ]; same */<br />
233: bin_obs[i] = obs[ idx[m] ];<br />
234: cnt++;<br />
235: }<br />
236: /* determine parameters for piece-wise linear fit */<br />
237: ls_straightline( cnt, bin_cond, bin_obs, a);<br />
238:<br />
239: /* determine uncertainty */<br />
240: m = m0;<br />
241: var = 0.;<br />
242: for ( i = 0; i < obs_per_bin && m < N; i++, m++)<br />
243: {<br />
244: diff = obs[ idx[m] ] - (a[0] + a[1] * bin_cond[i]);<br />
245: var += diff * diff;<br />
246: }<br />
247: var = var / (double)cnt;<br />
248: if (var > 0.)<br />
249: w = 1. / var;<br />
250: else w = 0.;<br />
251: fprintf( out,<br />
252: "\n# %4d %10d %14.4e %14.4e %14.4e %12.3e",<br />
253: b, i, a[0], a[1], bin_cond[i-1], var);<br />
254: fprintf( stdout,<br />
255: "\n g%d(x) = (x > %.4f && x < %.4f) ? %.4f +x* %.4f : 0",<br />
256: b, last_cond, bin_cond[i-1], a[0], a[1]);<br />
257:<br />
258: last_cond = bin_cond[i-1];<br />
259:<br />
260: /* klone determined bin weight for all corresponding<br />
261: * observations<br />
262: */<br />
263: for ( i = 0, m = m0; i < obs_per_bin && m < N; i++, m++)<br />
264: {<br />
265: weights[ idx[m] ] = w;<br />
266: }<br />
267: n = m; /* update number of already used observations */<br />
268: }<br />
269:<br />
270: free_vector( &bin_cond);<br />
271: free_vector( &bin_obs);<br />
272: free_vector( &cond_sort);<br />
273: free_ivector( &idx);<br />
274: fprintf( out,<br />
275: "\n# -- %s - end ------------------------------", rtn);<br />
276: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: outlier_detection.c<br />
3: * Function....: outlier detection<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 03.07.2009<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include "errmsg.h"<br />
18: #include "matrix_utils.h"<br />
19: #include "macros.h"<br />
20: #include "prototypes.h"<br />
21: #include "erf.h"<br />
22: #include "defines.h"<br />
23:<br />
24: /* disables output from outlier detection */<br />
25: /* #define COMPTEST */<br />
26:<br />
27: /*---------------------------------------------------------------<br />
28: * outlier_detection1()<br />
29: *<br />
30: * outlier_detection based on st<strong>and</strong>ard deviation of obs.<br />
31: * plus re-weighting<br />
32: *--------------------------------------------------------------*/<br />
33: int<br />
34: outlier_detection1( int N,/* number of observations */<br />
35: double sigma_y, /* st<strong>and</strong>ard uncertainty */<br />
36: double *deviates, /* absolute deviates */<br />
37: double *weights, /* weights of observations */<br />
38: double nu, /* Chauvenet’s parameter */<br />
39: FILE *out)<br />
40: {<br />
41: char *rtn = "outlier_detection1";<br />
42: int i, err;<br />
43: int count_outlier; /* counts the outliers */<br />
44: double erfval;<br />
45: double lambda_O;<br />
46: double kappa_O;<br />
47:<br />
48: #ifndef COMPTEST<br />
49: fprintf( out,<br />
50: "\n# -- %s - start ------------------------------", rtn);<br />
51: #endif<br />
52:<br />
53: if (nu > 0. && nu < 1.0)<br />
54: {<br />
55: /* set threshold according to Chauvenet’s criterion,<br />
56: * if nu is inside correct range<br />
57: */<br />
58: err = erfinv( 1 - nu / N, &erfval);<br />
59: if (err) return 0;<br />
60: kappa_O = sqrt(2.) * erfval;<br />
61: }<br />
62: else<br />
63: {<br />
64: kappa_O = 4; /* use fixed conservative threshold */<br />
65: }<br />
66:<br />
67: /* set breakdown point (threshold) */<br />
68: lambda_O = sigma_y * kappa_O;<br />
69:<br />
70: #ifndef COMPTEST<br />
71: fprintf( out, "\n# sigma_y = %f, kappa_O = %f, lambda_O = %f",<br />
72: sigma_y, kappa_O, lambda_O);<br />
73: #endif<br />
74:<br />
75: /* compare all deviates with threshold */<br />
76: count_outlier = 0;<br />
77: for (i = 0; i < N; i++)<br />
78: {<br />
79: if (deviates[i] >= lambda_O) /* take as outlier */<br />
80: {<br />
81: weights[i] = 0.0;<br />
82: count_outlier++;<br />
83: }<br />
84: }<br />
85:<br />
86: #ifndef COMPTEST<br />
87: fprintf( out,<br />
88: "\n# -- %s - end ------------------------------", rtn);<br />
89: #endif<br />
90:<br />
91: return count_outlier;<br />
92: }<br />
93:<br />
94: /*---------------------------------------------------------------<br />
95: * outlier_detection2()<br />
96: *<br />
97: * cluster-based outlier detection (ClubOD)<br />
98: *<br />
99: *--------------------------------------------------------------*/<br />
100: int<br />
101: outlier_detection2( int N,/* number of observations */<br />
102: double *deviates, /* absolute deviates */<br />
103: double *weights, /* weights of observations */<br />
104: FILE *out)<br />
105: {<br />
106: char *rtn="outlier_detection2";<br />
107: int i, j;<br />
108: int start_i; /* range for outlier search */<br />
109: int stop; /* flag */<br />
110: int cntZ; /* counter for distances being equal to zero */<br />
111: int count_outlier; /* counts the outliers */<br />
112: int *idx_dev=NULL;<br />
113: double relation, relation_max;<br />
114: double dist_loc, dist_ave;<br />
115: double *dist_glob = NULL;<br />
116: double *dist_all = NULL, dist_all_max;<br />
117: double *dist_sort = NULL;<br />
118: double *dev_sort = NULL;<br />
119: double lambda_O;<br />
120: double dist_thresh;<br />
121: double kappa1; /* kappa to be used */<br />
122:<br />
123: /* number of observations for determination of kappa_1 */<br />
124: const int NN[19]=<br />
125: { 8, 11, 16, 23, 32, 45, 64, 91, 128, 181, 256,<br />
126: 362, 512, 724, 1024, 1448, 2048, 2896, 4096<br />
127: };<br />
128: /* kappa_1 values according to NN[] */<br />
129: const double ka1[19]=<br />
130: { 7.3, 7.7, 10.1, 11.8, 14.1, 16.7, 20.3, 25.2, 31.5, 39.6, 51.3,<br />
131: 66.6, 86.4, 112, 150, 198.0, 261.0, 351.0,<br />
132: };<br />
133: const double kappa2 = 2.0;<br />
134: /* proportion of observations that should belong to the<br />
135: * bulk of good observations<br />
136: */<br />
137: const double kappa4 = 0.6;<br />
138:<br />
139: #ifndef COMPTEST
S.2 Main functions 21<br />
140: fprintf( out, "\n# -- %s - start ----------------------", rtn);<br />
141: #endif<br />
142:<br />
143: /*<br />
144: * memory allocation<br />
145: */<br />
146: idx_dev = ivector( N); /* index array */<br />
147: dev_sort = vector( N); /* sorted absolute deviations */<br />
148: dist_all = vector( N); /* distances between deviations */<br />
149: dist_sort = vector( N); /* sorted distances */<br />
150: dist_glob = vector( N); /* global distances */<br />
151:<br />
152: /*<br />
153: * determination of kappa_1 in dependent on number of<br />
154: * observations (threshold for suspicious distances)<br />
155: */<br />
156: if (N > NN[0])<br />
157: {<br />
158: if (N >= NN[18])<br />
159: kappa1 = ka1[18];<br />
160: else<br />
161: {<br />
162: for (i = 1; i < 19; i++)<br />
163: {<br />
164: if ( N 0; i--)<br />
186: {<br />
187: dist_all[i] = dev_sort[i] - dev_sort[i-1];<br />
188: }<br />
189:<br />
190: /* dummy */<br />
191: dist_all[0] = 0.;<br />
192:<br />
193: /* ascending sorting of distances in order to get<br />
194: * the median distance<br />
195: */<br />
196: memcpy( dist_sort, dist_all, sizeof(double) * N);<br />
197: heap_sort_d( N, dist_sort);<br />
198:<br />
199: #ifndef COMPTEST<br />
200: fprintf( out, "\n# Number of observations: %d", N);<br />
201: fprintf( out, "\n# kappa1: %f", kappa1);<br />
202: fprintf( out, "\n# kappa2: %f", kappa2);<br />
203: #endif<br />
204:<br />
205: /* keep major part as good observations */<br />
206: start_i = (int) ceil( kappa4 * N);<br />
207:<br />
208: /* determination of dist_glob,<br />
209: * separate value for each deviate<br />
210: */<br />
211: {<br />
212: double arg, wj, sum_wj;<br />
213: /* for all observations, which have to be tested */<br />
214: for ( i = start_i; i < N; i++)<br />
215: {<br />
216: /* compute weighted average as d_glob,<br />
217: * 2* sigma = N, variance = N*N/4<br />
218: */<br />
219: arg = -0.5 * 4. / (N * N);<br />
220: sum_wj = 0.;<br />
221: dist_glob[i] = 0;<br />
222:<br />
223: /* take all distances into account, exclude [0] */<br />
224: for (j = 1; j < i; j++)<br />
225: {<br />
226: wj = exp( j*j * arg);<br />
227: /* dist_all[] sorted according increasing deviates<br />
228: * largest fac2 for distance of highes deviate<br />
229: */<br />
230: dist_glob[i] += dist_all[i-j] * wj;<br />
231: sum_wj += wj;<br />
232: }<br />
233: if (sum_wj > 0.)<br />
234: dist_glob[i] /= sum_wj; /* normalise by sum */<br />
235: else<br />
236: dist_glob[i] = 0.0;<br />
237: }<br />
238: }<br />
239:<br />
240: if (dist_glob[start_i] == 0.0) /* check for smallest deviate */<br />
241: {<br />
242: #ifndef COMPTEST<br />
243: fprintf( out, "\n#\n# all distances are equal to zero!");<br />
244: fprintf( out, "\n# nothing to weight, perfect fit!");<br />
245: #endif<br />
246: }<br />
247: else<br />
248: {<br />
249: /*<br />
250: * initialisation of thresholds<br />
251: */<br />
252: /* reset breakdown point */<br />
253: lambda_O = 0;<br />
254:<br />
255: /*<br />
256: * search for suspicious distance<br />
257: */<br />
258:<br />
259: #ifndef COMPTEST<br />
260: fprintf( out,<br />
261: "\n#\n# n deviate d[n] d_glob");<br />
262: fprintf( out, " d[n]/d_glob d_loc d[n]/d_loc ");<br />
263: fprintf( out,<br />
264: "\n# -----------------------------------------------");<br />
265: fprintf( out, "-------------------------------");<br />
266: #endif<br />
267:<br />
268: stop = 0;<br />
269: relation_max = 0.;<br />
270: dist_all_max = 0;<br />
271:<br />
272: /* check only upper portion of sorted deviates */<br />
273: for (i = start_i; i < N && !stop; i++)<br />
274: {<br />
275: dist_thresh = dist_glob[i] * kappa1;<br />
276:<br />
277: #ifndef COMPTEST<br />
278: fprintf( out, "\n# %3d\t %.3e\t %.3e", i, dev_sort[i],<br />
279: dist_all[i]);<br />
280: fprintf( out, "\t %8.2e\t %8.2f",<br />
281: dist_glob[i], dist_all[i] / dist_glob[i]);<br />
282: #endif<br />
283:<br />
284: /* if global condition is fulfilled, then check also local<br />
285: * one<br />
286: */<br />
287: if (dist_all[i] >= dist_thresh)<br />
288: {<br />
289: double arg, wj, sum_wj;<br />
290:<br />
291: /* determination of local distance value,<br />
292: * 12* sigma = N, variance = N*N/144<br />
293: */<br />
294: arg = -0.5 * 144. / (N * N);<br />
295: cntZ = 0;<br />
296: sum_wj = 0;<br />
297: dist_ave = 0;<br />
298: for (j = 1; j < i; j++)<br />
299: {<br />
300: wj = exp( j*j * arg);<br />
301: /* largest fac2 for closest neighbour */<br />
302: dist_ave += dist_all[i-j] * wj;<br />
303: sum_wj += wj;<br />
304: /* count distances equal to zero */<br />
305: if (dist_all[i-j] == 0.0) cntZ++;<br />
306: }<br />
307: if (sum_wj)<br />
308: dist_loc = dist_ave / sum_wj;<br />
309: else<br />
310: dist_loc = 0.0;<br />
311:<br />
312: /* exception h<strong>and</strong>ling, if more than 50% of distances<br />
313: * are equal to zero<br />
314: */<br />
315: if (cntZ 0.0)<br />
319: relation = dist_all[i] / dist_loc;<br />
320: else<br />
321: relation = 0.0;<br />
322: }<br />
323: else /* exception h<strong>and</strong>ling */<br />
324: {<br />
325: /* current distance is > zero, border case */<br />
326: if (dist_all[i] > 0)<br />
327: {<br />
328: relation = kappa2;<br />
329: }<br />
330: else<br />
331: {
22 S The Source Code<br />
332: /* not considered further */<br />
333: relation = 0;<br />
334: }<br />
335: }<br />
336:<br />
337: #ifndef COMPTEST<br />
338: fprintf( out, "\t %.3e", dist_loc);<br />
339: fprintf( out, "\t %f", relation);<br />
340: #endif<br />
341:<br />
342: /* check second condition */<br />
343: if (relation >= kappa2)<br />
344: {<br />
345: /* outliers found */<br />
346:<br />
347: #ifndef COMPTEST<br />
348: fprintf( out, " *");<br />
349: #endif<br />
350: /* look for the highest relation (change in distances)*/<br />
351: if (relation > relation_max)<br />
352: {<br />
353: #ifndef COMPTEST<br />
354: fprintf( out, " ##");<br />
355: #endif<br />
356: /* deviate of current position is taken as<br />
357: * breakdown point<br />
358: */<br />
359: lambda_O = dev_sort[i];<br />
360: /* store current releation as maximal one */<br />
361: relation_max = relation;<br />
362: /* store current distance as maximum distance */<br />
363: dist_all_max = dist_all[i];<br />
364: }<br />
365: else if (relation == relation_max)<br />
366: {<br />
367: /* can happen, for instance, if relation was several<br />
368: * times equal to kappa2<br />
369: */<br />
370: /* if equal, then take teh one corresponding to the<br />
371: * larger absolute deviate<br />
372: */<br />
373: if (dist_all[i] >= dist_all_max)<br />
374: {<br />
375: /* take the one with higher distance */<br />
376: #ifndef COMPTEST<br />
377: fprintf( out, " ##");<br />
378: #endif<br />
379: lambda_O = dev_sort[i];<br />
380: relation_max = relation;<br />
381: dist_all_max = dist_all[i];<br />
382: }<br />
383: }<br />
384: /*stop = 1; */<br />
385: }<br />
386: } /* if (dist_sort[i] > dist_thresh) */<br />
387: } /* for i */<br />
388:<br />
389: /* check whether there was at least one relation<br />
390: * higher than kappa2<br />
391: */<br />
392: #ifndef COMPTEST<br />
393: if (relation_max > 0.0)<br />
394: {<br />
395: fprintf( out, "\n#\n# outliers detected !");<br />
396: fprintf( out, "\t lambda_O = %f", lambda_O);<br />
397: }<br />
398: #endif<br />
399:<br />
400: /* inspect unsorted data, set weights of outliers to zero*/<br />
401: count_outlier = 0;<br />
402: if (lambda_O > 0)<br />
403: {<br />
404: for ( i = 0; i < N; i++)<br />
405: {<br />
406: if (deviates[i] >= lambda_O) /* outliers */<br />
407: {<br />
408: weights[i] = 0.;<br />
409: count_outlier++;<br />
410: }<br />
411: }<br />
412: }<br />
413: } /* if (enough observations) */<br />
414:<br />
415: /* output information for debugging */<br />
416: #ifndef COMPTEST<br />
417: fprintf( out, "\n#\n# n deviate ");<br />
418: fprintf( out, " d[n] weights[ idx[i] ]");<br />
419: for (i = 0; i < N && i < MAX_LINES_W; i++)<br />
420: {<br />
421: fprintf( out, "\n#%4d %14.9e %14.9e %16.8f", i,<br />
422: dev_sort[i], dist_all[i],<br />
423: weights[ idx_dev[i] ]);<br />
424: }<br />
425: #endif<br />
426:<br />
427: free_vector( &dist_glob);<br />
428: free_vector( &dev_sort);<br />
429: free_vector( &dist_sort);<br />
430: free_vector( &dist_all);<br />
431: free_ivector( &idx_dev);<br />
432:<br />
433: #ifndef COMPTEST<br />
434: fprintf( out, "\n# -- %s - end -----------------------",rtn);<br />
435: #endif<br />
436:<br />
437: return count_outlier;<br />
438: }
S.3 Model functions 23<br />
S.3 Model functions<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: functions.c<br />
3: * Function....: model functions <strong>and</strong> their derivatives<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 07.05.2008, 23.06.2009, 26.10.2009, 18.02.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include <br />
19: #include "macros.h"<br />
20: #include "functions.h"<br />
21: #include "defines.h"<br />
22:<br />
23: #define DEG2RAD M_PI/180.<br />
24:<br />
25: /* for reasons of compatibility all derivative functions<br />
26: * have the same parameter list<br />
27: * xxx_deriv( double (*funct)(int,double*,double*),<br />
28: * int i, int j, int M, double *cond, double *a)<br />
29: *<br />
30: * However, the only function requiring (*funct) is the<br />
31: * generic function f_deriv()<br />
32: */<br />
33:<br />
34: /*---------------------------------------------------------------<br />
35: * fconstant_deriv()<br />
36: *--------------------------------------------------------------*/<br />
37: double<br />
38: fconstant_deriv( double (*funct)(int,double*,double*),<br />
39: int i, int j, int M, double *cond, double *a)<br />
40: {<br />
41: return 1.0; /* derivation of a1 */<br />
42: }<br />
43:<br />
44: /*---------------------------------------------------------------<br />
45: * flin_deriv()<br />
46: * f(x|a) = a1 + SUM_j a_j * x_j<br />
47: *--------------------------------------------------------------*/<br />
48: double<br />
49: flin_deriv( double (*funct)(int,double*,double*),<br />
50: int i, int j, int M, double *cond, double *a)<br />
51: {<br />
52: /* i ... number of current observation */<br />
53: if (j == 0)<br />
54: return 1.; /* derivation of a1 */<br />
55: else<br />
56: return cond[(M-1) * i + j - 1];<br />
57: }<br />
58:<br />
59: /*---------------------------------------------------------------<br />
60: * fcosine_deriv()<br />
61: * f(x|a) = a1 + a2 * cos( x) + a3 * sin( x)<br />
62: *--------------------------------------------------------------*/<br />
63: double<br />
64: fcosine_deriv( double (*funct)(int,double*,double*),<br />
65: int i, int j, int M, double *cond, double *a)<br />
66: {<br />
67: if (j == 0)<br />
68: return 1.; /* derivation of a1 */<br />
69: else if (j == 1)<br />
70: return (cos( cond[i] * DEG2RAD));<br />
71: else<br />
72: return (sin( cond[i] * DEG2RAD));<br />
73: }<br />
74:<br />
75: /*---------------------------------------------------------------<br />
76: * fcosine_nonlin()<br />
77: * f(x|a) = a1 + a2 * cos( x - a3)<br />
78: *--------------------------------------------------------------*/<br />
79: double<br />
80: fcosine_nonlin( int i, double *cond, double *a)<br />
81: {<br />
82: return a[0] + a[1] * cos( (cond[i] - a[2]) * DEG2RAD);<br />
83: }<br />
84:<br />
85: /*---------------------------------------------------------------<br />
86: * fcosine_nonlin_deriv()<br />
87: * f(x|a) = a1 + a2 * cos( x - a3)<br />
88: *--------------------------------------------------------------*/<br />
89: double<br />
90: fcosine_nonlin_deriv( double (*funct)(int,double*,double*),<br />
91: int i, int j, int M, double *cond, double *a)<br />
92: {<br />
93: if (j == 0)<br />
94: return 1.; /* derivation of a1 */<br />
95: else if (j == 1)<br />
96: return (cos( (cond[i] - a[2]) * DEG2RAD));<br />
97: else<br />
98: return (a[1] * sin( (cond[i] - a[2]) * DEG2RAD));<br />
99: }<br />
100:<br />
101: /*---------------------------------------------------------------<br />
102: * fcosine_trend()<br />
103: * f(x|a) = a1 + a2 * x + a3 * cos( x - a4)<br />
104: *--------------------------------------------------------------*/<br />
105: double<br />
106: fcosine_trend( int i, double *cond, double *a)<br />
107: {<br />
108: return a[0] + a[1] * cond[i] + a[2] * cos( cond[i] - a[3]);<br />
109: }<br />
110:<br />
111: /*---------------------------------------------------------------<br />
112: * fcosine_trend_deriv()<br />
113: * f(x|a) = a1 + a2 * x + a3 * cos( x - a4)<br />
114: *--------------------------------------------------------------*/<br />
115: double<br />
116: fcosine_trend_deriv( double (*funct)(int,double*,double*),<br />
117: int i, int j, int M, double *cond, double *a)<br />
118: {<br />
119: if (j == 0)<br />
120: return 1.; /* derivation of a1 */<br />
121: else if (j == 1)<br />
122: return cond[i];<br />
123: else if (j == 2)<br />
124: return cos( cond[i] - a[3]);<br />
125: else<br />
126: return (a[2] * sin( cond[i] - a[3]));<br />
127: }<br />
128:<br />
129: /*---------------------------------------------------------------<br />
130: * ftrigonometric1()<br />
131: * f(x|a) = a1 + a2*cos(a3*x-a4)<br />
132: *--------------------------------------------------------------*/<br />
133: double<br />
134: ftrigonometric1( int i, double *cond, double *a)<br />
135: {<br />
136: return a[0] + a[1] * cos( a[2]*cond[i] - a[3]);<br />
137: }<br />
138:<br />
139: /*---------------------------------------------------------------<br />
140: * ftrigonometric2()<br />
141: * f(x|a) = a1 + a2*cos(a3*x-a4) + a5*cos(2*a3*x-a7)<br />
142: *--------------------------------------------------------------*/<br />
143: double<br />
144: ftrigonometric2( int i, double *cond, double *a)<br />
145: {<br />
146: return a[0] + a[1] * cos( a[2]*cond[i] - a[3])<br />
147: + a[4] * cos( 2*a[2]*cond[i] - a[5]);<br />
148: }<br />
149:<br />
150: /*---------------------------------------------------------------<br />
151: * flogarithmic()<br />
152: * f(x|a) = log( a1 * x)<br />
153: *--------------------------------------------------------------*/<br />
154: double<br />
155: flogarithmic( int i, double *cond, double *a)<br />
156: {<br />
157: assert( a[0] * cond[i] > 0.);<br />
158: return log( a[0] * cond[i]);<br />
159: }<br />
160:<br />
161: /*---------------------------------------------------------------<br />
162: * flogarithmic_deriv()<br />
163: * f(x|a) = log( a1 * x)<br />
164: *--------------------------------------------------------------*/<br />
165: double<br />
166: flogarithmic_deriv( double (*funct)(int,double*,double*),<br />
167: int i, int j, int M, double *cond, double *a)<br />
168: {<br />
169: /* correction of values, which are outside the domain of<br />
170: definition */<br />
171: /* if (a[0] y’= 1/a */<br />
173: if (a[0]
24 S The Source Code<br />
190: /*---------------------------------------------------------------<br />
191: * fexponential()<br />
192: * f(x|a) = a1 + a2 * exp( a3 * x)<br />
193: *--------------------------------------------------------------*/<br />
194: double<br />
195: fexponential( int i, double *cond, double *a)<br />
196: {<br />
197: return (a[0] + a[1] * exp( a[2] *cond[i]));<br />
198: }<br />
199:<br />
200: /*---------------------------------------------------------------<br />
201: * fexponential_deriv()<br />
202: * f(x|a) = a1 + a2 * exp( a3 * x)<br />
203: *--------------------------------------------------------------*/<br />
204: double<br />
205: fexponential_deriv( double (*funct)(int,double*,double*),<br />
206: int i, int j, int M, double *cond, double *a)<br />
207: {<br />
208: if (j == 0)<br />
209: return 1.;<br />
210: else if (j == 1)<br />
211: return (exp( a[2] * cond[i]));<br />
212: else<br />
213: {<br />
214: if (a[2] < 0) /* limitation of parameter space */<br />
215: {<br />
216: return (cond[i] * a[1] * exp( a[2] * cond[i]));<br />
217: }<br />
218: else<br />
219: return cond[i] * a[1]; /* set a[2] virtually to zero */<br />
220: }<br />
221: }<br />
222:<br />
223:<br />
224: /*---------------------------------------------------------------<br />
225: * fpolynomial()<br />
226: * f(x|a) = sum_{j=1}^M aj * x^(j-1)<br />
227: *--------------------------------------------------------------*/<br />
228: double fpolynomial( int i, double *cond, double *a)<br />
229: {<br />
230: long j;<br />
231: double y, xj;<br />
232: /* since M ist not passed as a parameter, we assume maximal<br />
233: * number. oveflous a[j] must be zero !<br />
234: */<br />
235: y = a[0];<br />
236: xj = 1.;<br />
237: for ( j = 1; j < M_MAX; j++)<br />
238: {<br />
239: xj *= cond[i];<br />
240: y += a[j] * xj;<br />
241: }<br />
242: return y;<br />
243: }<br />
244:<br />
245: /*---------------------------------------------------------------<br />
246: * fpolynomial_deriv()<br />
247: * f(x|a) = sum_{j=1}^M aj * x^(j-1)<br />
248: *--------------------------------------------------------------*/<br />
249: double<br />
250: fpolynomial_deriv( double (*funct)(int,double*,double*),<br />
251: int i, int j, int M, double *cond, double *a)<br />
252: {<br />
253: return pow( cond[i], (double)j);<br />
254: }<br />
255:<br />
256: /*---------------------------------------------------------------<br />
257: * fgen_laplace()<br />
258: * f(x|a) = a1 * exp( -|x|^a2 * a3)<br />
259: *--------------------------------------------------------------*/<br />
260: double<br />
261: fgen_laplace( int i, double *cond, double *a)<br />
262: {<br />
263: return a[0] * exp( -pow( fabs( cond[i]), a[1]) * a[2]);<br />
264: }<br />
265:<br />
266: /*---------------------------------------------------------------<br />
267: * fgen_laplace_deriv()<br />
268: * f(x|a) = a1 * exp( -|x|^a2 * a3)<br />
269: *--------------------------------------------------------------*/<br />
270: double<br />
271: fgen_laplace_deriv( double (*funct)(int,double*,double*),<br />
272: int i, int j, int M, double *cond, double *a)<br />
273: {<br />
274: if (a[1] < 0) /* limitation of parameter space */<br />
275: a[1] = 1E-10;<br />
276: if (j == 0)<br />
277: {<br />
278: /* y = a0 * exp( -|x|^a1 * a2)<br />
279: * dy/da0 = exp( -a2 * |x|^a1)<br />
280: */<br />
281: return exp( -a[2] * pow( fabs( cond[i]), a[1]));<br />
282: }<br />
283: else if (j == 1)<br />
284: {<br />
285: /* y = a0 * exp( -a2 * |x|^a1)<br />
286: * dy/da1 = a0 * exp( -a2 * |x|^a1) * -a2 * |x|^a1 * ln|x|<br />
287: */<br />
288: return -a[0] * exp( -a[2] * pow( fabs( cond[i]), a[1])) *<br />
289: a[2] *<br />
290: pow( fabs( cond[i]), a[1]) * log( fabs( cond[i]));<br />
291: }<br />
292: else<br />
293: {<br />
294: /* y = a0 * exp( -a2 * |x|^a1)<br />
295: * dy/da2 = a0 * exp( -a2 * |x|^a1) * - |x|^a1<br />
296: */<br />
297: return -a[0] * exp( -a[2] * pow( fabs( cond[i]), a[1])) *<br />
298: pow( fabs( cond[i]), a[1]);<br />
299: }<br />
300: }<br />
301:<br />
302: /*---------------------------------------------------------------<br />
303: * fexpon2()<br />
304: * f(x|a) = a1 * exp( a2 * x)<br />
305: *--------------------------------------------------------------*/<br />
306: double<br />
307: fexpon2( int i, double *cond, double *a)<br />
308: {<br />
309: return (a[0] * exp( a[1] * cond[i]));<br />
310: }<br />
311:<br />
312: /*---------------------------------------------------------------<br />
313: * fexpon2_deriv()<br />
314: * f(x|a) = a1 * exp( a2 * x)<br />
315: *--------------------------------------------------------------*/<br />
316: double<br />
317: fexpon2_deriv( double (*funct)(int,double*,double*),<br />
318: int i, int j, int M, double *cond, double *a)<br />
319: {<br />
320: if (j == 0)<br />
321: {<br />
322: if (a[1] < 0) /* limitation of parameter space */<br />
323: {<br />
324: return (exp( a[1] * cond[i]));<br />
325: }<br />
326: else<br />
327: return 1; /* set a[1] virtually to zero */<br />
328: }<br />
329: else<br />
330: {<br />
331: if (a[1] < 0) /* limitation of parameter space */<br />
332: {<br />
333: return (cond[i] * a[0] * exp( a[1] * cond[i]));<br />
334: }<br />
335: else<br />
336: return cond[i] * a[0]; /* set a[1] virtually to zero */<br />
337: }<br />
338: }<br />
339:<br />
340: /*---------------------------------------------------------------<br />
341: * fgauss2()<br />
342: * f(x|a) = a1 * exp( a3 * (x-a2)^2) +<br />
343: * a4 * exp( a6 * (x-a5)^2)<br />
344: *--------------------------------------------------------------*/<br />
345: double<br />
346: fgauss2( int i, double *cond, double *a)<br />
347: {<br />
348: double tmp1 = cond[i] - a[1];<br />
349: double tmp2 = cond[i] - a[4];<br />
350: return (a[0] * exp( a[2] * tmp1 * tmp1) +<br />
351: a[3] * exp( a[5] * tmp2 * tmp2) );<br />
352: }<br />
353:<br />
354: /*---------------------------------------------------------------<br />
355: * fgauss1()<br />
356: * f(x|a) = a1 * exp( a3 * (x-a2)^2)<br />
357: *--------------------------------------------------------------*/<br />
358: double<br />
359: fgauss1( int i, double *cond, double *a)<br />
360: {<br />
361: double tmp1 = cond[i] - a[1];<br />
362: return a[0] * exp( a[2] * tmp1 * tmp1);<br />
363: }<br />
364:<br />
365: /*---------------------------------------------------------------<br />
366: * fgauss_deriv()<br />
367: * f(x|a) = a1 * exp( a3 * (x-a2)^2)<br />
368: *--------------------------------------------------------------*/<br />
369: double<br />
370: fgauss_deriv( double (*funct)(int,double*,double*),<br />
371: int i, int j, int M, double *cond, double *a)<br />
372: {<br />
373: double tmp1 = cond[i] - a[1];<br />
374:<br />
375: if (a[1] < 0) /* limitation of parameter space */<br />
376: a[1] = 1E-10;<br />
377: if (a[2] > 0) /* limitation of parameter space */<br />
378: a[2] = -1E-10;<br />
379: if (j==0)<br />
380: /* y = a1 * exp( a3 * (x-a2)^2)<br />
381: *dy/da1 = exp( a3 * (x-a2)^2)
S.3 Model functions 25<br />
382: */<br />
383: return exp( a[2] * tmp1 * tmp1);<br />
384: else if (j==1)<br />
385: /* y = a1 * exp( a3 * (x-a2)^2)<br />
386: *dy/da2 =-a1 * exp( a3 * (x-a2)^2) * a3 * 2 * (x-a2)<br />
387: */<br />
388: return -a[0] * exp( a[2] * tmp1 * tmp1) * a[2] *<br />
389: 2 * tmp1;<br />
390: else<br />
391: /* y = a1 * exp( a3 * (x-a2)^2)<br />
392: *dy/da3 = a1 * exp( a3 * (x-a2)^2) * (x-a2)^2<br />
393: */<br />
394: return a[0] * exp( a[2] * tmp1 * tmp1) * tmp1*tmp1;<br />
395: }<br />
396:<br />
397: /*---------------------------------------------------------------<br />
398: * fgauss1_deriv2()<br />
399: * f(x|a) = a1 * exp( a3 * (x-a2)^2)<br />
400: * siehe http://www.mathetools.de/differenzieren/<br />
401: *--------------------------------------------------------------*/<br />
402: double<br />
403: fgauss_deriv2( double (*funct)(int,double*,double*),<br />
404: int j, int k, int M, int i, double *cond, double *a)<br />
405: {<br />
406: double tmp1 = cond[i] - a[1];<br />
407:<br />
408: if (a[2] > 0) /* limitation of parameter space */<br />
409: a[2] = -1E-10;<br />
410:<br />
411: if (j==0)<br />
412: {<br />
413: if (k == 0)<br />
414: /* y = a1 * exp( a3 * (x-a2)^2)<br />
415: *dy/da1 = exp( a3 * (x-a2)^2)<br />
416: *d2y/d2a1 = 0<br />
417: */<br />
418: return 0;<br />
419: else if (k == 1)<br />
420: /* y = a1 * exp( a3 * (x-a2)^2)<br />
421: *dy/da1 = exp( a3 * (x-a2)^2)<br />
422: *d2y/da1da2 = -exp( a3 * (x-a2)^2) * a3 * 2 * (x-a2)<br />
423: */<br />
424: return -exp( a[2] * tmp1*tmp1) * a[2] * 2 * tmp1;<br />
425: else<br />
426: /* y = a1 * exp( a3 * (x-a2)^2)<br />
427: *dy/da1 = exp( a3 * (x-a2)^2)<br />
428: *d2y/da1da3 = exp( a3 * (x-a2)^2) * (x-a2)^2<br />
429: */<br />
430: return exp( a[2] * tmp1*tmp1) * tmp1* tmp1;<br />
431: }<br />
432: else if (j==1)<br />
433: {<br />
434: if (k == 0)<br />
435: /* y = a1 * exp( a3 * (x-a2)^2)<br />
436: *dy/da2 =-a1 * exp( a3 * (x-a2)^2) * a3 * 2 * (x-a2)<br />
437: *dy/da2da1 =-exp( a3 * (x-a2)^2) * a3 * 2 * (x-a2)<br />
438: */<br />
439: return -exp( a[2] * tmp1*tmp1) * a[2] * 2 * tmp1;<br />
440: else if (k == 1)<br />
441: /* y = a1 * exp( a3 * (x-a2)^2)<br />
442: *dy/da2 =-a1 * exp( a3 * (x-a2)^2) * a3 * 2 * (x-a2)<br />
443: *dy/da2 =-2*a1*a3 * exp( a3 * (x-a2)^2) * (x-a2)<br />
444: *dy/d2a2=-2*a1*a3 * exp( a3 * (x-a2)^2)* (-1) +<br />
445: 2*a1*a3 * exp( a3 * (x-a2)^2)* a3* 2*(x-a2) * (x-a2)<br />
446: *dy/d2a2= 4*a1*a3^2 * exp( a3 * (x-a2)^2)*(x-a2)^2 +<br />
447: * 2*a1*a3 * exp( a3 * (x-a2)^2)<br />
448: */<br />
449: return 4*a[0]*a[2]*a[2] * exp( a[2] * tmp1*tmp1)*tmp1*tmp1 +<br />
450: 2*a[0]*a[2] * exp( a[2] * tmp1*tmp1);<br />
451: else<br />
452: /* y = a1 * exp( a3 * (x-a2)^2)<br />
453: *dy/da2 =-2*a1*a3 * exp( a3 * (x-a2)^2) * (x-a2)<br />
454: *dy/da2da3 =-2*a1*(x-a2)^3* a3 * exp( a3 * (x-a2)^2) -<br />
455: * 2 * a1* (x-a2)*exp( a3 * (x-a2)^2)<br />
456: */<br />
457: return 2*a[0] * tmp1*tmp1*tmp1 * a[2] * exp( a[2] * tmp1*tmp1)<br />
458: -2 * a[0]* tmp1 * exp( a[2] * tmp1*tmp1);<br />
459: }<br />
460: else<br />
461: {<br />
462: if (k == 0)<br />
463: /* y = a1 * exp( a3 * (x-a2)^2)<br />
464: *dy/da3 = a1 * exp( a3 * (x-a2)^2) * (x-a2)^2<br />
465: *dy/da3da1 = exp( a3 * (x-a2)^2) * (x-a2)^2<br />
466: */<br />
467: return exp( a[2] * tmp1*tmp1) * tmp1* tmp1;<br />
468: else if (k == 1)<br />
469: /* y = a1 * exp( a3 * (x-a2)^2)<br />
470: *dy/da3 = a1 * exp( a3 * (x-a2)^2) * (x-a2)^2<br />
471: *dy/da2da3 =-2*a1*(x-a2)^3* a3 * exp( a3 * (x-a2)^2) -<br />
472: * 2 * a1* (x-a2)*exp( a3 * (x-a2)^2)<br />
473: */<br />
474: return 2*a[0] * tmp1*tmp1*tmp1 * a[2] * exp( a[2] * tmp1*tmp1)<br />
475: -2 * a[0]* tmp1 * exp( a[2] * tmp1*tmp1);<br />
476: else<br />
477: /* y = a1 * exp( a3 * (x-a2)^2)<br />
478: *dy/da3 = a1 * exp( a3 * (x-a2)^2) * (x-a2)^2<br />
479: *dy/d2a3= a1 * exp( a3 * (x-a2)^2) * (x-a2)^4<br />
480: */<br />
481: return a[0] * exp( a[2] * tmp1*tmp1) * tmp1*tmp1 * tmp1*tmp1;<br />
482: }<br />
483: }<br />
484:<br />
485: /*---------------------------------------------------------------<br />
486: * fcircleTLS()<br />
487: * f(x|a) = 0 = (sqrt[(x1-a1)^2 + (x2-a2)^2^] - a3)^2<br />
488: *--------------------------------------------------------------*/<br />
489: double<br />
490: fcircleTLS( int i, double *cond, double *a)<br />
491: {<br />
492: double tmp1, tmp2, d;<br />
493: /* two conditions per measurement */<br />
494: tmp1 = cond[2*i ] - a[0];<br />
495: tmp2 = cond[2*i+1] - a[1];<br />
496: d = sqrt(tmp1*tmp1 + tmp2*tmp2) - a[2];<br />
497: return d;<br />
498: }<br />
499:<br />
500: /*---------------------------------------------------------------<br />
501: * fcircleTLS_deriv()<br />
502: * f(x|a) = 0 = (sqrt[(x1-a1)^2 + (x2-a2)^2^] - a3)^2<br />
503: *--------------------------------------------------------------*/<br />
504: double<br />
505: fcircleTLS_deriv( double (*funct)(int,double*,double*),<br />
506: int i, int j, int M, double *cond, double *a)<br />
507: {<br />
508: double b, tmp1, tmp2;<br />
509: tmp1 = a[0] - cond[2*i ];<br />
510: tmp2 = a[1] - cond[2*i+1];<br />
511: b = sqrt(tmp1*tmp1 + tmp2*tmp2);<br />
512: if (j==0)<br />
513: return tmp1 / b;<br />
514: else if (j==1)<br />
515: return tmp2 / b;<br />
516: else<br />
517: return (-1);<br />
518: }<br />
519: /*---------------------------------------------------------------<br />
520: * fcircle()<br />
521: * f(x|a) = 0 = (x1-a1)^2 + (x2-a2)^2 - a3^2<br />
522: *--------------------------------------------------------------*/<br />
523: double<br />
524: fcircle( int i, double *cond, double *a)<br />
525: {<br />
526: double tmp1, tmp2;<br />
527: /* two conditions per measurement */<br />
528: tmp1 = cond[2*i ] - a[0];<br />
529: tmp2 = cond[2*i+1] - a[1];<br />
530:<br />
531: return tmp1*tmp1 + tmp2*tmp2 - a[2]*a[2];<br />
532: }<br />
533:<br />
534: /*---------------------------------------------------------------<br />
535: * fcircle_deriv()<br />
536: * f(x|a) = 0 = (x-a1)^2 + (x2-a2)^2 - a3^2<br />
537: *--------------------------------------------------------------*/<br />
538: double<br />
539: fcircle_deriv( double (*funct)(int,double*,double*),<br />
540: int i, int j, int M, double *cond, double *a)<br />
541: {<br />
542: if (j==0)<br />
543: return 2*(a[0] - cond[2*i]);<br />
544: else if (j==1)<br />
545: return 2*(a[1] - cond[2*i+1]);<br />
546: else<br />
547: return -2 * a[2];<br />
548: }<br />
549:<br />
550: /*---------------------------------------------------------------<br />
551: * fcirclelin_deriv()<br />
552: * f(x|b) = x1^2 + x2^2 = b1*x1 + b2*x2 - b3<br />
553: *--------------------------------------------------------------*/<br />
554: double<br />
555: fcirclelin_deriv( double (*funct)(int,double*,double*),<br />
556: int i, int j, int M, double *cond, double *a)<br />
557: {<br />
558: if (j==0)<br />
559: return cond[2*i];<br />
560: else if (j==1)<br />
561: return cond[2*i+1];<br />
562: else<br />
563: return -1.;<br />
564: }<br />
565:<br />
566: /*---------------------------------------------------------------<br />
567: * frotation()<br />
568: * 21... x = f1(u|a) = a1 + cos(a3) * u - sin(a3) * v<br />
569: * y = f2(u|a) = a2 + sin(a3) * u + cos(a3) * v<br />
570: *--------------------------------------------------------------*/<br />
571: double<br />
572: frotation( int i, double *cond, double *a)<br />
573: {
26 S The Source Code<br />
574: if (i%2 == 0)<br />
575: {<br />
576: /* equation for x */<br />
577: return a[0] + cos(a[2]) * cond[i] - sin(a[2]) * cond[i+1];<br />
578: }<br />
579: else<br />
580: {<br />
581: /* equation for y */<br />
582: return a[1] + sin(a[2]) * cond[i-1] + cos(a[2]) * cond[i];<br />
583: }<br />
584: }<br />
585:<br />
586: /*---------------------------------------------------------------<br />
587: * fpolynom2_deriv()<br />
588: * f(x|a) = a1 + a2 * x + a3 * x*x<br />
589: *--------------------------------------------------------------*/<br />
590: double<br />
591: fpolynom2_deriv( double (*funct) (int,double*,double*),<br />
592: int i, int j, int M, double *cond, double *a)<br />
593: {<br />
594: if (j == 0)<br />
595: return 1.;<br />
596: else if (j == 1)<br />
597: {<br />
598: return cond[i];<br />
599: }<br />
600: else<br />
601: {<br />
602: return cond[i] * cond[i];<br />
603: }<br />
604: }<br />
605:<br />
606:<br />
607: /*---------------------------------------------------------------<br />
608: * fpolynom3_deriv()<br />
609: * f(x|a) = a1 + a2 * x + a3 * x*x + a4 * x*x*x<br />
610: *--------------------------------------------------------------*/<br />
611: double<br />
612: fpolynom3_deriv( double (*funct) (int,double*,double*),<br />
613: int i, int j, int M, double *cond, double *a)<br />
614: {<br />
615: if (j == 0)<br />
616: return 1.;<br />
617: else if (j == 1)<br />
618: {<br />
619: return cond[i];<br />
620: }<br />
621: else if (j == 2)<br />
622: {<br />
623: return cond[i] * cond[i];<br />
624: }<br />
625: else<br />
626: {<br />
627: return cond[i] * cond[i] * cond[i];<br />
628: }<br />
629: }<br />
630:<br />
631: /*---------------------------------------------------------------<br />
632: * fquadsurface_deriv()<br />
633: * f(x|a) = a1 + a2*x1 + a3*x1^2 + a4*x2 + a5*x2^2<br />
634: *--------------------------------------------------------------*/<br />
635: double<br />
636: fquadsurface_deriv( double (*funct) (int,double*,double*),<br />
637: int i, int j, int M, double *cond, double *a)<br />
638: {<br />
639: if (j == 0)<br />
640: return 1.;<br />
641: else if (j == 1)<br />
642: {<br />
643: return cond[2*i];<br />
644: }<br />
645: else if (j == 2)<br />
646: {<br />
647: return cond[2*i] * cond[2*i];<br />
648: }<br />
649: else if (j == 3)<br />
650: {<br />
651: return cond[2*i+1];<br />
652: }<br />
653: else<br />
654: {<br />
655: return cond[2*i+1] * cond[2*i+1];<br />
656: }<br />
657: }<br />
658:<br />
659: /*---------------------------------------------------------------<br />
660: * fNN_3_3()<br />
661: *--------------------------------------------------------------*/<br />
662: double<br />
663: fNN_3_3( int i, double *cond, double *a)<br />
664: {<br />
665: double h1, h2, h3;<br />
666: double arg1, arg2, arg3;<br />
667:<br />
668: /* 1st hidden neuron */<br />
669: arg1 = a[0] + a[1] * cond[3*i]<br />
670: + a[2] * cond[3*i+1]<br />
671: + a[3] * cond[3*i+2];<br />
672: h1 = tanh( arg1);<br />
673:<br />
674: /* 2nd hidden neuron */<br />
675: arg2 = a[4] + a[5] * cond[3*i]<br />
676: + a[6] * cond[3*i+1]<br />
677: + a[7] * cond[3*i+2];<br />
678: h2 = tanh( arg2);<br />
679:<br />
680: /* 3rd hidden neuron */<br />
681: arg3 = a[8] + a[9] * cond[3*i]<br />
682: + a[10] * cond[3*i+1]<br />
683: + a[11] * cond[3*i+2];<br />
684: h3 = tanh( arg3);<br />
685:<br />
686: /* output neuron */<br />
687: return a[12] * h1 + a[13] * h2 + a[14] * h3;<br />
688: }<br />
689:<br />
690: /*---------------------------------------------------------------<br />
691: * fNN_3_3_sigmoid(), obsolete<br />
692: *--------------------------------------------------------------*/<br />
693: double<br />
694: fNN_3_3_sigmoid( int i, double *cond, double *a)<br />
695: {<br />
696: double h1, h2, h3;<br />
697: double arg1, arg2, arg3;<br />
698:<br />
699: /* 1st hidden neuron */<br />
700: arg1 = a[0] + a[1] * cond[3*i]<br />
701: + a[2] * cond[3*i+1]<br />
702: + a[3] * cond[3*i+2];<br />
703: h1 = 2. / (1. + exp( -arg1)) - 1;<br />
704:<br />
705: /* 2nd hidden neuron */<br />
706: arg2 = a[4] + a[5] * cond[3*i]<br />
707: + a[6] * cond[3*i+1]<br />
708: + a[7] * cond[3*i+2];<br />
709: h2 = 2. / (1. + exp( -arg2)) - 1;<br />
710:<br />
711: /* 3rd hidden neuron */<br />
712: arg3 = a[8] + a[9] * cond[3*i]<br />
713: + a[10] * cond[3*i+1]<br />
714: + a[11] * cond[3*i+2];<br />
715: h3 = 2. / (1. + exp( -arg3)) - 1;<br />
716:<br />
717: /* output neuron */<br />
718: return a[12] * h1 + a[13] * h2 + a[14] * h3 + a[15];<br />
719: }<br />
720:<br />
721: /*---------------------------------------------------------------<br />
722: * fNN_3_2()<br />
723: * f(x|a) =<br />
724: *--------------------------------------------------------------*/<br />
725: double<br />
726: fNN_3_2( int i, double *cond, double *a)<br />
727: {<br />
728: double h1, h2;<br />
729: double arg1, arg2;<br />
730:<br />
731: /* 1st hidden neuron */<br />
732: arg1 = a[0] + a[1] * cond[3*i]<br />
733: + a[2] * cond[3*i+1]<br />
734: + a[3] * cond[3*i+2];<br />
735: if (arg1 < 0) arg1 = 0;<br />
736: h1 = 2. / (1. + exp( -arg1)) - 1;<br />
737:<br />
738: /* 2nd hidden neuron */<br />
739: arg2 = a[4] + a[5] * cond[3*i]<br />
740: + a[6] * cond[3*i+1]<br />
741: + a[7] * cond[3*i+2];<br />
742: if (arg2 < 0) arg2 = 0;<br />
743: h2 = 2. / (1. + exp( -arg2)) - 1;<br />
744:<br />
745: /* output neuron */<br />
746: return a[8] * h1 + a[9] * h2 + a[10];<br />
747: }<br />
748:<br />
749: /*---------------------------------------------------------------<br />
750: * fNN_2_2()<br />
751: * f(x|a) =<br />
752: *--------------------------------------------------------------*/<br />
753: double<br />
754: fNN_2_2( int i, double *cond, double *a)<br />
755: {<br />
756: double h1, h2;<br />
757: double arg1, arg2;<br />
758:<br />
759: /* 1st hidden neuron */<br />
760: arg1 = a[0] + a[1] * cond[2*i]<br />
761: + a[2] * cond[2*i+1];<br />
762: h1 = 2. / (1. + exp( -arg1)) - 1;<br />
763:<br />
764: /* 2nd hidden neuron */<br />
765: arg2 = a[3] + a[4] * cond[2*i]
S.3 Model functions 27<br />
766: + a[5] * cond[2*i+1];<br />
767: h2 = 2. / (1. + exp( -arg2)) - 1;<br />
768:<br />
769: /* output neuron */<br />
770: return a[6] * h1 + a[7] * h2 + a[8];<br />
771: }<br />
772:<br />
773: /*---------------------------------------------------------------<br />
774: * fNN_1_2()<br />
775: * f(x|a) =<br />
776: *--------------------------------------------------------------*/<br />
777: double<br />
778: fNN_1_2( int i, double *cond, double *a)<br />
779: {<br />
780: double h1, h2;<br />
781: double arg1, arg2;<br />
782:<br />
783: /* 1st hidden neuron */<br />
784: arg1 = a[0] + a[1] * cond[i];<br />
785: /*h1 = 2. / (1. + exp( -arg1)) - 1;*/<br />
786: h1 = tanh( arg1);<br />
787:<br />
788: /* 2nd hidden neuron */<br />
789: arg2 = a[2] + a[3] * cond[i];<br />
790: /* h2 = 2. / (1. + exp( -arg2)) - 1; */<br />
791: h2 = tanh( arg2);<br />
792:<br />
793: /* output neuron */<br />
794: return a[4] * h1 + a[5] * h2 + a[6];<br />
795: }<br />
796:<br />
797: /*---------------------------------------------------------------<br />
798: * fNN_1_3()<br />
799: * f(x|a) =<br />
800: *--------------------------------------------------------------*/<br />
801: double<br />
802: fNN_1_3( int i, double *cond, double *a)<br />
803: {<br />
804: double h1, h2, h3;<br />
805: double arg;<br />
806:<br />
807: /* 1st hidden neuron */<br />
808: arg = a[0] + a[1] * cond[i];<br />
809: h1 = tanh( arg);<br />
810: /* h1 = 2. / (1. + exp( -arg)) - 1; */<br />
811:<br />
812: /* 2nd hidden neuron */<br />
813: arg = a[2] + a[3] * cond[i];<br />
814: h2 = tanh( arg);<br />
815: /* h2 = 2. / (1. + exp( -arg)) - 1; */<br />
816:<br />
817: /* 3rd hidden neuron */<br />
818: arg = a[4] + a[5] * cond[i];<br />
819: h3 = tanh( arg);<br />
820: /* h3 = 2. / (1. + exp( -arg)) - 1; */<br />
821:<br />
822: /* output neuron */<br />
823: return a[6] * h1 + a[7] * h2 + a[8] * h2 + a[9];<br />
824: }<br />
825:<br />
826: /*---------------------------------------------------------------<br />
827: * f_deriv()<br />
828: * numerical derivation, used for several model functions<br />
829: *--------------------------------------------------------------*/<br />
830: double<br />
831: f_deriv( double (*funct)(int,double*,double*),<br />
832: int i, int j, int M, double *cond, double *a)<br />
833: {<br />
834: double tmp1, tmp2, atmp[M_MAX], ajp, ajm, C;<br />
835: double del;<br />
836:<br />
837: /* inspect positions close to current one */<br />
838: if ( a[j] != 0.0)<br />
839: {<br />
840: C = 1000000;<br />
841: del = a[j]/C;<br />
842: }<br />
843: else<br />
844: {<br />
845: del = 0.001;<br />
846: }<br />
847: ajp = a[j] + del; /* plus a bit of current parameter value*/<br />
848: ajm = a[j] - del; /* minus % */<br />
849: /* create modified parameter vector,<br />
850: * copy maximum number of parameters<br />
851: */<br />
852: /* copy all possible parameters, needed for POLYNOMIAL_REG */<br />
853: memcpy( atmp, a, sizeof(double) * M_MAX);<br />
854: atmp[j] = ajp;<br />
855: /* look, what result is at modified position */<br />
856: tmp1 = funct( i , cond, atmp);<br />
857: atmp[j] = ajm;<br />
858: tmp2 = funct( i , cond, atmp);<br />
859:<br />
860: /* compute gradient */<br />
861: return tmp1 / (2*del) - tmp2 / (2*del);<br />
862: }<br />
863:<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: functions.h<br />
3: * Function....: proto typing for functions.c<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 25.09.2009, 06.11.2009, 08.01.2010, 18.02.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef FUNCT_H<br />
15: #define FUNCT_H<br />
16:<br />
17: /* linear functions */<br />
18: double fconstant_deriv( double (*funct)(int,double*,double*),<br />
19: int i, int j, int M, double *cond, double *a);<br />
20: double flin_deriv( double (*funct)(int,double*,double*),<br />
21: int i, int j, int M, double *cond, double *a);<br />
22: double fcosine_deriv( double (*funct)(int,double*,double*),<br />
23: int i, int j, int M, double *cond, double *a);<br />
24: double fprediction_deriv( double (*funct)(int,double*,double*),<br />
25: int i, int j, int M, double *cond, double *a);<br />
26: double fpolynom2_deriv( double (*funct)(int,double*,double*),<br />
27: int i, int j, int M, double *cond, double *a);<br />
28: double fpolynom3_deriv( double (*funct)(int,double*,double*),<br />
29: int i, int j, int M, double *cond, double *a);<br />
30: double fpolynomial_deriv( double (*funct)(int,double*,double*),<br />
31: int i, int j, int M, double *cond, double *a);<br />
32: double fquadsurface_deriv( double (*funct)(int,double*,double*),<br />
33: int i, int j, int M, double *cond, double *a);<br />
34:<br />
35: /* nonlinear functions */<br />
36: double fpolynomial( int i, double *cond, double *a);<br />
37: int init_polynomial( int N, double *obs, double *cond,<br />
38: double *a, unsigned char *a_flag, FILE *logfile);<br />
39:<br />
40: double fcosine_nonlin( int i, double *cond, double *a);<br />
41: double fcosine_nonlin_deriv( double (*funct)(int,double*,double*),<br />
42: int i, int j, int M, double *cond, double *a);<br />
43: int init_cosine_nonlin( int N, double *obs, double *cond,<br />
44: double *a, unsigned char *a_flag, FILE *logfile);<br />
45:<br />
46: double fcosine_trend( int i, double *cond, double *a);<br />
47: double fcosine_trend_deriv( double (*funct)(int,double*,double*),<br />
48: int i, int j, int M, double *cond, double *a);<br />
49: int init_cosine_trend( int N, double *obs, double *cond,<br />
50: double *a, unsigned char *a_flag, FILE *logfile);<br />
51:<br />
52: double ftrigonometric1( int i, double *cond, double *a);<br />
53: int init_trigonometric1( int N, double *obs, double *cond,<br />
54: double *a, unsigned char *a_flag, FILE *logfile);<br />
55:<br />
56: double ftrigonometric2( int i, double *cond, double *a);<br />
57: int init_trigonometric2( int N, double *obs, double *cond,<br />
58: double *a, unsigned char *a_flag, FILE *logfile);<br />
59:<br />
60: double flogarithmic( int i, double *cond, double *a);<br />
61: double flogarithmic_deriv( double (*funct)(int,double*,double*),<br />
62: int i, int j, int M, double *cond, double *a);<br />
63: double flogarithmic_deriv2( double (*funct)(int,double*,double*),<br />
64: int j, int k, int M, int i, double *cond, double *a);<br />
65: int init_logarithmic( int N, double *obs, double *cond,<br />
66: double *a, unsigned char *a_flag, FILE *logfile);<br />
67:<br />
68: double fexponential( int i, double *cond, double *a);<br />
69: double fexponential_deriv( double (*funct)(int,double*,double*),<br />
70: int i, int j, int M, double *cond, double *a);<br />
71: int init_exponential( int N, double *obs, double *cond,<br />
72: double *a, unsigned char *a_flag, FILE *out);<br />
73:<br />
74: double fexpon2( int i, double *cond, double *a);<br />
75: int init_expon2( int N, double *obs, double *cond,<br />
76: double *a, unsigned char *a_flag, FILE *out);<br />
77: double fgen_laplace( int i, double *cond, double *a);<br />
78: double fgen_laplace_deriv( double (*funct)(int,double*,double*),<br />
79: int i, int j, int M, double *cond, double *a);<br />
80: int init_gen_laplace( int N, double *obs, double *cond,<br />
81: double *a, unsigned char *a_flag, FILE *out);<br />
82: double fexpon2_deriv( double (*funct)(int,double*,double*),<br />
83: int i, int j, int M, double *cond, double *a);<br />
84:<br />
85: double fgauss2( int i, double *cond, double *a);<br />
86: double fgauss1( int i, double *cond, double *a);<br />
87:<br />
88: int init_gauss2( int N, double *obs, double *cond,<br />
89: double *a, unsigned char *a_flag, FILE *out);<br />
90: int init_gauss1( int N, double *obs, double *cond,double *a,<br />
91: unsigned char *a_flag, int peak_flag, FILE *out);
28 S The Source Code<br />
92:<br />
93: double fgauss_deriv( double (*funct)(int,double*,double*),<br />
94: int i, int j, int M, double *cond, double *a);<br />
95: double fgauss_deriv2( double (*funct)(int,double*,double*),<br />
96: int j, int k, int M, int i, double *cond, double *a);<br />
97: int init_gauss( int N, double *obs, double *cond,double *a,<br />
98: unsigned char *a_flag, FILE *out);<br />
99:<br />
100: double frotation( int i, double *cond, double *a);<br />
101: int init_rotation( int N, double *obs, double *cond,<br />
102: double *a, unsigned char *a_flag, FILE *logfile);<br />
103:<br />
104: double fcircleTLS( int i, double *cond, double *a);<br />
105: double fcircleTLS_deriv( double (*funct)(int,double*,double*),<br />
106: int i, int j, int M, double *cond, double *a);<br />
107: double fcircle( int i, double *cond, double *a);<br />
108: double fcircle_deriv( double (*funct)(int,double*,double*),<br />
109: int i, int j, int M, double *cond, double *a);<br />
110: int init_circle( int N, double *obs, double *cond,<br />
111: double *a, unsigned char *a_flag, FILE *logfile);<br />
112:<br />
113: double fcirclelin_deriv( double (*funct)(int,double*,double*),<br />
114: int i, int j, int M, double *cond, double *a);<br />
115: int init_circlelin( int N, double *obs, double *cond,<br />
116: double *a, unsigned char *a_flag, FILE *logfile);<br />
117:<br />
118: double fNN_3_3( int i, double *cond, double *a);<br />
119: int init_NN3x3x1( int N, double *obs, double *cond,<br />
120: double *a, unsigned char *a_flag, FILE *logfile);<br />
121: int init_NN( int N, double *obs, double *cond,<br />
122: double *a, unsigned char *a_flag, FILE *logfile);<br />
123: double fNN_3_2( int i, double *cond, double *a);<br />
124: double fNN_2_2( int i, double *cond, double *a);<br />
125: double fNN_1_2( int i, double *cond, double *a);<br />
126: double fNN_1_3( int i, double *cond, double *a);<br />
127: int init_NN1x3x1( int N, double *obs, double *cond,<br />
128: double *a, unsigned char *a_flag, FILE *logfile);<br />
129:<br />
130: /* common numerical derivation function for all<br />
131: * nonlinear problems<br />
132: */<br />
133: double f_deriv( double (*funct)(int,double*,double*),<br />
134: int i, int j, int M, double *cond, double *a);<br />
135:<br />
136: #endif<br />
0:<br />
1: /*****************************************************************<br />
2: *<br />
3: * File....: functions.c<br />
4: * Function: model functions <strong>and</strong> their derivatives<br />
5: * Author..: Tilo Strutz<br />
6: * Date....: 23.09.2007<br />
7: *<br />
8: * LICENCE DETAILS: see software manual<br />
9: * free academic use<br />
10: * cite source as<br />
11: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
12: *<br />
13: *****************************************************************/<br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include "macros.h"<br />
19: #include "functions.h"<br />
20:<br />
21: #define DEG2RAD M_PI/180.<br />
22:<br />
23: /*---------------------------------------------------------------<br />
24: * fNIST_Eckerle4()<br />
25: * f(x|a) = a1 / a2 * exp(-0.5*((x -a3)/ a2)^2)<br />
26: *--------------------------------------------------------------*/<br />
27: double<br />
28: fNIST_Eckerle4( int i, double *cond, double *a)<br />
29: {<br />
30: double x;<br />
31: x = (cond[i] - a[2]) / a[1];<br />
32: return (a[0] / a[1]) * exp( -0.5*x*x);<br />
33: }<br />
34:<br />
35: /*---------------------------------------------------------------<br />
36: * fNIST_Eckerle4_deriv()<br />
37: * f(x|a) = a1 / a2 * exp(-0.5*((x -a3)/ a2)^2)<br />
38: *--------------------------------------------------------------*/<br />
39: double<br />
40: fNIST_Eckerle4_deriv( double (*funct)(int,double*,double*),<br />
41: int i, int j, int M, double *cond, double *a)<br />
42: {<br />
43: double x;<br />
44: x = (cond[i] - a[2]) / a[1];<br />
45: if (j == 0)<br />
46: /* y = a0 / a1 * exp(-0.5*((x -a2)/ a1)^2) */<br />
47: return exp(-0.5*x*x) / a[1];<br />
48: else if (j == 1)<br />
49: return a[0] * exp(-0.5*x*x) / (a[1]*a[1]) * (x*x - 1);<br />
50: else<br />
51: return a[0] * exp(-0.5*x*x) * (cond[i] - a[2]) /<br />
52: (a[1]*a[1]*a[1]);<br />
53: }<br />
54:<br />
55: /*---------------------------------------------------------------<br />
56: * fNIST_Rat43()<br />
57: * f(x|a) = a1 / [1 + exp(a2 - a3*x)]^(1/a4)<br />
58: *--------------------------------------------------------------*/<br />
59: double<br />
60: fNIST_Rat43( int i, double *cond, double *a)<br />
61: {<br />
62: double x;<br />
63: x = exp( a[1] - a[2]*cond[i]);<br />
64: return a[0] / pow(1 + x, 1/a[3]);<br />
65: }<br />
66:<br />
67: /*---------------------------------------------------------------<br />
68: * fNIST_Rat43_deriv()<br />
69: * f(x|a) = a1 / [1 + exp(a2 - a3*x)]^(1/a4)<br />
70: *--------------------------------------------------------------*/<br />
71: double<br />
72: fNIST_Rat43_deriv( double (*funct)(int,double*,double*),<br />
73: int i, int j, int M, double *cond, double *a)<br />
74: {<br />
75: double x;<br />
76: x = exp( a[1] - a[2]*cond[i]);<br />
77: /* y = a0 / [1 + exp( a1-a2*x)]^(1/a3) */<br />
78: if (j == 0)<br />
79: return 1. / pow(1 + x, 1/a[3]);<br />
80: else if (j == 1)<br />
81: return -a[0] * x * pow( (x+1), -1/a[3]-1 ) / a[3];<br />
82: else if (j == 2)<br />
83: return a[0]*cond[i] * x * pow( (x+1), -1/a[3]-1 ) / a[3];<br />
84: else<br />
85: return a[0] * log( x+1) / (pow( (x+1), 1/a[3]) *a[3]*a[3]);<br />
86: }<br />
87:<br />
88: /*---------------------------------------------------------------<br />
89: * fNIST_Rat42()<br />
90: * f(x|a) = a1 / (1 + exp(a2 - a3*x))<br />
91: *--------------------------------------------------------------*/<br />
92: double<br />
93: fNIST_Rat42( int i, double *cond, double *a)<br />
94: {<br />
95: return a[0] / (1 + exp( a[1] - a[2]*cond[i]) );<br />
96: }<br />
97:<br />
98: /*---------------------------------------------------------------<br />
99: * fNIST_Rat42_deriv()<br />
100: * f(x|a) = a1 / (1 + exp(a2 - a3*x))<br />
101: *--------------------------------------------------------------*/<br />
102: double<br />
103: fNIST_Rat42_deriv( double (*funct)(int,double*,double*),<br />
104: int i, int j, int M, double *cond, double *a)<br />
105: {<br />
106: /* y = a0 / (1 + exp( a1 - a2*x)) */<br />
107: if (j == 0)<br />
108: return 1. / (1 + exp( a[1] - a[2]*cond[i]) );<br />
109: else if (j == 1)<br />
110: return -a[0] * exp( a[1] - a[2]*cond[i]) /<br />
111: pow( (1 + exp( a[1] - a[2]*cond[i])), 2. );<br />
112: else<br />
113: return a[0] * cond[i] * exp( a[1] - a[2]*cond[i]) /<br />
114: pow( (1 + exp( a[1] - a[2]*cond[i])), 2. );<br />
115: }<br />
116:<br />
117: /*---------------------------------------------------------------<br />
118: * fNIST_thurber()<br />
119: * f(x|a) =(a1 + a2*x + a3*x**2 + a4*x**3) /<br />
120: * (1 + a5*x + a6*x**2 + a7*x**3)<br />
121: *--------------------------------------------------------------*/<br />
122: double<br />
123: fNIST_thurber( int i, double *cond, double *a)<br />
124: {<br />
125: double x2, x3;<br />
126: x2 = cond[i]*cond[i];<br />
127: x3 = x2*cond[i];<br />
128: return (a[0] + a[1]*cond[i] + a[2]*x2 + a[3]*x3) /<br />
129: (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3);<br />
130: }<br />
131:<br />
132: /*---------------------------------------------------------------<br />
133: * fNIST_thurber_deriv()<br />
134: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
135: *--------------------------------------------------------------*/<br />
136: double<br />
137: fNIST_thurber_deriv( double (*funct)(int,double*,double*),<br />
138: int i, int j, int M, double *cond, double *a)<br />
139: {<br />
140: double x2, x3;<br />
141: x2 = cond[i]*cond[i];<br />
142: x3 = x2*cond[i];<br />
143: if (j == 0)<br />
144: /* y = (a0 + a1*x + a2*x**2 + a3*x**3) /
S.3 Model functions 29<br />
145: (1 + a4*x + a5*x**2 + a6*x**3) */<br />
146: return 1. / (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3);<br />
147: else if (j == 1)<br />
148: return cond[i] / (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3);<br />
149: else if (j == 2)<br />
150: return x2 / (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3);<br />
151: else if (j == 3)<br />
152: return x3 / (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3);<br />
153: else if (j == 4)<br />
154: return -cond[i] * (a[0] + a[1]*cond[i] + a[2]*x2 + a[3]*x3) /<br />
155: pow( (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3), 2.);<br />
156: else if (j == 5)<br />
157: return -x2 * (a[0] + a[1]*cond[i] + a[2]*x2 + a[3]*x3) /<br />
158: pow( (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3), 2.);<br />
159: else<br />
160: return -x3 * (a[0] + a[1]*cond[i] + a[2]*x2 + a[3]*x3) /<br />
161: pow( (1 + a[4]*cond[i] + a[5]*x2 + a[6]*x3), 2.);<br />
162: }<br />
163:<br />
164: /*---------------------------------------------------------------<br />
165: * fNIST_MGH09()<br />
166: * f(x|a) =a1 * (x**2 + a2*x) / (x*x + a3*x + a4)<br />
167: *--------------------------------------------------------------*/<br />
168: double<br />
169: fNIST_MGH09( int i, double *cond, double *a)<br />
170: {<br />
171: double x2;<br />
172: x2 = cond[i]*cond[i];<br />
173: return a[0] * (x2 + a[1]*cond[i]) /<br />
174: (x2 + a[2]*cond[i] + a[3]);<br />
175: }<br />
176:<br />
177: /*---------------------------------------------------------------<br />
178: * fNIST_MGH09_deriv()<br />
179: * f(x|a) =a1 * (x**2 + a2*x) / (x*x + a3*x + a4)<br />
180: *--------------------------------------------------------------*/<br />
181: double<br />
182: fNIST_MGH09_deriv( double (*funct)(int,double*,double*),<br />
183: int i, int j, int M, double *cond, double *a)<br />
184: {<br />
185: double x2;<br />
186: x2 = cond[i]*cond[i];<br />
187: if (j == 0)<br />
188: /* y = a0 * (x**2 + a1*x) / (x*x + a2*x + a3) */<br />
189: /* dy/da0 = (x**2 + a1*x) / (x*x + a2*x + a3) */<br />
190: return (x2 + a[1]*cond[i]) / (x2 + a[2]*cond[i] + a[3]);<br />
191: else if (j == 1)<br />
192: return a[0] * cond[i] / (x2 + a[2]*cond[i] + a[3]);<br />
193: else if (j == 2)<br />
194: return -a[0] * (x2 + a[1]*cond[i])*cond[i] /<br />
195: pow( (x2 + a[2]*cond[i] + a[3]), 2.);<br />
196: else<br />
197: return -a[0] * (x2 + a[1]*cond[i]) /<br />
198: pow( (x2 + a[2]*cond[i] + a[3]), 2.);<br />
199: }<br />
200:<br />
201: /*---------------------------------------------------------------<br />
202: * fNIST_MGH10()<br />
203: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
204: *--------------------------------------------------------------*/<br />
205: double<br />
206: fNIST_MGH10( int i, double *cond, double *a)<br />
207: {<br />
208: return a[0] * exp( a[1] / (cond[i] + a[2]));<br />
209: }<br />
210:<br />
211: /*---------------------------------------------------------------<br />
212: * fNIST_MGH10_deriv()<br />
213: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
214: *--------------------------------------------------------------*/<br />
215: double<br />
216: fNIST_MGH10_deriv( double (*funct)(int,double*,double*),<br />
217: int i, int j, int M, double *cond, double *a)<br />
218: {<br />
219: if (j == 0)<br />
220: /* y = a0 * exp( a1 / (x+a2)) */<br />
221: /* dy/da0 = exp( a1 / (x+a2)) */<br />
222: return exp( a[1] / (cond[i] + a[2]));<br />
223: else if (j == 1)<br />
224: /* y = a0 * exp( a1 / (x+a2)) */<br />
225: /* dy/da1 = a0 * exp( a1 / (x+a2)) / (x+a2) */<br />
226: return a[0] * exp( a[1] / (cond[i] + a[2])) / (cond[i]+ a[2]);<br />
227: else<br />
228: /* y = a0 * exp( a1 / (x+a2)) */<br />
229: /* dy/da2 =-a0*a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
230: return -a[0] * a[1] * exp( a[1] / (cond[i] + a[2])) /<br />
231: ((cond[i]+ a[2])*(cond[i]+ a[2]));<br />
232: }<br />
233:<br />
234: /*---------------------------------------------------------------<br />
235: * fNIST_MGH10_deriv2()<br />
236: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
237: *--------------------------------------------------------------*/<br />
238: double<br />
239: fNIST_MGH10_deriv2( double (*funct)(int,double*,double*),<br />
240: int j, int k, int M, int i, double *cond, double *a)<br />
241: {<br />
242: /* i ... number of current observation */<br />
243: /* j ... derivation with respect to a_j */<br />
244: /* k ... derivation with respect to a_k */<br />
245: if (j == 0)<br />
246: {<br />
247: if ( k == 0)<br />
248: /* y = a0 * exp( a1 / (x+a2)) */<br />
249: /* dy/da0 = exp( a1 / (x+a2)) */<br />
250: return 0;<br />
251: else if ( k == 1)<br />
252: /* y = a0 * exp( a1 / (x+a2)) */<br />
253: /* dy/da0 = exp( a1 / (x+a2)) */<br />
254: /* d2y/da0da1 = exp( a1 / (x+a2)) / (x+a2) */<br />
255: return exp( a[1] / (cond[i] + a[2])) /<br />
256: (cond[i] + a[2]);<br />
257: else<br />
258: /* y = a0 * exp( a1 / (x+a2)) */<br />
259: /* dy/da0 = exp( a1 / (x+a2)) */<br />
260: /* d2y/da0da2 = -a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
261: return -a[1] * exp( a[1] / (cond[i] + a[2])) /<br />
262: ((cond[i] + a[2])*(cond[i] + a[2]));<br />
263: }<br />
264: else if (j == 1)<br />
265: {<br />
266: if ( k == 0)<br />
267: /* y = a0 * exp( a1 / (x+a2)) */<br />
268: /* dy/da1 = a0 * exp( a1 / (x+a2)) / (x+a2) */<br />
269: /* d2y/da1da0 = exp( a1 / (x+a2)) / (x+a2) */<br />
270: return exp( a[1] / (cond[i] + a[2])) /<br />
271: (cond[i] + a[2]);<br />
272: else if ( k == 1)<br />
273: /* y = a0 * exp( a1 / (x+a2)) */<br />
274: /* dy/da1 = a0 * exp( a1 / (x+a2)) / (x+a2) */<br />
275: /* d2y/d2a1 = a0 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
276: return a[0] * exp( a[1] / (cond[i] + a[2])) /<br />
277: ((cond[i] + a[2])*(cond[i] + a[2]));<br />
278: else<br />
279: /* y = a0 * exp( a1 / (x+a2)) */<br />
280: /* dy/da1 = a0 * exp( a1 / (x+a2)) / (x+a2) */<br />
281: /* d2y/da1da2 =-a0 * exp( a1 / (x+a2)) / (x+a2)^2 -<br />
282: a0*a1 * exp( a1 / (x+a2)) / (x+a2)^3 */<br />
283: /* d2y/da1da2 =-a0 * exp( a1 / (x+a2)) / (x+a2)^2 *<br />
284: (1 + a1 / (x+a2)) */<br />
285: return -a[0] * exp( a[1] / (cond[i] + a[2])) /<br />
286: ((cond[i] + a[2])*(cond[i] + a[2])) *<br />
287: (1 + a[1]/(cond[i]+ a[2]));<br />
288: }<br />
289: else<br />
290: {<br />
291: if ( k == 0)<br />
292: /* y = a0 * exp( a1 / (x+a2)) */<br />
293: /* dy/da2 =-a0*a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
294: /* d2y/da0da2 = -a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
295: return -a[1] * exp( a[1] / (cond[i] + a[2])) /<br />
296: ((cond[i] + a[2])*(cond[i] + a[2]));<br />
297: else if ( k == 1)<br />
298: /* y = a0 * exp( a1 / (x+a2)) */<br />
299: /* dy/da2 =-a0*a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
300: /* d2y/da1da2 =-a0 * exp( a1 / (x+a2)) / (x+a2)^2 -<br />
301: a0*a1 * exp( a1 / (x+a2)) / (x+a2)^3 */<br />
302: /* d2y/da1da2 =-a0 * exp( a1 / (x+a2)) / (x+a2)^2 *<br />
303: (1 + a1 / (x+a2)) */<br />
304: return -a[0] * exp( a[1] / (cond[i] + a[2])) /<br />
305: ((cond[i] + a[2])*(cond[i] + a[2])) *<br />
306: (1 + a[1]/(cond[i]+ a[2]));<br />
307: else<br />
308: /* y = a0 * exp( a1 / (x+a2)) */<br />
309: /* dy/da2 =-a0*a1 * exp( a1 / (x+a2)) / (x+a2)^2 */<br />
310: /* d2y/da2da2 =2*a0*a1 * exp( a1 / (x+a2)) / (x+a2)^3 +<br />
311: a0*a1^2 * exp( a1 / (x+a2)) / (x+a2)^4 */<br />
312: /* d2y/da2da2 = a0*a1 * exp( a1 / (x+a2)) / (x+a2)^3 *<br />
313: (2 + a1 / (x+a2) */<br />
314: return a[0] * a[1] * exp( a[1] / (cond[i] + a[2])) /<br />
315: ((cond[i]+ a[2])*(cond[i]+ a[2])*(cond[i]+ a[2])) *<br />
316: (2 + a[1] /(cond[i]+ a[2]));<br />
317: }<br />
318: }<br />
319:<br />
320: /*---------------------------------------------------------------<br />
321: * fNIST_Bennett5()<br />
322: * f(x|a) = a1 * (x+a2)^(-1/a3)<br />
323: *--------------------------------------------------------------*/<br />
324: double<br />
325: fNIST_Bennett5( int i, double *cond, double *a)<br />
326: {<br />
327: return a[0] * pow( (cond[i] + a[1]), -1./a[2]);<br />
328: }<br />
329:<br />
330: /*---------------------------------------------------------------<br />
331: * fNIST_Bennett5_deriv()<br />
332: * f(x|a) = a1 * (x+a2)^(-1/a3)<br />
333: *--------------------------------------------------------------*/<br />
334: double<br />
335: fNIST_Bennett5_deriv( double (*funct)(int,double*,double*),<br />
336: int i, int j, int M, double *cond, double *a)
30 S The Source Code<br />
337: {<br />
338: /* i ... number of current observation */<br />
339: if (j == 0)<br />
340: return pow( (cond[i] + a[1]), -1./a[2]); /* derivation of a1 */<br />
341: else if (j == 1)<br />
342: return a[0] * pow( (cond[i] + a[1]), -1./a[2] - 1.)*(-1./a[2]);<br />
343: /* derivation of a2 */<br />
344: else<br />
345: return a[0] * pow( (cond[i] + a[1]), -1./a[2]) *<br />
346: log( a[1] + cond[i]) / (a[2]*a[2]);<br />
347: }<br />
348:<br />
349: /*---------------------------------------------------------------<br />
350: * fNIST_BoxBOD()<br />
351: * f(x|a) = a1 * (1 - exp( -a2 * x) )<br />
352: *--------------------------------------------------------------*/<br />
353: double<br />
354: fNIST_BoxBOD( int i, double *cond, double *a)<br />
355: {<br />
356: return ( a[0] * (1 - exp( -a[1] *cond[i])) );<br />
357: }<br />
358:<br />
359: /*---------------------------------------------------------------<br />
360: * fNIST_BoxBOD_deriv()<br />
361: * f(x|a) = a1 * (1 - exp( -a2 * x) )<br />
362: *--------------------------------------------------------------*/<br />
363: double<br />
364: fNIST_BoxBOD_deriv( double (*funct)(), int i, int j, int M,<br />
365: double *cond, double *a)<br />
366: {<br />
367: /* y = a0 * (1 - exp( -a1 * x) ) */<br />
368: if ( a[1] < 0 ) a[1] = 0;<br />
369: if (j == 0)<br />
370: {<br />
371: return (1 - exp( -a[1] *cond[i]));<br />
372: }<br />
373: else<br />
374: {<br />
375: return ( a[0] * cond[i] * exp( -a[1]*cond[i]) );<br />
376: }<br />
377: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File....: functions_NIST.h<br />
3: * Function: proto typing for functions_NIST.c<br />
4: * Author..: Tilo Strutz<br />
5: * Date....: 23.09.2009<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef FUNCT_NIST_H<br />
15: #define FUNCT_NIST_H<br />
16:<br />
17:<br />
18: /* linear functions */<br />
19:<br />
20: /* nonlinear functions */<br />
21:<br />
22: double fNIST_BoxBOD( int i, double *cond, double *a);<br />
23: double fNIST_BoxBOD_deriv( double (*funct)(int,double*,double*),<br />
24: int i, int j, int M, double *cond, double *a);<br />
25: int init_NIST_BoxBOD( int N, double *obs,<br />
26: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
27: double fNIST_MGH09( int i, double *cond, double *a);<br />
28: double fNIST_MGH09_deriv( double (*funct)(int,double*,double*),<br />
29: int i, int j, int M, double *cond, double *a);<br />
30: int init_NIST_MGH09( int N, double *obs, double *cond,<br />
31: double *a, unsigned char *a_flag, FILE *logfile);<br />
32:<br />
33: double fNIST_thurber( int i, double *cond, double *a);<br />
34: double fNIST_thurber_deriv( double (*funct)(int,double*,double*),<br />
35: int i, int j, int M, double *cond, double *a);<br />
36: int init_NIST_thurber( int N, double *obs,<br />
37: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
38:<br />
39: double fNIST_Rat42( int i, double *cond, double *a);<br />
40: double fNIST_Rat42_deriv( double (*funct)(int,double*,double*),<br />
41: int i, int j, int M, double *cond, double *a);<br />
42: int init_NIST_Rat42( int N, double *obs,<br />
43: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
44:<br />
45: double fNIST_Rat43( int i, double *cond, double *a);<br />
46: double fNIST_Rat43_deriv( double (*funct)(int,double*,double*),<br />
47: int i, int j, int M, double *cond, double *a);<br />
48: int init_NIST_Rat43( int N, double *obs,<br />
49: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
50:<br />
51: double fNIST_Eckerle4( int i, double *cond, double *a);<br />
52: double fNIST_Eckerle4_deriv( double (*funct)(int,double*,double*),<br />
53: int i, int j, int M, double *cond, double *a);<br />
54: int init_NIST_Eckerle4( int N, double *obs,<br />
55: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
56:<br />
57: double fNIST_MGH10( int i, double *cond, double *a);<br />
58: int init_NIST_MGH10( int N, double *obs,<br />
59: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
60: double fNIST_MGH10_deriv( double (*funct)(int,double*,double*),<br />
61: int i, int j, int M, double *cond, double *a);<br />
62: double fNIST_MGH10_deriv2( double (*funct)(int,double*,double*),<br />
63: int i, int j, int M, int n, double *cond, double *a);<br />
64:<br />
65: double fNIST_Bennett5( int i, double *cond, double *a);<br />
66: int init_NIST_Bennett5( int N, double *obs,<br />
67: double *cond, double *a, unsigned char *a_flag, FILE *out);<br />
68: double fNIST_Bennett5_deriv( double (*funct)(int,double*,double*),<br />
69: int i, int j, int M, double *cond, double *a);<br />
70:<br />
71: #endif
S.4 Initialisation of nonlinear models 31<br />
S.4 Initialisation of nonlinear<br />
models<br />
0: /****************************************************************<br />
1: *<br />
2: * File........: init_collection.c<br />
3: * Function....: parameter initialisation for<br />
4: * different functions<br />
5: * Author......: Tilo Strutz<br />
6: * last changes: 02.07.2009, 30.09.2009, 08.01.2010, 18.02.2010<br />
7: *<br />
8: * LICENCE DETAILS: see software manual<br />
9: * free academic use<br />
10: * cite source as<br />
11: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
12: *<br />
13: ****************************************************************/<br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include "functions.h"<br />
19: #include "macros.h"<br />
20: #include "defines.h"<br />
21: #include "prototypes.h"<br />
22:<br />
23: #ifndef WIN32<br />
24: #include <br />
25: #else<br />
26: #include <br />
27: #define r<strong>and</strong>om r<strong>and</strong><br />
28: #endif<br />
29:<br />
30: /*---------------------------------------------------------------<br />
31: * init_polynomial()<br />
32: * f(x|a) = sum_{j=1}^M aj * x^(j-1)<br />
33: *--------------------------------------------------------------*/<br />
34: int init_polynomial( int N, double *obs, double *cond,<br />
35: double *a, unsigned char *a_flag, FILE *logfile)<br />
36: {<br />
37: long j;<br />
38:<br />
39: // if (!a_flag[0] && !a_flag[1])<br />
40: // {<br />
41: /* estimate first two parameters */<br />
42: // ls_straightline( N, cond, obs, a);<br />
43: // }<br />
44: // else<br />
45: {<br />
46: if (!a_flag[0])<br />
47: a[0] = ((double)r<strong>and</strong>()/ RAND_MAX - 0.5) * 10.01;<br />
48: if (!a_flag[1])<br />
49: a[1] = ((double)r<strong>and</strong>()/ RAND_MAX - 0.5) * 10.01;<br />
50: }<br />
51: /* assume maximal number of parameters */<br />
52: for ( j = 2; j < M_MAX; j++)<br />
53: {<br />
54: if (!a_flag[j])<br />
55: a[j] = ((double)r<strong>and</strong>()/ RAND_MAX - 0.5) * 10.01;<br />
56: }<br />
57: return 0;<br />
58: }<br />
59:<br />
60: /*---------------------------------------------------------------<br />
61: * init_cosine_nonlin()<br />
62: * 5: f(x|a) = a1 + a2 * cos( x - a3) (omega = 2*pi)<br />
63: *--------------------------------------------------------------*/<br />
64: int<br />
65: init_cosine_nonlin( int N, double *obs, double *cond,<br />
66: double *a, unsigned char *a_flag, FILE *logfile)<br />
67: {<br />
68: int i;<br />
69: double mean;<br />
70:<br />
71: /* mean value for a[0] */<br />
72: if (!a_flag[0])<br />
73: {<br />
74: mean = 0;<br />
75: for (i = 0; i < N; i++)<br />
76: mean += obs[i];<br />
77: a[0] = mean / N;<br />
78: }<br />
79:<br />
80: /* estimation of a2 = radius */<br />
81: //if (!a_flag[1]) /* if not set on comm<strong>and</strong> line */<br />
82: //{<br />
83: // mean = 0;<br />
84: // for (i = 0; i < N; i++)<br />
85: // mean += obs[i] * sqrt( 2.);<br />
86: // a[1] = mean / N;<br />
87: //}<br />
88: {<br />
89: double max_obs, min_obs;<br />
90: max_obs = min_obs = obs[0];<br />
91: for (i = 1; i < N; i++)<br />
92: {<br />
93: if (max_obs < obs[i]) max_obs = obs[i];<br />
94: if (min_obs > obs[i]) min_obs = obs[i];<br />
95: }<br />
96: if (!a_flag[1]) /* if not set on comm<strong>and</strong> line */<br />
97: {<br />
98: a[1] = 0.5 * ( max_obs - min_obs);<br />
99: }<br />
100: }<br />
101:<br />
102: /* estimation of a3 = phase shift */<br />
103: if (!a_flag[2])<br />
104: {<br />
105: a[2] = 1.; /* dummy */<br />
106: }<br />
107:<br />
108: return 0;<br />
109: }<br />
110:<br />
111: /*---------------------------------------------------------------<br />
112: * init_cosine_trend()<br />
113: * 12: f(x|a) = a1 + a2 * x + a3 * cos( x - a4)<br />
114: *--------------------------------------------------------------*/<br />
115: int<br />
116: init_cosine_trend( int N, double *obs, double *cond,<br />
117: double *a, unsigned char *a_flag, FILE *logfile)<br />
118: {<br />
119: int i;<br />
120: double mean;<br />
121:<br />
122: /* mean value for a[0] */<br />
123: if (!a_flag[0])<br />
124: {<br />
125: mean = 0;<br />
126: for (i = 0; i < N; i++)<br />
127: mean += obs[i];<br />
128: a[0] = mean / N;<br />
129: }<br />
130:<br />
131: /* estimation of a3 = linear trend */<br />
132: if (!a_flag[1])<br />
133: {<br />
134: a[1] = 0.; /* dummy */<br />
135: }<br />
136:<br />
137: /* estimation of a3 = radius */<br />
138: if (!a_flag[2]) /* if not set on comm<strong>and</strong> line */<br />
139: {<br />
140: mean = 0;<br />
141: for (i = 0; i < N; i++)<br />
142: mean += obs[i] * sqrt( 2.);<br />
143: a[2] = mean / N;<br />
144: }<br />
145:<br />
146: /* estimation of a4 = phase shift */<br />
147: if (!a_flag[3])<br />
148: {<br />
149: a[3] = 0.; /* dummy */<br />
150: }<br />
151:<br />
152: return 0;<br />
153: }<br />
154:<br />
155: /*---------------------------------------------------------------<br />
156: * init_trigonometric1()<br />
157: * f(x|a) = a1 + a2*cos(a3*x-a4)<br />
158: *--------------------------------------------------------------*/<br />
159: int<br />
160: init_trigonometric1( int N, double *obs, double *cond,<br />
161: double *a, unsigned char *a_flag, FILE *logfile)<br />
162: {<br />
163: int i;<br />
164: double mean;<br />
165:<br />
166: /* mean value for a[0] */<br />
167: if (!a_flag[0])<br />
168: {<br />
169: mean = 0;<br />
170: for (i = 0; i < N; i++)<br />
171: mean += obs[i];<br />
172: a[0] = mean / N;<br />
173: }<br />
174:<br />
175: /* estimation of a3 = period */<br />
176: {<br />
177: double max_x, min_x;<br />
178: max_x = min_x = cond[0];<br />
179: for (i = 1; i < N; i++)<br />
180: {<br />
181: if (max_x < cond[i]) max_x = cond[i];<br />
182: if (min_x > cond[i]) min_x = cond[i];<br />
183: }<br />
184: if (!a_flag[2])<br />
185: a[2] = 2*3.141 / (2 * ( max_x - min_x));<br />
186: }
32 S The Source Code<br />
187:<br />
188: /* estimation of a2 = amplitude */<br />
189: {<br />
190: double max_obs, min_obs;<br />
191: max_obs = min_obs = obs[0];<br />
192: for (i = 1; i < N; i++)<br />
193: {<br />
194: if (max_obs < obs[i]) max_obs = obs[i];<br />
195: if (min_obs > obs[i]) min_obs = obs[i];<br />
196: }<br />
197: if (!a_flag[1]) /* if not set on comm<strong>and</strong> line */<br />
198: {<br />
199: a[1] = 0.5 * ( max_obs - min_obs);<br />
200: }<br />
201: }<br />
202:<br />
203: /* estimation of a4 = phase shift */<br />
204: if (!a_flag[3])<br />
205: {<br />
206: a[3] = 0.; /* dummy */<br />
207: }<br />
208:<br />
209: return 0;<br />
210: }<br />
211:<br />
212: /*---------------------------------------------------------------<br />
213: * init_trigonometric2()<br />
214: * f(x|a) = a1 + a2*cos(a3*x-a4) + a5*cos(2*a3*x-a6)<br />
215: *--------------------------------------------------------------*/<br />
216: int<br />
217: init_trigonometric2( int N, double *obs, double *cond,<br />
218: double *a, unsigned char *a_flag, FILE *logfile)<br />
219: {<br />
220: int i;<br />
221: double mean;<br />
222:<br />
223: /* mean value for a[0] */<br />
224: if (!a_flag[0])<br />
225: {<br />
226: mean = 0;<br />
227: for (i = 0; i < N; i++)<br />
228: mean += obs[i];<br />
229: a[0] = mean / N;<br />
230: }<br />
231:<br />
232: /* estimation of a3 = period */<br />
233: {<br />
234: double max_x, min_x;<br />
235: max_x = min_x = cond[0];<br />
236: for (i = 1; i < N; i++)<br />
237: {<br />
238: if (max_x < cond[i]) max_x = cond[i];<br />
239: if (min_x > cond[i]) min_x = cond[i];<br />
240: }<br />
241: if (!a_flag[2])<br />
242: a[2] = 2*3.141 / (2 * ( max_x - min_x));<br />
243: }<br />
244:<br />
245: /* estimation of a2, a5 = amplitude */<br />
246: {<br />
247: double max_obs, min_obs;<br />
248: max_obs = min_obs = obs[0];<br />
249: for (i = 1; i < N; i++)<br />
250: {<br />
251: if (max_obs < obs[i]) max_obs = obs[i];<br />
252: if (min_obs > obs[i]) min_obs = obs[i];<br />
253: }<br />
254: if (!a_flag[1]) /* if not set on comm<strong>and</strong> line */<br />
255: {<br />
256: a[1] = 0.5 * ( max_obs - min_obs);<br />
257: }<br />
258: if (!a_flag[4]) /* if not set on comm<strong>and</strong> line */<br />
259: {<br />
260: a[4] = r<strong>and</strong>() * 0.5 * ( max_obs - min_obs);<br />
261: }<br />
262: }<br />
263:<br />
264: /* estimation of a4,a6 = phase shift */<br />
265: if (!a_flag[3])<br />
266: {<br />
267: a[3] = 0.; /* dummy */<br />
268: }<br />
269: if (!a_flag[5])<br />
270: {<br />
271: a[5] = 0.; /* dummy */<br />
272: }<br />
273: return 0;<br />
274: }<br />
275:<br />
276: /*---------------------------------------------------------------<br />
277: * init_logarithmic()<br />
278: * f(x|a) = log( a1 * x)<br />
279: *--------------------------------------------------------------*/<br />
280: int<br />
281: init_logarithmic( int N, double *obs, double *cond,<br />
282: double *a, unsigned char *a_flag, FILE *logfile)<br />
283: {<br />
284: if (!a_flag[0])<br />
285: a[0] = 5;<br />
286: return 0;<br />
287: }<br />
288: /*---------------------------------------------------------------<br />
289: * init_exponential()<br />
290: * f(x|a) = a1 + a2 * exp( a3 * x)<br />
291: *--------------------------------------------------------------*/<br />
292: int<br />
293: init_exponential( int N, double *obs, double *cond,<br />
294: double *a, unsigned char *a_flag, FILE *logfile)<br />
295: {<br />
296: int err = 0; /* return value */<br />
297: int i, itmp;<br />
298: double mean;<br />
299:<br />
300: /* number of conditions to be inspected */<br />
301: itmp = MAX( 0, MIN( 5, N));<br />
302:<br />
303: /* estimation of a1 = tail of graph */<br />
304: if (!a_flag[0])<br />
305: {<br />
306: mean = 0;<br />
307: for (i = N - 1; i > N - itmp; i--)<br />
308: mean += obs[i];<br />
309: a[0] = mean / itmp;<br />
310: }<br />
311:<br />
312: /* estimation of a2 = head of function */<br />
313: if (!a_flag[1])<br />
314: {<br />
315: mean = 0;<br />
316: for (i = 0; i < itmp; i++)<br />
317: mean += obs[i];<br />
318:<br />
319: /* assumes conditions starting close to zero<br />
320: * y(x=0) = a1 + a2 * exp( a3 * 0) = a1 + a2<br />
321: */<br />
322: a[1] = mean / itmp;<br />
323: }<br />
324:<br />
325: /* estimation of a3 = gradient at head of function */<br />
326: if (!a_flag[2])<br />
327: {<br />
328: mean = 0;<br />
329: for (i = 1; i < itmp; i++)<br />
330: mean += (obs[i] - obs[i - 1]) / (cond[i] - cond[i - 1]);<br />
331: a[2] = mean / (itmp * 0.5);<br />
332: }<br />
333:<br />
334: /* if not decaying */<br />
335: if (a[0] > a[1])<br />
336: {<br />
337: fprintf( stderr, "\n a1 > a2 !");<br />
338: fprintf( stderr, "\n flip signs of a2 <strong>and</strong> a3 !\n");<br />
339: a[1] = -a[1];<br />
340: a[2] = -a[2];<br />
341: }<br />
342:<br />
343: return err;<br />
344: }<br />
345:<br />
346: /*---------------------------------------------------------------<br />
347: * init_expon2()<br />
348: * f(x|a) = a1 * exp( a2 * x)<br />
349: *--------------------------------------------------------------*/<br />
350: int<br />
351: init_expon2( int N, double *obs, double *cond,<br />
352: double *a, unsigned char *a_flag, FILE *out)<br />
353: {<br />
354: int i, itmp;<br />
355: double mean;<br />
356:<br />
357: /* number of conditions to be inspected */<br />
358: itmp = MAX( 0, MIN( 5, N));<br />
359:<br />
360: /* estimation of a1 = head of function */<br />
361: if (!a_flag[0])<br />
362: {<br />
363: mean = 0;<br />
364: for (i = 0; i < itmp; i++)<br />
365: mean += obs[i];<br />
366:<br />
367: /* assumes conditions starting close to zero<br />
368: * y(x=0) = a1 * exp( a2 * 0) = a1<br />
369: */<br />
370: a[0] = mean / itmp;<br />
371: }<br />
372:<br />
373: /* estimation of a2 = gradient at head of function<br />
374: * a2 = f’(0)/a1<br />
375: */<br />
376: if (!a_flag[1])<br />
377: {<br />
378: mean = 0;
S.4 Initialisation of nonlinear models 33<br />
379: for (i = 1; i obs[i])<br />
419: {<br />
420: min_val = obs[i];<br />
421: i_min = i; /* peak position */<br />
422: condmin = cond[i];<br />
423: }<br />
424: }<br />
425: if (max_val == min_val)<br />
426: {<br />
427: fprintf( out, "\n\n Nothing to fit !!");<br />
428: a[0] = 0.;<br />
429: a[2] = -50000000.0;<br />
430: a[1] = 0.;<br />
431: err = 8;<br />
432: goto endfunc;<br />
433: }<br />
434:<br />
435: mean = sum = var = 0.;<br />
436: /* take only that part which has the highest peak */<br />
437: if (fabs(max_val) > fabs(min_val))<br />
438: {<br />
439: /* positive amplitude */<br />
440: for (i = 0; i < N; i++)<br />
441: {<br />
442: if (obs[i] > 0.)<br />
443: {<br />
444: /* mean <strong>and</strong> variance of condition<br />
445: * observed value is like probability<br />
446: */<br />
447: tmp = cond[i] * obs[i];<br />
448: mean += tmp;<br />
449: var += cond[i] * tmp;<br />
450: sum += obs[i];<br />
451: }<br />
452: }<br />
453: if (sum > 0.)<br />
454: {<br />
455: mean /= sum; /* average along cond[i] */<br />
456: var = var/sum - mean*mean;<br />
457: }<br />
458: }<br />
459: else<br />
460: {<br />
461: /* negative amplitude */<br />
462: for (i = 0; i < N; i++)<br />
463: {<br />
464: if (obs[i] < 0.)<br />
465: {<br />
466: tmp = - cond[i] * obs[i];<br />
467: mean += tmp;<br />
468: var += cond[i] * tmp;<br />
469: sum -= obs[i];<br />
470: }<br />
471: }<br />
472: if (sum > 0.)<br />
473: {<br />
474: mean /= sum;<br />
475: var = var/sum - mean*mean;<br />
476: }<br />
477: }<br />
478:<br />
479: /* if only one data point, then sigma is zero */<br />
480: if (var > 0.) sigma = sqrt( var); /* deviation of Gaussian */<br />
481: else<br />
482: sigma = 0.0000001;<br />
483:<br />
484:<br />
485: /* get index of mean position */<br />
486: for (i = 1; i < N; i++)<br />
487: {<br />
488: if (cond[i-1] fabs(mean - condmax))<br />
506: sigma -= fabs(mean - condmax);<br />
507: }<br />
508: }<br />
509: else<br />
510: {<br />
511: {<br />
512: if (!a_flag[0]) a[0] = min_val;<br />
513: if (!a_flag[1]) a[1] = condmin;<br />
514: if (sigma > fabs(mean-condmin)) sigma -= fabs(mean-condmin);<br />
515: }<br />
516: }<br />
517: /* transcode deviation */<br />
518: if (!a_flag[2]) a[2] = -0.5 / (sigma*sigma);<br />
519:<br />
520: endfunc:<br />
521: return err;<br />
522: }<br />
523:<br />
524: /*---------------------------------------------------------------<br />
525: * init_gen_laplace()<br />
526: * f(x|a) = a1 * exp( -|x|^a2 * a3)<br />
527: *--------------------------------------------------------------*/<br />
528: int<br />
529: init_gen_laplace( int N, double *obs, double *cond,<br />
530: double *a, unsigned char *a_flag, FILE *out)<br />
531: {<br />
532: /* assumes conditions starting close to zero<br />
533: * y(x=0) = a1 * exp( 0) = a1<br />
534: */<br />
535: if (!a_flag[0])<br />
536: {<br />
537: a[0] = obs[0];<br />
538: }<br />
539: if (!a_flag[1])<br />
540: {<br />
541: a[1] = 1.0;<br />
542: }<br />
543: if (!a_flag[2])<br />
544: {<br />
545: a[2] = 0.8;<br />
546: }<br />
547:<br />
548: return 0;<br />
549: }<br />
550:<br />
551: /*---------------------------------------------------------------<br />
552: * init_circlelin()<br />
553: * f(x|a) = 0 = (x1-a1)^2 + (x2-a2)^2 - a3^2<br />
554: *--------------------------------------------------------------*/<br />
555: int<br />
556: init_circlelin( int N, double *obs, double *cond,<br />
557: double *a, unsigned char *a_flag, FILE *logfile)<br />
558: {<br />
559: int err = 0; /* return value */<br />
560: double b1, b2, b3;<br />
561:<br />
562: /* get estimates of centre coordinates <strong>and</strong> radius */<br />
563: err = init_circle( N, obs, cond, a, a_flag, logfile);<br />
564:<br />
565: /* convert into vector b */<br />
566: b1 = 2 * a[0];<br />
567: b2 = 2 * a[1];<br />
568: b3 = a[0]*a[0] + a[1]*a[1] - a[2]*a[2];<br />
569:<br />
570: /* put back to a[] */
34 S The Source Code<br />
571: a[0] = b1;<br />
572: a[1] = b2;<br />
573: a[2] = b3;<br />
574:<br />
575: return err;<br />
576: }<br />
577:<br />
578: /*---------------------------------------------------------------<br />
579: * init_circle()<br />
580: * f(x|a) = 0 = (x1-a1)^2 + (x2-a2)^2 - a3^2<br />
581: *--------------------------------------------------------------*/<br />
582: int<br />
583: init_circle( int N, double *obs, double *cond,<br />
584: double *a, unsigned char *a_flag, FILE *logfile)<br />
585: {<br />
586: int err = 0; /* return value */<br />
587: int i;<br />
588: double sum_x, sum_y, rad2, diff1, diff2;<br />
589:<br />
590: fprintf( logfile, "\n#\n# init_circle()");<br />
591:<br />
592: /*<br />
593: * determine circle centre<br />
594: */<br />
595:<br />
596: /* compute centroids of conditions */<br />
597: sum_x = sum_y = 0.;<br />
598: /* two conditions */<br />
599: for (i = 0; i < 2*N; i+=2)<br />
600: {<br />
601: sum_x += cond[i];<br />
602: sum_y += cond[i+1];<br />
603: }<br />
604: sum_x /= (double)N;<br />
605: sum_y /= (double)N;<br />
606:<br />
607: rad2 = 0;<br />
608: for (i = 0; i < 2*N; i+=2)<br />
609: {<br />
610: diff1 = cond[i] - sum_x;<br />
611: diff2 = cond[i+1] - sum_y;<br />
612: rad2 += sqrt( diff1*diff1 + diff2*diff2);<br />
613: }<br />
614: rad2 = rad2 / (double)N;<br />
615: fprintf( logfile, "\n#\n# mean of condition coordinates");<br />
616: fprintf( logfile, "\n# mean(x)= %f", sum_x);<br />
617: fprintf( logfile, "\n# mean(y)= %f", sum_y);<br />
618: fprintf( logfile, "\n# radius = %f", rad2);<br />
619:<br />
620: if (!a_flag[0]) a[0] = sum_x;<br />
621: if (!a_flag[1]) a[1] = sum_y;<br />
622: if (!a_flag[2]) a[2] = rad2;<br />
623:<br />
624: fprintf( logfile,<br />
625: "\n# f(x|a) =0= (x1-%f)**2 + (x2-%f)**2 - %f**2",<br />
626: a[0], a[1], a[2]);<br />
627:<br />
628: return err;<br />
629: }<br />
630:<br />
631: /*---------------------------------------------------------------<br />
632: * init_rotation()<br />
633: * 21... f1(x|a) = a1 + cos(a3) * x1 - sin(a3) * x2<br />
634: * f2(x|a) = a2 + sin(a3) * x1 + cos(a3) * x2<br />
635: *-------------------------------------------------------------*/<br />
636: int<br />
637: init_rotation( int N, double *obs, double *cond,<br />
638: double *a, unsigned char *a_flag, FILE *logfile)<br />
639: {<br />
640: int err = 0; /* return value */<br />
641: int i;<br />
642: double sum_x, sum_y, sum_u, sum_v;<br />
643:<br />
644: fprintf( logfile, "\n#\n# init_rotation()");<br />
645:<br />
646: /*<br />
647: * determine rough translation<br />
648: */<br />
649:<br />
650: /* compute centroids of conditions <strong>and</strong> observations */<br />
651: sum_x = sum_y = 0;<br />
652: sum_u = sum_v = 0;<br />
653: /* assume double observations <strong>and</strong> conditions */<br />
654: for (i = 0; i < N * 2; i+=2)<br />
655: {<br />
656: sum_x += obs[i];<br />
657: sum_y += obs[i+1];<br />
658: sum_u += cond[i];<br />
659: sum_v += cond[i+1];<br />
660: }<br />
661: sum_x /= (double)N;<br />
662: sum_y /= (double)N;<br />
663: sum_u /= (double)N;<br />
664: sum_v /= (double)N;<br />
665: fprintf( logfile, "\n#\n# mean of condition coordinates");<br />
666: fprintf( logfile, "\n# mean(u)= %f", sum_u);<br />
667: fprintf( logfile, "\n# mean(v)= %f", sum_v);<br />
668: fprintf( logfile, "\n# mean of observed coordinates");<br />
669: fprintf( logfile, "\n# mean(x)= %f", sum_x);<br />
670: fprintf( logfile, "\n# mean(y)= %f", sum_y);<br />
671:<br />
672: if (!a_flag[0]) a[0] = sum_x - sum_u;<br />
673: if (!a_flag[1]) a[1] = sum_y - sum_v;<br />
674: if (!a_flag[2]) a[2] = 0; /* assume no rotation */<br />
675:<br />
676:<br />
677: fprintf( logfile,<br />
678: "\n# f1(u,v) = %f + cos(%f) * u - sin(%f) * v",<br />
679: a[0], a[2], a[2]);<br />
680: fprintf( logfile,<br />
681: "\n# f2(u,v) = %f + sin(%f) * u + cos(%f) * v",<br />
682: a[1], a[2], a[2]);<br />
683:<br />
684: return err;<br />
685: }<br />
686:<br />
687: /*---------------------------------------------------------------<br />
688: * init_NN3x3x1()<br />
689: * 3x3x1<br />
690: *--------------------------------------------------------------*/<br />
691: int<br />
692: init_NN3x3x1( int N, double *obs, double *cond,<br />
693: double *a, unsigned char *a_flag, FILE *logfile)<br />
694: {<br />
695: int i, j;<br />
696: double minval, maxval;<br />
697: #ifndef WIN32<br />
698: struct timeval tv;<br />
699: struct timezone tz;<br />
700:<br />
701: gettimeofday( &tv, &tz);<br />
702: sr<strong>and</strong>om( tv.tv_sec);<br />
703: #else<br />
704: /* Seed the r<strong>and</strong>om-number generator with current time so that<br />
705: * the numbers will be different every time we run.<br />
706: */<br />
707: sr<strong>and</strong>( (unsigned)time( NULL ) );<br />
708: #endif<br />
709:<br />
710: /* give parameters r<strong>and</strong>om values */<br />
711: for ( j = 0; j < M_MAX; j++)<br />
712: {<br />
713: if (!a_flag[j])<br />
714: a[j] = 2. * (float)r<strong>and</strong>om()/ (float)RAND_MAX - 1.;<br />
715: }<br />
716:<br />
717: /* make r<strong>and</strong>om numbers in a range that |cond x param| < 5 */<br />
718: minval = maxval = cond[0];<br />
719: for ( i = 1; i < N; i++)<br />
720: {<br />
721: if (minval > cond[3*i]) minval = cond[3*i];<br />
722: if (maxval < cond[3*i]) maxval = cond[3*i];<br />
723: }<br />
724: /* weights from 1st input */<br />
725: if (!a_flag[1]) a[1] = a[1] / (maxval-minval);<br />
726: if (!a_flag[5]) a[5] = a[5] / (maxval-minval);<br />
727: if (!a_flag[9]) a[9] = a[9] / (maxval-minval);<br />
728:<br />
729: minval = maxval = cond[1];<br />
730: for ( i = 1; i < N; i++)<br />
731: {<br />
732: if (minval > cond[3*i+1]) minval = cond[3*i+1];<br />
733: if (maxval < cond[3*i+1]) maxval = cond[3*i+1];<br />
734: }<br />
735: /* weights from 2nd input */<br />
736: if (!a_flag[2]) a[2] = a[2] / (maxval-minval);<br />
737: if (!a_flag[6]) a[6] = a[6] / (maxval-minval);<br />
738: if (!a_flag[10])a[10]= a[10] / (maxval-minval);<br />
739:<br />
740: minval = maxval = cond[2];<br />
741: for ( i = 1; i < N; i++)<br />
742: {<br />
743: if (minval > cond[3*i+2]) minval = cond[3*i+2];<br />
744: if (maxval < cond[3*i+2]) maxval = cond[3*i+2];<br />
745: }<br />
746: /* weights from 3rd input */<br />
747: if (!a_flag[3]) a[3] = a[3] / (maxval-minval);<br />
748: if (!a_flag[7]) a[7] = a[7] / (maxval-minval);<br />
749: if (!a_flag[11])a[11]= a[11]/ (maxval-minval);<br />
750:<br />
751: return 0;<br />
752: }<br />
753:<br />
754: /*---------------------------------------------------------------<br />
755: * init_NN1x3x1()<br />
756: * 1x3x1<br />
757: *--------------------------------------------------------------*/<br />
758: int<br />
759: init_NN1x3x1( int N, double *obs, double *cond,<br />
760: double *a, unsigned char *a_flag, FILE *logfile)<br />
761: {<br />
762: int i, j;
S.4 Initialisation of nonlinear models 35<br />
763: double minval, maxval;<br />
764: #ifndef WIN32<br />
765: struct timeval tv;<br />
766: struct timezone tz;<br />
767:<br />
768: gettimeofday( &tv, &tz);<br />
769: sr<strong>and</strong>om( tv.tv_sec);<br />
770: #else<br />
771: /* Seed the r<strong>and</strong>om-number generator with current time so that<br />
772: * the numbers will be different every time we run.<br />
773: */<br />
774: sr<strong>and</strong>( (unsigned)time( NULL ) );<br />
775: #endif<br />
776:<br />
777: /* give parameters r<strong>and</strong>om values */<br />
778: for ( j = 0; j < M_MAX; j++)<br />
779: {<br />
780: if (!a_flag[j])<br />
781: {<br />
782: a[j] = 2. * (float)r<strong>and</strong>om() / (float)RAND_MAX - 1.;<br />
783: }<br />
784: }<br />
785:<br />
786: /* make r<strong>and</strong>om numbers in a range that |cond x param| < 5 */<br />
787: minval = maxval = cond[0];<br />
788: for ( i = 1; i < N; i++)<br />
789: {<br />
790: if (minval > cond[i]) minval = cond[i];<br />
791: if (maxval < cond[i]) maxval = cond[i];<br />
792: }<br />
793: /* weights from 1st input */<br />
794: if (!a_flag[1]) a[1] = a[1] / (maxval-minval);<br />
795: if (!a_flag[3]) a[3] = a[3] / (maxval-minval);<br />
796: if (!a_flag[5]) a[5] = a[5] / (maxval-minval);<br />
797:<br />
798: return 0;<br />
799: }<br />
800:<br />
801: /*---------------------------------------------------------------<br />
802: * init_NN()<br />
803: * 3x...<br />
804: *--------------------------------------------------------------*/<br />
805: int<br />
806: init_NN( int N, double *obs, double *cond,<br />
807: double *a, unsigned char *a_flag, FILE *logfile)<br />
808: {<br />
809: int j;<br />
810: #ifndef WIN32<br />
811: struct timeval tv;<br />
812: struct timezone tz;<br />
813:<br />
814: gettimeofday( &tv, &tz);<br />
815: sr<strong>and</strong>om( tv.tv_sec);<br />
816: #else<br />
817: /* Seed the r<strong>and</strong>om-number generator with current time so that<br />
818: * the numbers will be different every time we run.<br />
819: */<br />
820: sr<strong>and</strong>( (unsigned)time( NULL ) );<br />
821: #endif<br />
822:<br />
823: for ( j = 0; j < M_MAX; j++)<br />
824: {<br />
825: if (!a_flag[j])<br />
826: {<br />
827: a[j] = 1. * (float)r<strong>and</strong>om() / (float)RAND_MAX - 0.5;<br />
828: }<br />
829: }<br />
830: return 0;<br />
831: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: init_gauss2.c<br />
3: * Function....: parameter initialisation for<br />
4: * data fitting with 2 Gaussians<br />
5: * Author......: Tilo Strutz<br />
6: * last changes: 02.07.2009<br />
7: *<br />
8: * LICENCE DETAILS: see software manual<br />
9: * free academic use<br />
10: * cite source as<br />
11: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
12: *<br />
13: *****************************************************************/<br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include "matrix_utils.h"<br />
19: #include "functions.h"<br />
20:<br />
21: /*---------------------------------------------------------------<br />
22: * init_gauss1()<br />
23: * f(x|a) = a1 * exp( (x-a2)^2 * a3)<br />
24: *--------------------------------------------------------------*/<br />
25: int<br />
26: init_gauss1( int N, double *obs, double *cond,<br />
27: double *a, unsigned char *a_flag,<br />
28: int peak_flag, FILE *logfile)<br />
29: {<br />
30: int err = 0; /* return value */<br />
31: int i;<br />
32: int i_mean = 0, i_max, i_min;<br />
33: double max_val, min_val, condmin=0., condmax=0.;<br />
34: double mean, var, sum, sigma, tmp;<br />
35:<br />
36: /*<br />
37: * get starting point<br />
38: * assuming that one Gaussian is good enough to fit the data<br />
39: */<br />
40:<br />
41: /* get peak of curve */<br />
42: max_val = min_val = obs[1];<br />
43: i_max = i_min = 1;<br />
44: condmax = cond[1];<br />
45: condmin = cond[1];<br />
46: for (i = 2; i < N-1; i++) /* let 1 sample border */<br />
47: {<br />
48: if (max_val < obs[i])<br />
49: {<br />
50: max_val = obs[i];<br />
51: i_max = i; /* peak position index */<br />
52: condmax = cond[i]; /* peak position */<br />
53: }<br />
54: if (min_val > obs[i])<br />
55: {<br />
56: min_val = obs[i];<br />
57: i_min = i; /* peak position */<br />
58: condmin = cond[i];<br />
59: }<br />
60: }<br />
61: if (max_val == min_val)<br />
62: {<br />
63: fprintf( logfile, "\n\n Nothing to fit !!");<br />
64: a[0] = 0.;<br />
65: a[2] = -50000000.0;<br />
66: a[1] = 0.;<br />
67: err = 8;<br />
68: goto endfunc;<br />
69: }<br />
70:<br />
71: mean = sum = var = 0.;<br />
72: /* take only that part which has the highest peak */<br />
73: if (fabs(max_val) > fabs(min_val))<br />
74: {<br />
75: /* positive amplitude */<br />
76: for (i = 0; i < N; i++)<br />
77: {<br />
78: if (obs[i] > 0.)<br />
79: {<br />
80: /* mean <strong>and</strong> variance of condition<br />
81: * observed value is like probability<br />
82: */<br />
83: tmp = cond[i] * obs[i];<br />
84: mean += tmp;<br />
85: var += cond[i] * tmp;<br />
86: sum += obs[i];<br />
87: }<br />
88: }<br />
89: if (sum > 0.)<br />
90: {<br />
91: mean /= sum; /* average along cond[i] */<br />
92: var = var/sum - mean*mean;<br />
93: }<br />
94: }<br />
95: else<br />
96: {<br />
97: /* negative amplitude */<br />
98: for (i = 0; i < N; i++)<br />
99: {<br />
100: if (obs[i] < 0.)<br />
101: {<br />
102: tmp = - cond[i] * obs[i];<br />
103: mean += tmp;<br />
104: var += cond[i] * tmp;<br />
105: sum -= obs[i];<br />
106: }<br />
107: }<br />
108: if (sum > 0.)<br />
109: {<br />
110: mean /= sum;<br />
111: var = var/sum - mean*mean;<br />
112: }<br />
113: }<br />
114: /* if only one data point, then sigma is zero */<br />
115: if (var > 0.) sigma = sqrt( var); /* deviation of Gaussian */<br />
116: else<br />
117: sigma = 0.0000001;<br />
118:<br />
119:<br />
120: /* get index of mean position */
36 S The Source Code<br />
121: for (i = 1; i < N; i++)<br />
122: {<br />
123: if (cond[i-1] fabs(mean - condmax))<br />
142: sigma -= fabs(mean - condmax);<br />
143: }<br />
144: else<br />
145: {<br />
146: /* increase by value dependent on obs at mean position */<br />
147: if (!a_flag[0])<br />
148: {<br />
149: a[0] = max_val + (max_val - obs[i_mean]) * 0.5;<br />
150: }<br />
151: if (!a_flag[1]) a[1] = mean;<br />
152: }<br />
153: }<br />
154: else<br />
155: {<br />
156: if (peak_flag)<br />
157: {<br />
158: if (!a_flag[0]) a[0] = min_val;<br />
159: if (!a_flag[1]) a[1] = condmin;<br />
160: if (sigma > fabs(mean-condmin)) sigma -= fabs(mean-condmin);<br />
161: }<br />
162: else<br />
163: {<br />
164: if (!a_flag[0])<br />
165: {<br />
166: a[0] = max_val + (max_val - obs[i_mean]) * 0.5;<br />
167: }<br />
168: if (!a_flag[1]) a[1] = mean;<br />
169: }<br />
170: }<br />
171: /* transcode deviation */<br />
172: if (!a_flag[2]) a[2] = -0.5 / (sigma*sigma);<br />
173:<br />
174: endfunc:<br />
175: return err;<br />
176: }<br />
177:<br />
178: /*---------------------------------------------------------------<br />
179: * init_gauss2()<br />
180: * f(x|a) = a1 * exp( a2 * (x-a3)^2) +<br />
181: * a4 * exp( a5 * (x-a6)^2)<br />
182: *--------------------------------------------------------------*/<br />
183: int<br />
184: init_gauss2( int N, double *obs, double *cond,<br />
185: double *a, unsigned char *a_flag, FILE *out)<br />
186: {<br />
187: int err = 0; /* return value */<br />
188: int i, M;<br />
189: double sigma1, sigma2;<br />
190: double *obs_cpy=NULL;<br />
191:<br />
192: M = 6; /* fixed number of parameters */<br />
193: obs_cpy = vector( N);<br />
194:<br />
195: /*<br />
196: * get starting point<br />
197: * assuming that one Gaussian is good enough to fit the data<br />
198: */<br />
199: /* initialises a[0], a[1], a[2]; select highest peak */<br />
200: err = init_gauss1( N, obs, cond, a, a_flag, 1, out);<br />
201: if (err) goto endfunc;<br />
202:<br />
203: sigma2 = sqrt( -0.5 / a[2]); /* get deviation back */<br />
204:<br />
205: fprintf( out, "\n# Initial parameter: first Gaussian");<br />
206: fprintf( out, "\n# amplitude: %f, mean: %f, deviation: %f",<br />
207: a[0], a[1], sigma2);<br />
208: /*<br />
209: * compute residuals between observation <strong>and</strong> model<br />
210: */<br />
211: for ( i = 0; i < N; i++)<br />
212: {<br />
213: obs_cpy[i] = obs[i] - fgauss1( i, cond, a);<br />
214: }<br />
215: /* prevent overwriting of first three parameters */<br />
216: a[3] = a[0];<br />
217: a[4] = a[1];<br />
218: a[5] = a[2];<br />
219:<br />
220: /* initialises a[0], a[1], a[2]; fitting of residual */<br />
221: init_gauss1( N, obs_cpy, cond, a, a_flag, 1, out);<br />
222: sigma1 = sqrt( -0.5 / a[2]);<br />
223: fprintf( out, "\n# Initial parameter: second Gaussian");<br />
224: fprintf( out, "\n# amplitude: %f, mean: %f, deviation: %f",<br />
225: a[0], a[1], sigma1);<br />
226:<br />
227: fprintf( out, "\n#\n# f(x) = %f * exp( ( x- %f)**2 * %f)",<br />
228: a[0],a[1],a[2]);<br />
229: fprintf( out, "+ %f * exp( ( x- %f)**2 * %f)",<br />
230: a[3],a[4],a[5]);<br />
231: endfunc:<br />
232: free_vector( &obs_cpy);<br />
233: return err;<br />
234: }<br />
0:<br />
1: /*****************************************************************<br />
2: *<br />
3: * File........: init_NIST.c<br />
4: * Function....: parameter initialisation for<br />
5: * different functions<br />
6: * Author......: Tilo Strutz<br />
7: * last changes: 28.09.2009, 20.01.2010<br />
8: *<br />
9: * LICENCE DETAILS: see software manual<br />
10: * free academic use<br />
11: * cite source as<br />
12: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
13: *<br />
14: *****************************************************************/<br />
15: #include <br />
16: #include <br />
17: #include <br />
18: #include <br />
19: #include "functions.h"<br />
20: #include "macros.h"<br />
21: #ifndef WIN32<br />
22: #include <br />
23: #else<br />
24: #include <br />
25: #define r<strong>and</strong>om r<strong>and</strong><br />
26: #endif<br />
27:<br />
28: /*---------------------------------------------------------------<br />
29: * init_NIST_Eckerle4()<br />
30: * f(x|a) = a1 / a2 * exp(-0.5*((x -a3)/ a2)^2)<br />
31: *--------------------------------------------------------------*/<br />
32: int<br />
33: init_NIST_Eckerle4( int N, double *obs, double *cond,<br />
34: double *a, unsigned char *a_flag, FILE *logfile)<br />
35: {<br />
36: int i, maxpos;<br />
37: double maxval;<br />
38:<br />
39: /* estimated parameter of a Gaussian bell */<br />
40:<br />
41: /* get mean value at maximum point */<br />
42: if (!a_flag[2])<br />
43: {<br />
44: maxval = obs[0];<br />
45: maxpos = 0;<br />
46: a[2] = cond[0];<br />
47: for ( i = 1; i < N; i++)<br />
48: {<br />
49: if (maxval < obs[i])<br />
50: {<br />
51: maxval = obs[i];<br />
52: maxpos = i;<br />
53: a[2] = cond[i];<br />
54: }<br />
55: }<br />
56: }<br />
57: /* get sigma */<br />
58: if (!a_flag[1])<br />
59: {<br />
60: for ( i = maxpos+1; i < N; i++)<br />
61: {<br />
62: if (obs[i] < maxval/2)<br />
63: {<br />
64: a[1] = i - maxpos;<br />
65: break;<br />
66: }<br />
67: }<br />
68: }<br />
69: /* get magnification */<br />
70: if (!a_flag[0])<br />
71: {<br />
72: a[0] = maxval * a[1];<br />
73: }<br />
74:<br />
75: return 0;
S.4 Initialisation of nonlinear models 37<br />
76: }<br />
172: /* set 1 */<br />
77:<br />
173: if (!a_flag[0]) a[0] = -2000;<br />
78: /*--------------------------------------------------------------- 174: if (!a_flag[1]) a[1] = 50;<br />
79: * init_NIST_Rat43()<br />
175: if (!a_flag[2]) a[2] = 0.8;<br />
80: * f(x|a) = a1 / (1 + exp(a2 - a3*x)^(1/a4))<br />
176:<br />
81: *--------------------------------------------------------------*/ 177: return 0;<br />
82: int<br />
178: }<br />
83: init_NIST_Rat43( int N, double *obs, double *cond,<br />
179:<br />
84: double *a, unsigned char *a_flag, FILE *logfile) 180: /*---------------------------------------------------------------<br />
85: {<br />
181: * init_NIST_BoxBOD()<br />
86: /* set 1 */<br />
182: * f(x|a) = a1 * (1 - exp( -a2 * x) )<br />
87: if (!a_flag[0]) a[0] = 100;<br />
183: *--------------------------------------------------------------*/<br />
88: if (!a_flag[1]) a[1] = 10;<br />
184: int<br />
89: if (!a_flag[2]) a[2] = 1;<br />
185: init_NIST_BoxBOD( int N, double *obs, double *cond,<br />
90: if (!a_flag[3]) a[3] = 1;<br />
186: double *a, unsigned char *a_flag, FILE *logfile)<br />
91:<br />
187: {<br />
92: return 0;<br />
188: int i, itmp;<br />
93: }<br />
189: double mean, maxval;<br />
94:<br />
190:<br />
95: /*--------------------------------------------------------------- 191: itmp = MAX( 0, MIN( 5, N));<br />
96: * init_NIST_Rat42()<br />
192:<br />
97: * f(x|a) = a1 / (1 + exp(a2 - a3*x))<br />
193: /* estimation of a1 = head of function */<br />
98: *--------------------------------------------------------------*/ 194: if (!a_flag[0])<br />
99: int<br />
195: {<br />
100: init_NIST_Rat42( int N, double *obs, double *cond,<br />
196: maxval = obs[0];<br />
101: double *a, unsigned char *a_flag, FILE *logfile) 197: for (i = 1; i < itmp; i++)<br />
102: {<br />
198: {<br />
103: /* set 1 */<br />
199: if (maxval < obs[i]) maxval = obs[i];<br />
104: if (!a_flag[0]) a[0] = 100;<br />
200: }<br />
105: if (!a_flag[1]) a[1] = 10;<br />
201: a[0] = maxval;<br />
106: if (!a_flag[2]) a[2] = 0.1;<br />
202: }<br />
107:<br />
203: /* estimation of a1*a2 = gradient at head of function */<br />
108: return 0;<br />
204: if (!a_flag[1])<br />
109: }<br />
205: {<br />
110:<br />
206: mean = 0;<br />
111: /*--------------------------------------------------------------- 207: for (i = 1; i < itmp; i++)<br />
112: * init_NIST_thurber()<br />
208: mean += (obs[i] - obs[i - 1]) / (cond[i] - cond[i - 1]);<br />
113: * f(x|a) =(a1 + a2*x + a3*x**2 + a4*x**3) /<br />
209: a[1] = mean / (itmp) / a[0];<br />
114: * (1 + a5*x + a6*x**2 + a7*x**3)<br />
210: /* use moderate value */<br />
115: *--------------------------------------------------------------*/ 211: if (a[1] > 2.) a[1] = 2.;<br />
116: int<br />
212: }<br />
117: init_NIST_thurber( int N, double *obs, double *cond, 213:<br />
118: double *a, unsigned char *a_flag, FILE *logfile) 214: return 0;<br />
119: {<br />
215: }<br />
120: /* set 1 */<br />
121: if (!a_flag[0]) a[0] = 1000;<br />
122: if (!a_flag[1]) a[1] = 1000;<br />
123: if (!a_flag[2]) a[2] = 400;<br />
124: if (!a_flag[3]) a[3] = 40;<br />
125: if (!a_flag[4]) a[4] = 0.7;<br />
126: if (!a_flag[5]) a[5] = 0.3;<br />
127: if (!a_flag[6]) a[6] = 0.03;<br />
128:<br />
129: return 0;<br />
130: }<br />
131:<br />
132: /*---------------------------------------------------------------<br />
133: * init_NIST_MGH09()<br />
134: * f(x|a) = a1 * (x**2 + a2*x) / (x*x + a3*x + a4)<br />
135: *--------------------------------------------------------------*/<br />
136: int<br />
137: init_NIST_MGH09( int N, double *obs, double *cond,<br />
138:<br />
139: {<br />
double *a, unsigned char *a_flag, FILE *logfile)<br />
140: /* set 1 */<br />
141: if (!a_flag[0]) a[0] = 25;<br />
142: if (!a_flag[1]) a[1] = 39;<br />
143: if (!a_flag[2]) a[2] = 41.5;<br />
144: if (!a_flag[3]) a[3] = 39;<br />
145:<br />
146: return 0;<br />
147: }<br />
148:<br />
149: /*---------------------------------------------------------------<br />
150: * init_NIST_MGH10()<br />
151: * f(x|a) = a1 * exp( a2 / (x+a3))<br />
152: *--------------------------------------------------------------*/<br />
153: int<br />
154: init_NIST_MGH10( int N, double *obs,<br />
155:<br />
156: {<br />
double *cond, double *a, unsigned char *a_flag, FILE *out)<br />
157: /* set 1 */<br />
158: if (!a_flag[0]) a[0] = 2;<br />
159: if (!a_flag[1]) a[1] = 400000;<br />
160: if (!a_flag[2]) a[2] = 25000;<br />
161:<br />
162: return 0;<br />
163: }<br />
164: /*---------------------------------------------------------------<br />
165: * init_NIST_Bennett5()<br />
166: * f(x|a) = a1 * (x+a2)^(-1/a3)<br />
167: *--------------------------------------------------------------*/<br />
168: int<br />
169: init_NIST_Bennett5( int N, double *obs,<br />
170:<br />
171: {<br />
double *cond, double *a, unsigned char *a_flag, FILE *out)
38 S The Source Code<br />
S.5 Matrix processing<br />
S.5.1 Utils<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: decomp_LU.c<br />
3: * Function....: LU decomposition<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2007<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include "matrix_utils.h"<br />
17: #include "errmsg.h"<br />
18: #define LITTLEBIT 1.0e-20;<br />
19:<br />
20: /*---------------------------------------------------------------<br />
21: * decomp_LU()<br />
22: *--------------------------------------------------------------*/<br />
23: int<br />
24: decomp_LU( double **normal, int M, int *indx, int *s)<br />
25: {<br />
26: char *rtn = "decomp_LU";<br />
27: int err = 0, i, imax = 0, j, k;<br />
28: double max_element, val, sum, tmp;<br />
29: double *row_scale = NULL; /* scaling of each row */<br />
30:<br />
31: /* allocate vector */<br />
32: row_scale = vector( M);<br />
33:<br />
34: *s = 1;<br />
35: /* examine input matrix */<br />
36: for (i = 0; i < M; i++)<br />
37: {<br />
38: max_element = 0.0;<br />
39: for (j = 0; j < M; j++)<br />
40: {<br />
41: if (( tmp = fabs( normal[i][j])) > max_element)<br />
42: max_element = tmp;<br />
43: }<br />
44: if (max_element == 0.0)<br />
45: {<br />
46: err = errmsg( ERR_IS_ZERO, rtn, "’max_element’", 0);<br />
47: goto endfunc;<br />
48: }<br />
49: row_scale[i] = 1.0 / max_element;<br />
50: }<br />
51: /* loop over columns of Crout’s method */<br />
52: for (j = 0; j < M; j++)<br />
53: {<br />
54: for (i = 0; i < j; i++)<br />
55: {<br />
56: sum = normal[i][j];<br />
57: for (k = 0; k < i; k++)<br />
58: sum -= normal[i][k] * normal[k][j];<br />
59: normal[i][j] = sum;<br />
60: }<br />
61: max_element = 0.0;<br />
62: for (i = j; i < M; i++)<br />
63: {<br />
64: sum = normal[i][j];<br />
65: for (k = 0; k < j; k++)<br />
66: {<br />
67: sum -= normal[i][k] * normal[k][j];<br />
68: }<br />
69: normal[i][j] = sum;<br />
70: /* is new pivot better than current best ? */<br />
71: if (( val = row_scale[i] * fabs( sum)) >= max_element)<br />
72: {<br />
73: max_element = val;<br />
74: imax = i;<br />
75: }<br />
76: }<br />
77: if (j != imax)<br />
78: {<br />
79: /* interchange of rows */<br />
80: for (k = 0; k < M; k++)<br />
81: {<br />
82: val = normal[imax][k];<br />
83: normal[imax][k] = normal[j][k];<br />
84: normal[j][k] = val;<br />
85: }<br />
86: *s = -( *s);<br />
87: /* interschange scale factors */<br />
88: row_scale[imax] = row_scale[j];<br />
89: }<br />
90: indx[j] = imax;<br />
91: if (normal[j][j] == 0.0)<br />
92: normal[j][j] = LITTLEBIT;<br />
93: if (j != (M - 1))<br />
94: {<br />
95: /* divide by the pivot element */<br />
96: val = 1.0 / (normal[j][j]);<br />
97: for (i = j + 1; i < M; i++)<br />
98: normal[i][j] *= val;<br />
99: }<br />
100: /* next column in reduction */<br />
101: }<br />
102:<br />
103: endfunc:<br />
104: free_vector( &row_scale);<br />
105: return err;<br />
106: }<br />
107:<br />
108: /*---------------------------------------------------------------<br />
109: * backsub_LU()<br />
110: *--------------------------------------------------------------*/<br />
111: void<br />
112: backsub_LU( double **lu, int N, int *indx, double back[])<br />
113: {<br />
114: int i, ii, idx, j;<br />
115: double sum;<br />
116:<br />
117: ii = -1;<br />
118: for (i = 0; i < N; i++)<br />
119: {<br />
120: idx = indx[i];<br />
121: sum = back[idx];<br />
122: back[idx] = back[i];<br />
123: if (ii >= 0.)<br />
124: {<br />
125: for (j = ii; j = 0; i--)<br />
133: {<br />
134: sum = back[i];<br />
135: for (j = i + 1; j < N; j++)<br />
136: sum -= lu[i][j] * back[j];<br />
137: back[i] = sum / lu[i][i];<br />
138: }<br />
139: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: svd_inversion.c<br />
3: * Function....: matrix inversion via SVD<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 18.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include "errmsg.h"<br />
18: #include "matrix_utils.h"<br />
19: #include "macros.h"<br />
20: #include "prototypes.h"<br />
21: #include "functions.h"<br />
22:<br />
23: /*---------------------------------------------------------------<br />
24: * svd_inversion()<br />
25: *<br />
26: *--------------------------------------------------------------*/<br />
27: int<br />
28: svd_inversion( int M, double **normal, double **normal_i, FILE *out)<br />
29: {<br />
30: char *rtn = "svd_inversion";<br />
31: int i, j, err = 0;<br />
32: double thresh, smax;<br />
33: double **tmpmat = NULL; /* temporary matrix */<br />
34: double *s = NULL; /* singular values */<br />
35: double **V = NULL; /* V matrix */<br />
36:<br />
37: V = matrix( M, M); /* V matrix for SVD */<br />
38: s = vector( M); /* singular values for SVD */<br />
39: tmpmat = matrix( M, M); /* temporary matrix */<br />
40:<br />
41: err = singvaldec( normal, M, M, s, V);<br />
42: if (err)<br />
43: {<br />
44: free_matrix( &V);
S.5 Matrix processing 39<br />
45: free_vector( &s);<br />
46: free_matrix( &tmpmat);<br />
47: goto endfunc;<br />
48: }<br />
49:<br />
50: smax = 0.0;<br />
51: for (j = 0; j < M; j++)<br />
52: {<br />
53: if (s[j] > smax) smax = s[j];<br />
54: }<br />
55: if (smax < TOL_S2)<br />
56: {<br />
57: fprintf( stderr,<br />
58: "\n###\n### singular matrix, smax = %f",smax);<br />
59: fprintf( out,<br />
60: "\n###\n### singular matrix, smax = %f",smax);<br />
61:<br />
62: err = 1;<br />
63: goto endfunc;<br />
64: }<br />
65: else if (smax > 1.e+31)<br />
66: {<br />
67: fprintf( stderr,<br />
68: "\n###\n### degraded matrix, smax = %f",smax);<br />
69: fprintf( out,<br />
70: "\n###\n### degraded matrix, smax = %f",smax);<br />
71: err = 1;<br />
72: goto endfunc;<br />
73: }<br />
74:<br />
75: thresh = MIN( TOL_S * smax, TOL_S);<br />
76:<br />
77: /* invert singular values */<br />
78: for (j = 0; j < M; j++)<br />
79: {<br />
80: /* abs_b)<br />
33: {<br />
34: dval = abs_b / abs_a;<br />
35: val = abs_a * sqrt( 1.0 + dval * dval);<br />
36: return val;<br />
37: }<br />
38: else<br />
39: {<br />
40: if (abs_b == 0.0)<br />
41: return 0.0;<br />
42: else<br />
43: {<br />
44: dval = abs_a / abs_b;<br />
45: val = abs_b * sqrt( 1.0 + dval * dval);<br />
46: return val;<br />
47: }<br />
48: }<br />
49: }<br />
50:<br />
51: /*---------------------------------------------------------------<br />
52: * singvaldec()<br />
53: * singular value decomposition<br />
54: * translation from http://www.pdas.com/programs/fmm.f90<br />
55: *--------------------------------------------------------------*/<br />
56: int<br />
57: singvaldec( double **a, int N, int M, double w[], double **v)<br />
58: {<br />
59: char *rtn = "singvaldec";<br />
60: int err = 0;<br />
61: int flag, i, its, j, jj, k, l = 0, nm;<br />
62: double anorm, c, f, g, h, s, scale, x, y, z, *rv1;<br />
63:<br />
64: rv1 = vector( M);<br />
65:<br />
66: /*<br />
67: * housholder reduction to bidiagonal form<br />
68: */<br />
69: g = scale = anorm = 0.0;<br />
70: for (i = 0; i < M; i++)<br />
71: {<br />
72: l = i + 1;<br />
73: assert( i >= 0);<br />
74: rv1[i] = scale * g;<br />
75: g = s = scale = 0.0;<br />
76: if (i < N)<br />
77: {<br />
78: for (k = i; k < N; k++)<br />
79: {<br />
80: scale += fabs( a[k][i]);<br />
81: }<br />
82: if (scale)<br />
83: {<br />
84: for (k = i; k < N; k++)<br />
85: {<br />
86: a[k][i] /= scale;<br />
87: s += a[k][i] * a[k][i];<br />
88: }<br />
89: f = a[i][i];<br />
90: g = -SIGN( sqrt( s), f);<br />
91: h = f * g - s;<br />
92: a[i][i] = f - g;<br />
93: for (j = l; j < M; j++)<br />
94: {<br />
95: s = 0.0;<br />
96: for (k = i; k < N; k++)<br />
97: {<br />
98: s += a[k][i] * a[k][j];<br />
99: }<br />
100: f = s / h;<br />
101: for (k = i; k < N; k++)<br />
102: a[k][j] += f * a[k][i];<br />
103: }<br />
104: for (k = i; k < N; k++)<br />
105: a[k][i] *= scale;<br />
106: }<br />
107: }<br />
108: w[i] = scale * g;<br />
109: g = s = scale = 0.0;<br />
110: if (i < N && i != M - 1)<br />
111: {<br />
112: for (k = l; k < M; k++)<br />
113: {<br />
114: scale += fabs( a[i][k]);<br />
115: }<br />
116: if (scale)<br />
117: {<br />
118: for (k = l; k < M; k++)<br />
119: {<br />
120: a[i][k] /= scale;<br />
121: s += a[i][k] * a[i][k];<br />
122: }<br />
123: f = a[i][l];<br />
124: g = -SIGN( sqrt( s), f);<br />
125: h = f * g - s;<br />
126: a[i][l] = f - g;
40 S The Source Code<br />
127: for (k = l; k < M; k++)<br />
128: {<br />
129: assert( k >= 0);<br />
130: rv1[k] = a[i][k] / h;<br />
131: }<br />
132: for (j = l; j < N; j++)<br />
133: {<br />
134: for (s = 0.0, k = l; k < M; k++)<br />
135: s += a[j][k] * a[i][k];<br />
136: for (k = l; k < M; k++)<br />
137: a[j][k] += s * rv1[k];<br />
138: }<br />
139: for (k = l; k < M; k++)<br />
140: a[i][k] *= scale;<br />
141: }<br />
142: }<br />
143: anorm = MAX( anorm, (fabs( w[i]) + fabs( rv1[i])));<br />
144: }<br />
145:<br />
146: /*<br />
147: * accumulation of right-h<strong>and</strong> transformations<br />
148: */<br />
149: for (i = M - 1; i >= 0; i--)<br />
150: {<br />
151: if (i < M - 1)<br />
152: {<br />
153: if (g)<br />
154: {<br />
155: for (j = l; j < M; j++)<br />
156: {<br />
157: v[j][i] = (a[i][j] / a[i][l]) / g;<br />
158: }<br />
159: for (j = l; j < M; j++)<br />
160: {<br />
161: for (s = 0.0, k = l; k < M; k++)<br />
162: s += a[i][k] * v[k][j];<br />
163: for (k = l; k < M; k++)<br />
164: v[k][j] += s * v[k][i];<br />
165: }<br />
166: }<br />
167: for (j = l; j < M; j++)<br />
168: v[i][j] = v[j][i] = 0.0;<br />
169: }<br />
170: v[i][i] = 1.0;<br />
171: assert( i >= 0);<br />
172: g = rv1[i];<br />
173: l = i;<br />
174: }<br />
175:<br />
176: /*<br />
177: * accumulation of left-h<strong>and</strong> transformations<br />
178: */<br />
179: for (i = MIN( N, M) - 1; i >= 0; i--)<br />
180: {<br />
181: l = i + 1;<br />
182: g = w[i];<br />
183: for (j = l; j < M; j++)<br />
184: a[i][j] = 0.0;<br />
185: if (g)<br />
186: {<br />
187: g = 1.0 / g;<br />
188: for (j = l; j < M; j++)<br />
189: {<br />
190: for (s = 0.0, k = l; k < N; k++)<br />
191: s += a[k][i] * a[k][j];<br />
192: f = (s / a[i][i]) * g;<br />
193: for (k = i; k < N; k++)<br />
194: a[k][j] += f * a[k][i];<br />
195: }<br />
196: for (j = i; j < N; j++)<br />
197: a[j][i] *= g;<br />
198: }<br />
199: else<br />
200: {<br />
201: for (j = i; j < N; j++)<br />
202: a[j][i] = 0.0;<br />
203: }<br />
204: ++a[i][i];<br />
205: }<br />
206:<br />
207: /*<br />
208: * diagonalization of the bidiagonal form<br />
209: */<br />
210: for (k = M - 1; k >= 0; k--) /* loop over singular values */<br />
211: {<br />
212: assert( k >= 0);<br />
213: for (its = 0; its < 30; its++) /* loop over allowed<br />
214: iterations */<br />
215: {<br />
216: flag = 1;<br />
217: for (l = k; l >= 0; l--) /* test for splitting */<br />
218: {<br />
219: nm = l - 1; /* note that rv1[1] is always zero */<br />
220: if (( double)( fabs( rv1[l]) + anorm) == anorm)<br />
221: {<br />
222: flag = 0;<br />
223: break;<br />
224: }<br />
225: if (( double)( fabs( w[nm]) + anorm) == anorm)<br />
226: break;<br />
227: }<br />
228: if (flag)<br />
229: {<br />
230: assert( l >= 0);<br />
231: c = 0.0; /* cancellation of rv1[l] if l greater than 1 */<br />
232: s = 1.0;<br />
233: for (i = l; i < k; i++)<br />
234: {<br />
235: f = s * rv1[i];<br />
236: rv1[i] = c * rv1[i];<br />
237: if (( double)( fabs( f) + anorm) == anorm)<br />
238: break;<br />
239: g = w[i];<br />
240: h = euclid_dist( f, g);<br />
241: w[i] = h;<br />
242: h = 1.0 / h;<br />
243: c = g * h;<br />
244: s = -f * h;<br />
245: for (j = 0; j < N; j++)<br />
246: {<br />
247: y = a[j][nm];<br />
248: z = a[j][i];<br />
249: a[j][nm] = y * c + z * s;<br />
250: a[j][i] = z * c - y * s;<br />
251: }<br />
252: }<br />
253: }<br />
254: /* test for convergence */<br />
255: z = w[k];<br />
256: if (l == k)<br />
257: {<br />
258: if (z < 0.0) /* singular value is made non-negative */<br />
259: {<br />
260: w[k] = -z;<br />
261: for (j = 0; j < M; j++)<br />
262: v[j][k] = -v[j][k];<br />
263: }<br />
264: break;<br />
265: }<br />
266: if (its == 30)<br />
267: {<br />
268: fprintf( stderr,<br />
269: "\n%s: No convergence after 30 iterations(SVD)\n", rtn);<br />
270: err = 57;<br />
271: goto endfunc;<br />
272: }<br />
273: /* shift from bottom 2 by 2 minor */<br />
274: x = w[l];<br />
275: nm = k - 1;<br />
276: y = w[nm];<br />
277: g = rv1[nm];<br />
278: assert( k >= 0);<br />
279: h = rv1[k];<br />
280: f =<br />
281: ( (y - z) * (y + z) + (g - h) * (g +<br />
282: h)) / (2.0 * h * y);<br />
283: g = euclid_dist( f, 1.0);<br />
284: f =<br />
285: ( (x - z) * (x + z) + h * (( y / (f + SIGN( g,<br />
286: f))) - h)) / x;<br />
287:<br />
288: /* next qr transformation */<br />
289: c = s = 1.0;<br />
290: for (j = l; j = 0);<br />
294: g = rv1[i];<br />
295: y = w[i];<br />
296: h = s * g;<br />
297: g = c * g;<br />
298: z = euclid_dist( f, h);<br />
299: rv1[j] = z;<br />
300: c = f / z;<br />
301: s = h / z;<br />
302: f = x * c + g * s;<br />
303: g = g * c - x * s;<br />
304: h = y * s;<br />
305: y *= c;<br />
306: for (jj = 0; jj < M; jj++)<br />
307: {<br />
308: x = v[jj][j];<br />
309: z = v[jj][i];<br />
310: v[jj][j] = x * c + z * s;<br />
311: v[jj][i] = z * c - x * s;<br />
312: }<br />
313: z = euclid_dist( f, h);<br />
314: w[j] = z;<br />
315: if (z) /* rotation can be arbitrary if z is zero */<br />
316: {<br />
317: z = 1.0 / z;<br />
318: c = f * z;
S.5 Matrix processing 41<br />
319: s = h * z;<br />
320: }<br />
321: f = c * g + s * y;<br />
322: x = c * y - s * g;<br />
323: for (jj = 0; jj < N; jj++)<br />
324: {<br />
325: y = a[jj][j];<br />
326: z = a[jj][i];<br />
327: a[jj][j] = y * c + z * s;<br />
328: a[jj][i] = z * c - y * s;<br />
329: }<br />
330: }<br />
331: assert( l >= 0);<br />
332: assert( k >= 0);<br />
333: rv1[l] = 0.0;<br />
334: rv1[k] = f;<br />
335: w[k] = x;<br />
336: }<br />
337: }<br />
338:<br />
339: endfunc:<br />
340: free_vector( &rv1);<br />
341: return err;<br />
342: }<br />
S.5.2 Allocation <strong>and</strong> matrix h<strong>and</strong>ling<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: matrix_utils.c<br />
3: * Function....: special functions for matrices<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2009<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include "errmsg.h"<br />
16:<br />
17: /*---------------------------------------------------------------<br />
18: * vector()<br />
19: * create a vector with subscript range v[0..N-1]<br />
20: *--------------------------------------------------------------*/<br />
21: double *vector( long N)<br />
22: {<br />
23: int err = 0;<br />
24: double *v;<br />
25:<br />
26: v = (double*)calloc( N, sizeof(double));<br />
27: if (v == NULL)<br />
28: {<br />
29: err = errmsg( ERR_ALLOCATE, "vector", " ", 0);<br />
30: exit( err);<br />
31: }<br />
32: return v;<br />
33: }<br />
34:<br />
35: /*---------------------------------------------------------------<br />
36: * fvector()<br />
37: * create a vector with subscript range v[0..N-1]<br />
38: *--------------------------------------------------------------*/<br />
39: float *fvector( long N)<br />
40: {<br />
41: int err = 0;<br />
42: float *v;<br />
43:<br />
44: v = (float*)calloc( N, sizeof(float));<br />
45: if (v == NULL)<br />
46: {<br />
47: err = errmsg( ERR_ALLOCATE, "vector", " ", 0);<br />
48: exit( err);<br />
49: }<br />
50: return v;<br />
51: }<br />
52:<br />
53: /*---------------------------------------------------------------<br />
54: * ivector()<br />
55: * create a vector with subscript range v[0..N-1]<br />
56: *--------------------------------------------------------------*/<br />
57: int *<br />
58: ivector( long N)<br />
59: {<br />
60: int err = 0;<br />
61: int *v;<br />
62:<br />
63: v = (int*)calloc( N, sizeof(int));<br />
64: if (v == NULL)<br />
65: {<br />
66: err = errmsg( ERR_ALLOCATE, "vector", " ", 0);<br />
67: exit( err);<br />
68: }<br />
69: return v;<br />
70: }<br />
71:<br />
72: /*---------------------------------------------------------------<br />
73: * matrix()<br />
74: * create a matrix with subscript range v[0..M-1][0..N-1]<br />
75: *--------------------------------------------------------------*/<br />
76: double **<br />
77: matrix( long N, long M)<br />
78: {<br />
79: int err = 0;<br />
80: long i;<br />
81: double **m;<br />
82:<br />
83: /* allocate pointers to rows */<br />
84: m = (double **)malloc( N * sizeof(double*));<br />
85: if (m == NULL)<br />
86: {<br />
87: err = errmsg( ERR_ALLOCATE, "matrix", " ", 0);<br />
88: exit( err);<br />
89: }<br />
90:<br />
91: /* allocate rows <strong>and</strong> set pointers to them */<br />
92: m[0] = (double*)calloc( M * N, sizeof(double));<br />
93: if (m[0] == NULL)<br />
94: {<br />
95: err = errmsg( ERR_ALLOCATE, "matrix", " ", 0);<br />
96: exit( err);<br />
97: }<br />
98:<br />
99: for (i = 1; i < N; i++)<br />
100: {<br />
101: m[i] = m[i - 1] + M;<br />
102: }<br />
103:<br />
104: /* return pointer to array of pointers to rows */<br />
105: return m;<br />
106: }<br />
107: /*---------------------------------------------------------------<br />
108: * fmatrix()<br />
109: * create a matrix with subscript range v[0..M-1][0..N-1]<br />
110: *--------------------------------------------------------------*/<br />
111: float **<br />
112: fmatrix( long N, long M)<br />
113: {<br />
114: int err = 0;<br />
115: long i;<br />
116: float **m;<br />
117:<br />
118: /* allocate pointers to rows */<br />
119: m = (float **)malloc( N * sizeof(float*));<br />
120: if (m == NULL)<br />
121: {<br />
122: err = errmsg( ERR_ALLOCATE, "matrix", " ", 0);<br />
123: exit( err);<br />
124: }<br />
125:<br />
126: /* allocate rows <strong>and</strong> set pointers to them */<br />
127: m[0] = (float*)calloc( M * N, sizeof(float));<br />
128: if (m[0] == NULL)<br />
129: {<br />
130: err = errmsg( ERR_ALLOCATE, "matrix", " ", 0);<br />
131: exit( err);<br />
132: }<br />
133:<br />
134: for (i = 1; i < N; i++)<br />
135: {<br />
136: m[i] = m[i - 1] + M;<br />
137: }<br />
138:<br />
139: /* return pointer to array of pointers to rows */<br />
140: return m;<br />
141: }<br />
142:<br />
143: /*---------------------------------------------------------------<br />
144: * free a vector allocated by vector()<br />
145: *--------------------------------------------------------------*/<br />
146: void<br />
147: free_vector( double *v[])<br />
148: {<br />
149: if (*v != NULL)<br />
150: free( *v);<br />
151: *v = NULL;<br />
152: }<br />
153:<br />
154: /*---------------------------------------------------------------<br />
155: * free a vector allocated by vector()<br />
156: *--------------------------------------------------------------*/<br />
157: void<br />
158: free_ivector( int *v[])<br />
159: {<br />
160: if (*v != NULL)<br />
161: free( *v);
42 S The Source Code<br />
162: *v = NULL;<br />
258: a[1][1] * (<br />
163: }<br />
259: a[2][2] * (-a[3][0]*a[0][3]*a[4][4] - a[3][3]*a[4][0]*a[0][4]<br />
164:<br />
260: +a[4][0]*a[0][3]*a[3][4] + a[4][3]*a[3][0]*a[0][4] ) +<br />
165: /*--------------------------------------------------------------- 261: a[3][0] * (+a[0][2]*a[2][3]*a[4][4] + a[0][3]*a[4][2]*a[2][4] ) +<br />
166: * free a matrix allocated by matrix()<br />
262: a[3][2] * (+a[2][0]*a[0][3]*a[4][4] + a[2][3]*a[4][0]*a[0][4] ) +<br />
167: *--------------------------------------------------------------*/ 263: a[3][3] * (-a[2][0]*a[0][2]*a[4][4] + a[4][0]*a[0][2]*a[2][4]<br />
168: void<br />
264: +a[4][2]*a[2][0]*a[0][4] ) +<br />
169: free_matrix( double **m[])<br />
265: a[4][0] * (-a[0][2]*a[2][3]*a[3][4] - a[0][3]*a[3][2]*a[2][4] ) +<br />
170: {<br />
266: a[4][2] * (-a[2][0]*a[0][3]*a[3][4] - a[2][3]*a[3][0]*a[0][4] ) +<br />
171:<br />
267: a[4][3] * (+a[2][0]*a[0][2]*a[3][4] - a[3][0]*a[0][2]*a[2][4]<br />
172: if (*m != NULL)<br />
268: -a[3][2]*a[2][0]*a[0][4] )<br />
173: {<br />
269: ) +<br />
174: if (*m[0] != NULL)<br />
270: a[2][2] * (<br />
175: free( *m[0]);<br />
271: a[3][0] * (+a[0][1]*a[1][3]*a[4][4] + a[0][3]*a[4][1]*a[1][4] ) +<br />
176: free( *m);<br />
272: a[3][1] * (+a[1][0]*a[0][3]*a[4][4] + a[1][3]*a[4][0]*a[0][4] ) +<br />
177: }<br />
273: a[3][3] * (-a[1][0]*a[0][1]*a[4][4] + a[4][0]*a[0][1]*a[1][4]<br />
178: *m = NULL;<br />
274: +a[4][1]*a[1][0]*a[0][4] ) +<br />
179: }<br />
275: a[4][0] * (-a[0][1]*a[1][3]*a[3][4] - a[0][3]*a[3][1]*a[1][4] ) +<br />
180:<br />
276: a[4][1] * (-a[1][0]*a[0][3]*a[3][4] - a[1][3]*a[3][0]*a[0][4] ) +<br />
181: /*--------------------------------------------------------------- 277: a[4][3] * (+a[1][0]*a[0][1]*a[3][4] - a[3][0]*a[0][1]*a[1][4]<br />
182: * free a matrix allocated by fmatrix()<br />
278: -a[3][1]*a[1][0]*a[0][4] )<br />
183: *--------------------------------------------------------------*/ 279: ) +<br />
184: void<br />
280: a[3][0] * (<br />
185: free_fmatrix( float **m[])<br />
281: a[0][1] * (-a[1][2]*a[2][3]*a[4][4] - a[1][3]*a[4][2]*a[2][4] ) +<br />
186: {<br />
282: a[0][2] * (-a[2][1]*a[1][3]*a[4][4] - a[2][3]*a[4][1]*a[1][4] ) +<br />
187:<br />
283: a[0][3] * (+a[2][1]*a[1][2]*a[4][4] - a[4][1]*a[1][2]*a[2][4]<br />
188: if (*m != NULL)<br />
284: -a[4][2]*a[2][1]*a[1][4] )<br />
189: {<br />
285: ) +<br />
190: if (*m[0] != NULL)<br />
286: a[3][1] * (<br />
191: free( *m[0]);<br />
287: a[1][0] * (-a[0][2]*a[2][3]*a[4][4] - a[0][3]*a[4][2]*a[2][4] ) +<br />
192: free( *m);<br />
288: a[1][2] * (-a[2][0]*a[0][3]*a[4][4] - a[2][3]*a[4][0]*a[0][4] ) +<br />
193: }<br />
289: a[1][3] * (+a[2][0]*a[0][2]*a[4][4] - a[4][0]*a[0][2]*a[2][4]<br />
194: *m = NULL;<br />
290: -a[4][2]*a[2][0]*a[0][4] )<br />
195: }<br />
291: ) +<br />
196:<br />
292: a[3][2] * (<br />
197: /*--------------------------------------------------------------- 293: a[2][0] * (-a[0][1]*a[1][3]*a[4][4] - a[0][3]*a[4][1]*a[1][4] ) +<br />
198: * determinant_2x2()<br />
294: a[2][1] * (-a[1][0]*a[0][3]*a[4][4] - a[1][3]*a[4][0]*a[0][4] ) +<br />
199: *--------------------------------------------------------------*/ 295: a[2][3] * (+a[1][0]*a[0][1]*a[4][4] - a[4][0]*a[0][1]*a[1][4]<br />
200: double<br />
296: -a[4][1]*a[1][0]*a[0][4] )<br />
201: determinant_2x2( double **a)<br />
297: ) +<br />
202: {<br />
298: a[3][3] * (<br />
203: return a[0][0] * a[1][1] - a[0][1] * a[1][0];<br />
299: a[2][0] * (+a[0][1]*a[1][2]*a[4][4] + a[0][2]*a[4][1]*a[1][4] ) +<br />
204: }<br />
300: a[2][1] * (+a[1][0]*a[0][2]*a[4][4] + a[1][2]*a[4][0]*a[0][4] ) +<br />
205:<br />
301: a[4][0] * (-a[0][1]*a[1][2]*a[2][4] - a[0][2]*a[2][1]*a[1][4] ) +<br />
206: /*--------------------------------------------------------------- 302: a[4][1] * (-a[1][0]*a[0][2]*a[2][4] - a[1][2]*a[2][0]*a[0][4] ) +<br />
207: * determinant_3x3()<br />
303: a[4][2] * (+a[1][0]*a[0][1]*a[2][4] - a[2][0]*a[0][1]*a[1][4]<br />
208: *--------------------------------------------------------------*/ 304: -a[2][1]*a[1][0]*a[0][4] )<br />
209: double<br />
305: ) +<br />
210: determinant_3x3( double **a)<br />
306: a[4][0] * (<br />
211: {<br />
307: a[0][1] * (+a[1][2]*a[2][3]*a[3][4] + a[1][3]*a[3][2]*a[2][4] ) +<br />
212: /* The numerical stability depends on the order of operations. 308: a[0][2] * (+a[2][1]*a[1][3]*a[3][4] + a[2][3]*a[3][1]*a[1][4] ) +<br />
213: * The discrimination below works for the mentioned data sets 309: a[0][3] * (-a[2][1]*a[1][2]*a[3][4] + a[3][1]*a[1][2]*a[2][4]<br />
214: * in Release mode, but should evaluated in more detail 310: +a[3][2]*a[2][1]*a[1][4] )<br />
215: */<br />
311: ) +<br />
216: if (fabs(a[0][0]) < 1)<br />
312: a[4][1] * (<br />
217: return<br />
313: a[1][0] * (+a[0][2]*a[2][3]*a[3][4] + a[0][3]*a[3][2]*a[2][4] ) +<br />
218: /* better performance for Eckerle4.dat */<br />
314: a[1][2] * (+a[2][0]*a[0][3]*a[3][4] + a[2][3]*a[3][0]*a[0][4] ) +<br />
219: (<br />
315: a[1][3] * (-a[2][0]*a[0][2]*a[3][4] + a[3][0]*a[0][2]*a[2][4]<br />
220: a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) - 316: +a[3][2]*a[2][0]*a[0][4] )<br />
221: a[0][1] * (a[1][0] * a[2][2] + a[2][0] * a[1][2]) 317: ) +<br />
222: ) +<br />
318: a[4][2] * (<br />
223: a[0][2] * (a[1][0] * a[2][1] - a[2][0] * a[1][1]); 319: a[2][0] * (+a[0][1]*a[1][3]*a[3][4] + a[0][3]*a[3][1]*a[1][4] ) +<br />
224: else<br />
320: a[2][1] * (+a[1][0]*a[0][3]*a[3][4] + a[1][3]*a[3][0]*a[0][4] ) +<br />
225: return<br />
321: a[2][3] * (-a[1][0]*a[0][1]*a[3][4] + a[3][1]*a[1][0]*a[0][4]<br />
226: /* better performance for MGH10.dat*/<br />
322: +a[3][0]*a[0][1]*a[1][4] )<br />
227: a[0][0] * a[1][1] * a[2][2] - a[0][0] * a[2][1] * a[1][2] - 323: ) +<br />
228: a[0][1] * a[1][0] * a[2][2] + a[0][1] * a[2][0] * a[1][2] + 324: a[4][3] * (<br />
229: a[0][2] * a[1][0] * a[2][1] - a[0][2] * a[2][0] * a[1][1]; 325: a[2][0] * (-a[0][1]*a[1][2]*a[3][4] - a[0][2]*a[3][1]*a[1][4] ) +<br />
230: }<br />
326: a[2][1] * (-a[1][0]*a[0][2]*a[3][4] - a[1][2]*a[3][0]*a[0][4] ) +<br />
231:<br />
327: a[3][0] * (+a[0][1]*a[1][2]*a[2][4] + a[0][2]*a[2][1]*a[1][4] )+<br />
232: /*--------------------------------------------------------------- 328: a[3][1] * (+a[1][0]*a[0][2]*a[2][4] + a[1][2]*a[2][0]*a[0][4] )+<br />
233: * inverse_5x5()<br />
329: a[3][2] * (-a[1][0]*a[0][1]*a[2][4] + a[2][0]*a[0][1]*a[1][4]<br />
234: * get the inverse of a square 5x5 matrix<br />
330: +a[2][1]*a[1][0]*a[0][4] )<br />
235: * returns determinant<br />
331: );<br />
236: *--------------------------------------------------------------*/ 332:<br />
237: double<br />
333: b[0][0] = -(<br />
238: inverse_5x5( double **a, double **b)<br />
334: a[1][1] * (<br />
239: {<br />
335: a[2][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
240: double det;<br />
336: a[2][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
241:<br />
337: a[2][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
242: det =<br />
338: )+<br />
243: a[0][0] * (<br />
339: a[1][2] * (<br />
244: a[1][1] * (+a[2][2]*a[3][3]*a[4][4] - a[2][2]*a[4][3]*a[3][4] 340: a[2][1] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
245: -a[3][2]*a[2][3]*a[4][4] - a[3][3]*a[4][2]*a[2][4] 341: a[2][3] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
246: +a[4][2]*a[2][3]*a[3][4] + a[4][3]*a[3][2]*a[2][4] ) + 342: a[2][4] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1])<br />
247: a[2][2] * (-a[3][1]*a[1][3]*a[4][4] - a[3][3]*a[4][1]*a[1][4] 343: )+<br />
248: +a[4][1]*a[1][3]*a[3][4] + a[4][3]*a[3][1]*a[1][4] ) + 344: a[1][3] * (<br />
249: a[3][1] * (+a[1][2]*a[2][3]*a[4][4] + a[1][3]*a[4][2]*a[2][4] ) + 345: a[2][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
250: a[3][2] * (+a[2][1]*a[1][3]*a[4][4] + a[2][3]*a[4][1]*a[1][4] ) + 346: a[2][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
251: a[3][3] * (-a[2][1]*a[1][2]*a[4][4] + a[4][1]*a[1][2]*a[2][4] 347: a[2][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
252: +a[4][2]*a[2][1]*a[1][4] ) +<br />
348: )+<br />
253: a[4][1] * (-a[1][2]*a[2][3]*a[3][4] - a[1][3]*a[3][2]*a[2][4] ) + 349: a[1][4] * (<br />
254: a[4][2] * (-a[2][1]*a[1][3]*a[3][4] - a[2][3]*a[3][1]*a[1][4] ) + 350: a[2][1] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
255: a[4][3] * (+a[2][1]*a[1][2]*a[3][4] - a[3][1]*a[1][2]*a[2][4] 351: a[2][2] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
256: -a[3][2]*a[2][1]*a[1][4] )<br />
352: a[2][3] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1])<br />
257: ) +<br />
353: ));
S.5 Matrix processing 43<br />
354:<br />
355: b[0][1] =<br />
356: a[0][1] * (<br />
357: a[2][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
358: a[2][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
359: a[2][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
360: )+<br />
361: a[0][2] * (<br />
362: a[2][1] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
363: a[2][3] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
364: a[2][4] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1])<br />
365: )+<br />
366: a[0][3] * (<br />
367: a[2][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
368: a[2][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
369: a[2][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
370: )+<br />
371: a[0][4] * (<br />
372: a[2][1] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
373: a[2][2] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
374: a[2][3] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1])<br />
375: );<br />
376:<br />
377: b[0][2] =<br />
378: a[1][1] * (<br />
379: a[0][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
380: a[0][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
381: a[0][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
382: )+<br />
383: a[1][2] * (<br />
384: a[0][1] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
385: a[0][3] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
386: a[0][4] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1])<br />
387: )+<br />
388: a[1][3] * (<br />
389: a[0][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
390: a[0][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
391: a[0][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
392: )+<br />
393: a[1][4] * (<br />
394: a[0][1] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
395: a[0][2] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
396: a[0][3] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1])<br />
397: );<br />
398:<br />
399: b[0][3] = +(<br />
400: a[1][1] * (<br />
401: a[2][2] * (-a[0][3]*a[4][4] + a[0][4]*a[4][3]) +<br />
402: a[2][3] * (+a[0][2]*a[4][4] - a[0][4]*a[4][2]) +<br />
403: a[2][4] * (-a[0][2]*a[4][3] + a[0][3]*a[4][2])<br />
404: )+<br />
405: a[1][2] * (<br />
406: a[2][1] * (+a[0][3]*a[4][4] - a[0][4]*a[4][3]) +<br />
407: a[2][3] * (-a[0][1]*a[4][4] + a[0][4]*a[4][1]) +<br />
408: a[2][4] * (+a[0][1]*a[4][3] - a[0][3]*a[4][1])<br />
409: )+<br />
410: a[1][3] * (<br />
411: a[2][1] * (-a[0][2]*a[4][4] + a[0][4]*a[4][2]) +<br />
412: a[2][2] * (+a[0][1]*a[4][4] - a[0][4]*a[4][1]) +<br />
413: a[2][4] * (-a[0][1]*a[4][2] + a[0][2]*a[4][1])<br />
414: )+<br />
415: a[1][4] * (<br />
416: a[2][1] * (+a[0][2]*a[4][3] - a[0][3]*a[4][2]) +<br />
417: a[2][2] * (-a[0][1]*a[4][3] + a[0][3]*a[4][1]) +<br />
418: a[2][3] * (+a[0][1]*a[4][2] - a[0][2]*a[4][1])<br />
419: ));<br />
420:<br />
421: b[0][4] =<br />
422: a[1][1] * (<br />
423: a[2][2] * (-a[3][3]*a[0][4] + a[3][4]*a[0][3]) +<br />
424: a[2][3] * (+a[3][2]*a[0][4] - a[3][4]*a[0][2]) +<br />
425: a[2][4] * (-a[3][2]*a[0][3] + a[3][3]*a[0][2])<br />
426: )+<br />
427: a[1][2] * (<br />
428: a[2][1] * (+a[3][3]*a[0][4] - a[3][4]*a[0][3]) +<br />
429: a[2][3] * (-a[3][1]*a[0][4] + a[3][4]*a[0][1]) +<br />
430: a[2][4] * (+a[3][1]*a[0][3] - a[3][3]*a[0][1])<br />
431: )+<br />
432: a[1][3] * (<br />
433: a[2][1] * (-a[3][2]*a[0][4] + a[3][4]*a[0][2]) +<br />
434: a[2][2] * (+a[3][1]*a[0][4] - a[3][4]*a[0][1]) +<br />
435: a[2][4] * (-a[3][1]*a[0][2] + a[3][2]*a[0][1])<br />
436: )+<br />
437: a[1][4] * (<br />
438: a[2][1] * (+a[3][2]*a[0][3] - a[3][3]*a[0][2]) +<br />
439: a[2][2] * (-a[3][1]*a[0][3] + a[3][3]*a[0][1]) +<br />
440: a[2][3] * (+a[3][1]*a[0][2] - a[3][2]*a[0][1])<br />
441: );<br />
442: /* second row */<br />
443: b[1][0] =<br />
444: a[1][0] * (<br />
445: a[2][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
446: a[2][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
447: a[2][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
448: )+<br />
449: a[1][2] * (<br />
450: a[2][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
451: a[2][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
452: a[2][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
453: )+<br />
454: a[1][3] * (<br />
455: a[2][0] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
456: a[2][2] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
457: a[2][4] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0])<br />
458: )+<br />
459: a[1][4] * (<br />
460: a[2][0] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
461: a[2][2] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
462: a[2][3] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
463: );<br />
464:<br />
465: b[1][1] = -(<br />
466: a[0][0] * (<br />
467: a[2][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
468: a[2][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
469: a[2][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
470: )+<br />
471: a[0][2] * (<br />
472: a[2][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
473: a[2][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
474: a[2][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
475: )+<br />
476: a[0][3] * (<br />
477: a[2][0] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
478: a[2][2] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
479: a[2][4] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0])<br />
480: )+<br />
481: a[0][4] * (<br />
482: a[2][0] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
483: a[2][2] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
484: a[2][3] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
485: ));<br />
486:<br />
487: b[1][2] = +(<br />
488: a[0][0] * (<br />
489: a[1][2] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
490: a[1][3] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
491: a[1][4] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
492: )+<br />
493: a[0][2] * (<br />
494: a[1][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
495: a[1][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
496: a[1][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
497: )+<br />
498: a[0][3] * (<br />
499: a[1][0] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
500: a[1][2] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
501: a[1][4] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0])<br />
502: )+<br />
503: a[0][4] * (<br />
504: a[1][0] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
505: a[1][2] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
506: a[1][3] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
507: ));<br />
508:<br />
509: b[1][3] = -(<br />
510: a[0][0] * (<br />
511: a[1][2] * (-a[2][3]*a[4][4] + a[2][4]*a[4][3]) +<br />
512: a[1][3] * (+a[2][2]*a[4][4] - a[2][4]*a[4][2]) +<br />
513: a[1][4] * (-a[2][2]*a[4][3] + a[2][3]*a[4][2])<br />
514: )+<br />
515: a[0][2] * (<br />
516: a[1][0] * (+a[2][3]*a[4][4] - a[2][4]*a[4][3]) +<br />
517: a[1][3] * (-a[2][0]*a[4][4] + a[2][4]*a[4][0]) +<br />
518: a[1][4] * (+a[2][0]*a[4][3] - a[2][3]*a[4][0])<br />
519: )+<br />
520: a[0][3] * (<br />
521: a[1][0] * (-a[2][2]*a[4][4] + a[2][4]*a[4][2]) +<br />
522: a[1][2] * (+a[2][0]*a[4][4] - a[2][4]*a[4][0]) +<br />
523: a[1][4] * (-a[2][0]*a[4][2] + a[2][2]*a[4][0])<br />
524: )+<br />
525: a[0][4] * (<br />
526: a[1][0] * (+a[2][2]*a[4][3] - a[2][3]*a[4][2]) +<br />
527: a[1][2] * (-a[2][0]*a[4][3] + a[2][3]*a[4][0]) +<br />
528: a[1][3] * (+a[2][0]*a[4][2] - a[2][2]*a[4][0])<br />
529: ));<br />
530:<br />
531: b[1][4] = +(<br />
532: a[0][0] * (<br />
533: a[1][2] * (-a[2][3]*a[3][4] + a[2][4]*a[3][3]) +<br />
534: a[1][3] * (+a[2][2]*a[3][4] - a[2][4]*a[3][2]) +<br />
535: a[1][4] * (-a[2][2]*a[3][3] + a[2][3]*a[3][2])<br />
536: )+<br />
537: a[0][2] * (<br />
538: a[1][0] * (+a[2][3]*a[3][4] - a[2][4]*a[3][3]) +<br />
539: a[1][3] * (-a[2][0]*a[3][4] + a[2][4]*a[3][0]) +<br />
540: a[1][4] * (+a[2][0]*a[3][3] - a[2][3]*a[3][0])<br />
541: )+<br />
542: a[0][3] * (<br />
543: a[1][0] * (-a[2][2]*a[3][4] + a[2][4]*a[3][2]) +<br />
544: a[1][2] * (+a[2][0]*a[3][4] - a[2][4]*a[3][0]) +<br />
545: a[1][4] * (-a[2][0]*a[3][2] + a[2][2]*a[3][0])
44 S The Source Code<br />
546: )+<br />
547: a[0][4] * (<br />
548: a[1][0] * (+a[2][2]*a[3][3] - a[2][3]*a[3][2]) +<br />
549: a[1][2] * (-a[2][0]*a[3][3] + a[2][3]*a[3][0]) +<br />
550: a[1][3] * (+a[2][0]*a[3][2] - a[2][2]*a[3][0])<br />
551: ));<br />
552: /* third row */<br />
553: b[2][0] = -(<br />
554: a[1][0] * (<br />
555: a[2][1] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
556: a[2][3] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
557: a[2][4] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1])<br />
558: )+<br />
559: a[1][1] * (<br />
560: a[2][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
561: a[2][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
562: a[2][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
563: )+<br />
564: a[1][3] * (<br />
565: a[2][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
566: a[2][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
567: a[2][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
568: )+<br />
569: a[1][4] * (<br />
570: a[2][0] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1]) +<br />
571: a[2][1] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
572: a[2][3] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
573: ));<br />
574:<br />
575: b[2][1] = +(<br />
576: a[0][0] * (<br />
577: a[2][1] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
578: a[2][3] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
579: a[2][4] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1])<br />
580: )+<br />
581: a[0][1] * (<br />
582: a[2][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
583: a[2][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
584: a[2][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
585: )+<br />
586: a[0][3] * (<br />
587: a[2][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
588: a[2][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
589: a[2][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
590: )+<br />
591: a[0][4] * (<br />
592: a[2][0] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1]) +<br />
593: a[2][1] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
594: a[2][3] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
595: ));<br />
596:<br />
597: b[2][2] = -(<br />
598: a[0][0] * (<br />
599: a[1][1] * (-a[3][3]*a[4][4] + a[3][4]*a[4][3]) +<br />
600: a[1][3] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
601: a[1][4] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1])<br />
602: )+<br />
603: a[0][1] * (<br />
604: a[1][0] * (+a[3][3]*a[4][4] - a[3][4]*a[4][3]) +<br />
605: a[1][3] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
606: a[1][4] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0])<br />
607: )+<br />
608: a[0][3] * (<br />
609: a[1][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
610: a[1][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
611: a[1][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
612: )+<br />
613: a[0][4] * (<br />
614: a[1][0] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1]) +<br />
615: a[1][1] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
616: a[1][3] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
617: ));<br />
618:<br />
619: b[2][3] = +(<br />
620: a[0][0] * (<br />
621: a[1][1] * (-a[2][3]*a[4][4] + a[2][4]*a[4][3]) +<br />
622: a[1][3] * (+a[2][1]*a[4][4] - a[2][4]*a[4][1]) +<br />
623: a[1][4] * (-a[2][1]*a[4][3] + a[2][3]*a[4][1])<br />
624: )+<br />
625: a[0][1] * (<br />
626: a[1][0] * (+a[2][3]*a[4][4] - a[2][4]*a[4][3]) +<br />
627: a[1][3] * (-a[2][0]*a[4][4] + a[2][4]*a[4][0]) +<br />
628: a[1][4] * (+a[2][0]*a[4][3] - a[2][3]*a[4][0])<br />
629: )+<br />
630: a[0][3] * (<br />
631: a[1][0] * (-a[2][1]*a[4][4] + a[2][4]*a[4][1]) +<br />
632: a[1][1] * (+a[2][0]*a[4][4] - a[2][4]*a[4][0]) +<br />
633: a[1][4] * (-a[2][0]*a[4][1] + a[2][1]*a[4][0])<br />
634: )+<br />
635: a[0][4] * (<br />
636: a[1][0] * (+a[2][1]*a[4][3] - a[2][3]*a[4][1]) +<br />
637: a[1][1] * (-a[2][0]*a[4][3] + a[2][3]*a[4][0]) +<br />
638: a[1][3] * (+a[2][0]*a[4][1] - a[2][1]*a[4][0])<br />
639: ));<br />
640:<br />
641: b[2][4] = -(<br />
642: a[0][0] * (<br />
643: a[1][1] * (-a[2][3]*a[3][4] + a[2][4]*a[3][3]) +<br />
644: a[1][3] * (+a[2][1]*a[3][4] - a[2][4]*a[3][1]) +<br />
645: a[1][4] * (-a[2][1]*a[3][3] + a[2][3]*a[3][1])<br />
646: )+<br />
647: a[0][1] * (<br />
648: a[1][0] * (+a[2][3]*a[3][4] - a[2][4]*a[3][3]) +<br />
649: a[1][3] * (-a[2][0]*a[3][4] + a[2][4]*a[3][0]) +<br />
650: a[1][4] * (+a[2][0]*a[3][3] - a[2][3]*a[3][0])<br />
651: )+<br />
652: a[0][3] * (<br />
653: a[1][0] * (-a[2][1]*a[3][4] + a[2][4]*a[3][1]) +<br />
654: a[1][1] * (+a[2][0]*a[3][4] - a[2][4]*a[3][0]) +<br />
655: a[1][4] * (-a[2][0]*a[3][1] + a[2][1]*a[3][0])<br />
656: )+<br />
657: a[0][4] * (<br />
658: a[1][0] * (+a[2][1]*a[3][3] - a[2][3]*a[3][1]) +<br />
659: a[1][1] * (-a[2][0]*a[3][3] + a[2][3]*a[3][0]) +<br />
660: a[1][3] * (+a[2][0]*a[3][1] - a[2][1]*a[3][0])<br />
661: ));<br />
662:<br />
663: /* fourth row */<br />
664: b[3][0] = +(<br />
665: a[1][0] * (<br />
666: a[2][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
667: a[2][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
668: a[2][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
669: )+<br />
670: a[1][1] * (<br />
671: a[2][0] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
672: a[2][2] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
673: a[2][4] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
674: )+<br />
675: a[1][2] * (<br />
676: a[2][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
677: a[2][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
678: a[2][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
679: )+<br />
680: a[1][4] * (<br />
681: a[2][0] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1]) +<br />
682: a[2][1] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0]) +<br />
683: a[2][2] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
684: ));<br />
685:<br />
686: b[3][1] = -(<br />
687: a[0][0] * (<br />
688: a[2][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
689: a[2][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
690: a[2][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
691: )+<br />
692: a[0][1] * (<br />
693: a[2][0] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
694: a[2][2] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
695: a[2][4] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
696: )+<br />
697: a[0][2] * (<br />
698: a[2][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
699: a[2][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
700: a[2][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
701: )+<br />
702: a[0][4] * (<br />
703: a[2][0] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1]) +<br />
704: a[2][1] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0]) +<br />
705: a[2][2] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
706: ));<br />
707:<br />
708: b[3][2] = +(<br />
709: a[0][0] * (<br />
710: a[1][1] * (-a[3][2]*a[4][4] + a[3][4]*a[4][2]) +<br />
711: a[1][2] * (+a[3][1]*a[4][4] - a[3][4]*a[4][1]) +<br />
712: a[1][4] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
713: )+<br />
714: a[0][1] * (<br />
715: a[1][0] * (+a[3][2]*a[4][4] - a[3][4]*a[4][2]) +<br />
716: a[1][2] * (-a[3][0]*a[4][4] + a[3][4]*a[4][0]) +<br />
717: a[1][4] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
718: )+<br />
719: a[0][2] * (<br />
720: a[1][0] * (-a[3][1]*a[4][4] + a[3][4]*a[4][1]) +<br />
721: a[1][1] * (+a[3][0]*a[4][4] - a[3][4]*a[4][0]) +<br />
722: a[1][4] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
723: )+<br />
724: a[0][4] * (<br />
725: a[1][0] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1]) +<br />
726: a[1][1] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0]) +<br />
727: a[1][2] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
728: ));<br />
729:<br />
730: b[3][3] = -(<br />
731: a[0][0] * (<br />
732: a[1][1] * (-a[2][2]*a[4][4] + a[2][4]*a[4][2]) +<br />
733: a[1][2] * (+a[2][1]*a[4][4] - a[2][4]*a[4][1]) +<br />
734: a[1][4] * (-a[2][1]*a[4][2] + a[2][2]*a[4][1])<br />
735: )+<br />
736: a[0][1] * (<br />
737: a[1][0] * (+a[2][2]*a[4][4] - a[2][4]*a[4][2]) +
S.5 Matrix processing 45<br />
738: a[1][2] * (-a[2][0]*a[4][4] + a[2][4]*a[4][0]) +<br />
739: a[1][4] * (+a[2][0]*a[4][2] - a[2][2]*a[4][0])<br />
740: )+<br />
741: a[0][2] * (<br />
742: a[1][0] * (-a[2][1]*a[4][4] + a[2][4]*a[4][1]) +<br />
743: a[1][1] * (+a[2][0]*a[4][4] - a[2][4]*a[4][0]) +<br />
744: a[1][4] * (-a[2][0]*a[4][1] + a[2][1]*a[4][0])<br />
745: )+<br />
746: a[0][4] * (<br />
747: a[1][0] * (+a[2][1]*a[4][2] - a[2][2]*a[4][1]) +<br />
748: a[1][1] * (-a[2][0]*a[4][2] + a[2][2]*a[4][0]) +<br />
749: a[1][2] * (+a[2][0]*a[4][1] - a[2][1]*a[4][0])<br />
750: ));<br />
751:<br />
752: b[3][4] = +(<br />
753: a[0][0] * (<br />
754: a[1][1] * (-a[2][2]*a[3][4] + a[2][4]*a[3][2]) +<br />
755: a[1][2] * (+a[2][1]*a[3][4] - a[2][4]*a[3][1]) +<br />
756: a[1][4] * (-a[2][1]*a[3][2] + a[2][2]*a[3][1])<br />
757: )+<br />
758: a[0][1] * (<br />
759: a[1][0] * (+a[2][2]*a[3][4] - a[2][4]*a[3][2]) +<br />
760: a[1][2] * (-a[2][0]*a[3][4] + a[2][4]*a[3][0]) +<br />
761: a[1][4] * (+a[2][0]*a[3][2] - a[2][2]*a[3][0])<br />
762: )+<br />
763: a[0][2] * (<br />
764: a[1][0] * (-a[2][1]*a[3][4] + a[2][4]*a[3][1]) +<br />
765: a[1][1] * (+a[2][0]*a[3][4] - a[2][4]*a[3][0]) +<br />
766: a[1][4] * (-a[2][0]*a[3][1] + a[2][1]*a[3][0])<br />
767: )+<br />
768: a[0][4] * (<br />
769: a[1][0] * (+a[2][1]*a[3][2] - a[2][2]*a[3][1]) +<br />
770: a[1][1] * (-a[2][0]*a[3][2] + a[2][2]*a[3][0]) +<br />
771: a[1][2] * (+a[2][0]*a[3][1] - a[2][1]*a[3][0])<br />
772: ));<br />
773:<br />
774: /* fifth row */<br />
775: b[4][0] = +(<br />
776: a[1][1] * (<br />
777: a[2][2] * (-a[3][3]*a[4][0] + a[3][0]*a[4][3]) +<br />
778: a[2][3] * (+a[3][2]*a[4][0] - a[3][0]*a[4][2]) +<br />
779: a[2][0] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2])<br />
780: )+<br />
781: a[1][2] * (<br />
782: a[2][1] * (+a[3][3]*a[4][0] - a[3][0]*a[4][3]) +<br />
783: a[2][3] * (-a[3][1]*a[4][0] + a[3][0]*a[4][1]) +<br />
784: a[2][0] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1])<br />
785: )+<br />
786: a[1][3] * (<br />
787: a[2][1] * (-a[3][2]*a[4][0] + a[3][0]*a[4][2]) +<br />
788: a[2][2] * (+a[3][1]*a[4][0] - a[3][0]*a[4][1]) +<br />
789: a[2][0] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
790: )+<br />
791: a[1][0] * (<br />
792: a[2][1] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
793: a[2][2] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
794: a[2][3] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1])<br />
795: ));<br />
796:<br />
797: b[4][1] = +(<br />
798: a[0][0] * (<br />
799: a[2][1] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2]) +<br />
800: a[2][2] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1]) +<br />
801: a[2][3] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
802: )+<br />
803: a[0][1] * (<br />
804: a[2][0] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
805: a[2][2] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
806: a[2][3] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
807: )+<br />
808: a[0][2] * (<br />
809: a[2][0] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
810: a[2][1] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0]) +<br />
811: a[2][3] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
812: )+<br />
813: a[0][3] * (<br />
814: a[2][0] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1]) +<br />
815: a[2][1] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0]) +<br />
816: a[2][2] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
817: ));<br />
818:<br />
819: b[4][2] = -(<br />
820: a[0][0] * (<br />
821: a[1][1] * (-a[3][2]*a[4][3] + a[3][3]*a[4][2]) +<br />
822: a[1][2] * (+a[3][1]*a[4][3] - a[3][3]*a[4][1]) +<br />
823: a[1][3] * (-a[3][1]*a[4][2] + a[3][2]*a[4][1])<br />
824: )+<br />
825: a[0][1] * (<br />
826: a[1][0] * (+a[3][2]*a[4][3] - a[3][3]*a[4][2]) +<br />
827: a[1][2] * (-a[3][0]*a[4][3] + a[3][3]*a[4][0]) +<br />
828: a[1][3] * (+a[3][0]*a[4][2] - a[3][2]*a[4][0])<br />
829: )+<br />
830: a[0][2] * (<br />
831: a[1][0] * (-a[3][1]*a[4][3] + a[3][3]*a[4][1]) +<br />
832: a[1][1] * (+a[3][0]*a[4][3] - a[3][3]*a[4][0]) +<br />
833: a[1][3] * (-a[3][0]*a[4][1] + a[3][1]*a[4][0])<br />
834: )+<br />
835: a[0][3] * (<br />
836: a[1][0] * (+a[3][1]*a[4][2] - a[3][2]*a[4][1]) +<br />
837: a[1][1] * (-a[3][0]*a[4][2] + a[3][2]*a[4][0]) +<br />
838: a[1][2] * (+a[3][0]*a[4][1] - a[3][1]*a[4][0])<br />
839: ));<br />
840:<br />
841: b[4][3] = +(<br />
842: a[0][0] * (<br />
843: a[1][1] * (-a[2][2]*a[4][3] + a[2][3]*a[4][2]) +<br />
844: a[1][2] * (+a[2][1]*a[4][3] - a[2][3]*a[4][1]) +<br />
845: a[1][3] * (-a[2][1]*a[4][2] + a[2][2]*a[4][1])<br />
846: )+<br />
847: a[0][1] * (<br />
848: a[1][0] * (+a[2][2]*a[4][3] - a[2][3]*a[4][2]) +<br />
849: a[1][2] * (-a[2][0]*a[4][3] + a[2][3]*a[4][0]) +<br />
850: a[1][3] * (+a[2][0]*a[4][2] - a[2][2]*a[4][0])<br />
851: )+<br />
852: a[0][2] * (<br />
853: a[1][0] * (-a[2][1]*a[4][3] + a[2][3]*a[4][1]) +<br />
854: a[1][1] * (+a[2][0]*a[4][3] - a[2][3]*a[4][0]) +<br />
855: a[1][3] * (-a[2][0]*a[4][1] + a[2][1]*a[4][0])<br />
856: )+<br />
857: a[0][3] * (<br />
858: a[1][0] * (+a[2][1]*a[4][2] - a[2][2]*a[4][1]) +<br />
859: a[1][1] * (-a[2][0]*a[4][2] + a[2][2]*a[4][0]) +<br />
860: a[1][2] * (+a[2][0]*a[4][1] - a[2][1]*a[4][0])<br />
861: ));<br />
862:<br />
863: b[4][4] = -(<br />
864: a[0][0] * (<br />
865: a[1][1] * (-a[2][2]*a[3][3] + a[2][3]*a[3][2]) +<br />
866: a[1][2] * (+a[2][1]*a[3][3] - a[2][3]*a[3][1]) +<br />
867: a[1][3] * (-a[2][1]*a[3][2] + a[2][2]*a[3][1])<br />
868: )+<br />
869: a[0][1] * (<br />
870: a[1][0] * (+a[2][2]*a[3][3] - a[2][3]*a[3][2]) +<br />
871: a[1][2] * (-a[2][0]*a[3][3] + a[2][3]*a[3][0]) +<br />
872: a[1][3] * (+a[2][0]*a[3][2] - a[2][2]*a[3][0])<br />
873: )+<br />
874: a[0][2] * (<br />
875: a[1][0] * (-a[2][1]*a[3][3] + a[2][3]*a[3][1]) +<br />
876: a[1][1] * (+a[2][0]*a[3][3] - a[2][3]*a[3][0]) +<br />
877: a[1][3] * (-a[2][0]*a[3][1] + a[2][1]*a[3][0])<br />
878: )+<br />
879: a[0][3] * (<br />
880: a[1][0] * (+a[2][1]*a[3][2] - a[2][2]*a[3][1]) +<br />
881: a[1][1] * (-a[2][0]*a[3][2] + a[2][2]*a[3][0]) +<br />
882: a[1][2] * (+a[2][0]*a[3][1] - a[2][1]*a[3][0])<br />
883: ));<br />
884:<br />
885: return det;<br />
886:<br />
887: }<br />
888:<br />
889: /*---------------------------------------------------------------<br />
890: * inverse_4x4()<br />
891: * get the inverse of a square 4x4 matrix<br />
892: * returns determinant<br />
893: *--------------------------------------------------------------*/<br />
894: double<br />
895: inverse_4x4( double **a, double **b)<br />
896: {<br />
897: double det;<br />
898:<br />
899: det =<br />
900: - a[0][0] * a[1][1] * a[2][2] * a[3][3]<br />
901: + a[0][0] * a[1][1] * a[2][3] * a[3][2]<br />
902: + a[0][0] * a[2][1] * a[1][2] * a[3][3]<br />
903: - a[0][0] * a[2][1] * a[1][3] * a[3][2]<br />
904: - a[0][0] * a[3][1] * a[1][2] * a[2][3]<br />
905: + a[0][0] * a[3][1] * a[1][3] * a[2][2]<br />
906:<br />
907: + a[1][0] * a[0][1] * a[2][2] * a[3][3]<br />
908: - a[1][0] * a[0][1] * a[2][3] * a[3][2]<br />
909: - a[1][0] * a[2][1] * a[0][2] * a[3][3]<br />
910: + a[1][0] * a[2][1] * a[0][3] * a[3][2]<br />
911: + a[1][0] * a[3][1] * a[0][2] * a[2][3]<br />
912: - a[1][0] * a[3][1] * a[0][3] * a[2][2]<br />
913:<br />
914: - a[2][0] * a[0][1] * a[1][2] * a[3][3]<br />
915: + a[2][0] * a[0][1] * a[1][3] * a[3][2]<br />
916: + a[2][0] * a[1][1] * a[0][2] * a[3][3]<br />
917: - a[2][0] * a[1][1] * a[0][3] * a[3][2]<br />
918: - a[2][0] * a[3][1] * a[0][2] * a[1][3]<br />
919: + a[2][0] * a[3][1] * a[0][3] * a[1][2]<br />
920:<br />
921: + a[3][0] * a[0][1] * a[1][2] * a[2][3]<br />
922: - a[3][0] * a[0][1] * a[1][3] * a[2][2]<br />
923: - a[3][0] * a[1][1] * a[0][2] * a[2][3]<br />
924: + a[3][0] * a[1][1] * a[0][3] * a[2][2]<br />
925: + a[3][0] * a[2][1] * a[0][2] * a[1][3]<br />
926: - a[3][0] * a[2][1] * a[0][3] * a[1][2] ;<br />
927:<br />
928:<br />
929: b[0][0] = - a[1][1] * (a[2][2]*a[3][3] - a[2][3] * a[3][2])
46 S The Source Code<br />
930: + a[2][1] * (a[1][2]*a[3][3] - a[1][3] * a[3][2])<br />
931: - a[3][1] * (a[1][2]*a[2][3] - a[1][3] * a[2][2]);<br />
932:<br />
933: b[0][1] = + a[0][1] * (a[2][2]*a[3][3] - a[2][3] * a[3][2])<br />
934: - a[2][1] * (a[0][2]*a[3][3] - a[0][3] * a[3][2])<br />
935: + a[3][1] * (a[0][2]*a[2][3] - a[0][3] * a[2][2]);<br />
936:<br />
937: b[0][2] = - a[0][1] * (a[1][2]*a[3][3] - a[1][3] * a[3][2])<br />
938: + a[1][1] * (a[0][2]*a[3][3] - a[0][3] * a[3][2])<br />
939: - a[3][1] * (a[0][2]*a[1][3] - a[0][3] * a[1][2]);<br />
940:<br />
941: b[0][3] = + a[0][1] * (a[1][2]*a[2][3] - a[1][3] * a[2][2])<br />
942: - a[1][1] * (a[0][2]*a[2][3] - a[0][3] * a[2][2])<br />
943: + a[2][1] * (a[0][2]*a[1][3] - a[0][3] * a[1][2]);<br />
944:<br />
945:<br />
946: b[1][0] = + a[1][0] * (a[2][2]*a[3][3] - a[2][3] * a[3][2])<br />
947: - a[2][0] * (a[1][2]*a[3][3] - a[1][3] * a[3][2])<br />
948: + a[3][0] * (a[1][2]*a[2][3] - a[1][3] * a[2][2]);<br />
949:<br />
950: b[1][1] = - a[0][0] * (a[2][2]*a[3][3] - a[2][3] * a[3][2])<br />
951: + a[2][0] * (a[0][2]*a[3][3] - a[0][3] * a[3][2])<br />
952: - a[3][0] * (a[0][2]*a[2][3] - a[0][3] * a[2][2]);<br />
953:<br />
954: b[1][2] = + a[0][0] * (a[1][2]*a[3][3] - a[1][3] * a[3][2])<br />
955: - a[1][0] * (a[0][2]*a[3][3] - a[0][3] * a[3][2])<br />
956: + a[3][0] * (a[0][2]*a[1][3] - a[0][3] * a[1][2]);<br />
957:<br />
958: b[1][3] = - a[0][0] * (a[1][2]*a[2][3] - a[1][3] * a[2][2])<br />
959: + a[1][0] * (a[0][2]*a[2][3] - a[0][3] * a[2][2])<br />
960: - a[2][0] * (a[0][2]*a[1][3] - a[0][3] * a[1][2]);<br />
961:<br />
962:<br />
963: b[2][0] = - a[1][0] * (a[2][1]*a[3][3] - a[2][3] * a[3][1])<br />
964: + a[2][0] * (a[1][1]*a[3][3] - a[1][3] * a[3][1])<br />
965: - a[3][0] * (a[1][1]*a[2][3] - a[1][3] * a[2][1]);<br />
966:<br />
967: b[2][1] = + a[0][0] * (a[2][1]*a[3][3] - a[2][3] * a[3][1])<br />
968: - a[2][0] * (a[0][1]*a[3][3] - a[0][3] * a[3][1])<br />
969: + a[3][0] * (a[0][1]*a[2][3] - a[0][3] * a[2][1]);<br />
970:<br />
971: b[2][2] = - a[0][0] * (a[1][1]*a[3][3] - a[1][3] * a[3][1])<br />
972: + a[1][0] * (a[0][1]*a[3][3] - a[0][3] * a[3][1])<br />
973: - a[3][0] * (a[0][1]*a[1][3] - a[0][3] * a[1][1]);<br />
974:<br />
975: b[2][3] = + a[0][0] * (a[1][1]*a[2][3] - a[1][3] * a[2][1])<br />
976: - a[1][0] * (a[0][1]*a[2][3] - a[0][3] * a[2][1])<br />
977: + a[2][0] * (a[0][1]*a[1][3] - a[0][3] * a[1][1]);<br />
978:<br />
979:<br />
980: b[3][0] = + a[1][0] * (a[2][1]*a[3][2] - a[2][2] * a[3][1])<br />
981: - a[2][0] * (a[1][1]*a[3][2] - a[1][2] * a[3][1])<br />
982: + a[3][0] * (a[1][1]*a[2][2] - a[1][2] * a[2][1]);<br />
983:<br />
984: b[3][1] = - a[0][0] * (a[2][1]*a[3][2] - a[2][2] * a[3][1])<br />
985: + a[2][0] * (a[0][1]*a[3][2] - a[0][2] * a[3][1])<br />
986: - a[3][0] * (a[0][1]*a[2][2] - a[0][2] * a[2][1]);<br />
987:<br />
988: b[3][2] = + a[0][0] * (a[1][1]*a[3][2] - a[1][2] * a[3][1])<br />
989: - a[1][0] * (a[0][1]*a[3][2] - a[0][2] * a[3][1])<br />
990: + a[3][0] * (a[0][1]*a[1][2] - a[0][2] * a[1][1]);<br />
991:<br />
992: b[3][3] = - a[0][0] * (a[1][1]*a[2][2] - a[1][2] * a[2][1])<br />
993: + a[1][0] * (a[0][1]*a[2][2] - a[0][2] * a[2][1])<br />
994: - a[2][0] * (a[0][1]*a[1][2] - a[0][2] * a[1][1]);<br />
995:<br />
996: return det;<br />
997: }<br />
998:<br />
999: /*---------------------------------------------------------------<br />
1000: * coFactor_3x3()<br />
1001: * Find the coFactor matrix of a square matrix<br />
1002: *--------------------------------------------------------------*/<br />
1003: void<br />
1004: coFactor_3x3( double **a, double **b)<br />
1005: {<br />
1006: b[0][0] = +( a[1][1] * a[2][2] - a[2][1] * a[1][2]);<br />
1007: b[1][0] = -( a[1][0] * a[2][2] - a[1][2] * a[2][0]);<br />
1008: b[2][0] = +( a[1][0] * a[2][1] - a[1][1] * a[2][0]);<br />
1009: b[0][1] = -( a[0][1] * a[2][2] - a[0][2] * a[2][1]);<br />
1010: b[1][1] = +( a[0][0] * a[2][2] - a[2][0] * a[0][2]);<br />
1011: b[2][1] = -( a[0][0] * a[2][1] - a[0][1] * a[2][0]);<br />
1012: b[0][2] = +( a[0][1] * a[1][2] - a[0][2] * a[1][1]);<br />
1013: b[1][2] = -( a[0][0] * a[1][2] - a[0][2] * a[1][0]);<br />
1014: b[2][2] = +( a[0][0] * a[1][1] - a[0][1] * a[1][0]);<br />
1015: }<br />
1016:<br />
1017: /*---------------------------------------------------------------<br />
1018: * coFactor_2x2()<br />
1019: * Find the coFactor matrix of a square matrix<br />
1020: *--------------------------------------------------------------*/<br />
1021: void<br />
1022: coFactor_2x2( double **a, double **b)<br />
1023: {<br />
1024: b[0][0] = +a[1][1];<br />
1025: b[1][0] = -a[0][1];<br />
1026: b[0][1] = -a[1][0];<br />
1027: b[1][1] = +a[0][0];<br />
1028: }<br />
1029:<br />
1030: /*---------------------------------------------------------------<br />
1031: * multiplication of squared matrices<br />
1032: * A = B * C<br />
1033: *--------------------------------------------------------------*/<br />
1034: void<br />
1035: multmatsq( int M, double **a, double **b, double **c)<br />
1036: {<br />
1037: int i, j, n;<br />
1038: for (i = 0; i < M; i++)<br />
1039: {<br />
1040: for (j = 0; j < M; j++)<br />
1041: {<br />
1042: a[i][j] = 0;<br />
1043: for (n = 0; n < M; n++)<br />
1044: {<br />
1045: a[i][j] += b[i][n] * c[n][j];<br />
1046: }<br />
1047: }<br />
1048: }<br />
1049: }<br />
1050:<br />
1051: /*---------------------------------------------------------------<br />
1052: * multiplication of squared matrices<br />
1053: * A = B * C^T<br />
1054: *--------------------------------------------------------------*/<br />
1055: void<br />
1056: multmatsqT( int M, double **a, double **b, double **c)<br />
1057: {<br />
1058: int i, j, n;<br />
1059: for (i = 0; i < M; i++)<br />
1060: {<br />
1061: for (j = 0; j < M; j++)<br />
1062: {<br />
1063: a[i][j] = 0;<br />
1064: for (n = 0; n < M; n++)<br />
1065: {<br />
1066: a[i][j] += b[i][n] * c[j][n];<br />
1067: }<br />
1068: }<br />
1069: }<br />
1070: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: matrix_utils.h<br />
3: * Function....: special functions (prototyping)<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2007<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef MATRIX_UTILS_H<br />
15: #define MATRIX_UTILS_H<br />
16:<br />
17: int *ivector( long N);<br />
18: float *fvector( long N);<br />
19: double *vector( long N);<br />
20: double **matrix( long M, long N);<br />
21: float **fmatrix( long N, long M);<br />
22:<br />
23: void free_ivector( int *v[]);<br />
24: void free_vector( double *v[]);<br />
25: void free_matrix( double **m[]);<br />
26: void free_fmatrix( float **m[]);<br />
27:<br />
28:<br />
29: double determinant_2x2( double **a);<br />
30: double determinant_3x3( double **a);<br />
31: double inverse_4x4( double **a, double **b);<br />
32: double inverse_5x5( double **a, double **b);<br />
33: void coFactor_2x2( double **a, double **b);<br />
34: void coFactor_3x3( double **a, double **b);<br />
35:<br />
36: void multmatsq( int M, double **a, double **b, double **c);<br />
37: void multmatsqT( int N, double **a, double **b, double **c);<br />
38:<br />
39: #endif<br />
S.6 Comm<strong>and</strong>-line parsing<br />
0: /****************************************************************<br />
1: *
S.6 Comm<strong>and</strong>-line parsing 47<br />
2: * File........: get_option.c<br />
3: * Function....: reading <strong>and</strong> analysing of<br />
4: * comm<strong>and</strong>-line parameters/options<br />
5: * Author......: Tilo Strutz<br />
6: * last changes: 15.08.2006<br />
7: *<br />
8: * LICENCE DETAILS: see software manual<br />
9: * free academic use<br />
10: * cite source as<br />
11: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
12: *<br />
13: ****************************************************************/<br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include "get_option.h"<br />
18:<br />
19: /* contains argument of option, if OptArg != NULL */<br />
20: char *OptArg = NULL;<br />
21: char CheckStr[256];<br />
22: /* CheckStr[] will be initialised with NEEDEDOPTIONS<br />
23: * all used optionen are deleted; if atleast one option remains,<br />
24: * an error message is output */<br />
25: char *optstr;<br />
26: int opt_num = 1;<br />
27:<br />
28: /*---------------------------------------------------------------<br />
29: * check_opt()<br />
30: *---------------------------------------------------------------*/<br />
31: int<br />
32: check_opt( const char *name)<br />
33: {<br />
34: char *ptr;<br />
35: int i, len, err = 0;<br />
36:<br />
37: len = strlen( CheckStr);<br />
38: for (i = 0; i < len; i++)<br />
39: {<br />
40: if (( CheckStr[i] != ’:’) && (CheckStr[i] != ’ ’))<br />
41: {<br />
42: ptr = &CheckStr[i];<br />
43: ptr = (char*)strpbrk( ptr, ";:");<br />
44: ptr[0] = ’\0’;<br />
45: err = 1;<br />
46: break;<br />
47: }<br />
48: }<br />
49: if (err)<br />
50: {<br />
51: fprintf( stderr, "\n Missing Option for (-%s)!", &CheckStr[i]);<br />
52: usage( name);<br />
53: }<br />
54: return err;<br />
55: }<br />
56:<br />
57: /*---------------------------------------------------------------<br />
58: * get_option()<br />
59: *<br />
60: * opt_num is number of option to be read<br />
61: * result: option string<br />
62: * required: global string containing all options<br />
63: * at first call opt_num must be equal to 1 !<br />
64: *<br />
65: *---------------------------------------------------------------*/<br />
66: char *<br />
67: get_option( int argc, const char *argv[])<br />
68: {<br />
69: char optstring[256], *ptr, c, d, string[256];<br />
70: char *gerrstr="#";<br />
71: int len, i, num;<br />
72:<br />
73: if (opt_num == 1)<br />
74: {<br />
75: strcpy( CheckStr, NEEDEDOPTIONS);<br />
76: }<br />
77: if (opt_num > (argc - 1))<br />
78: {<br />
79: return (NULL);<br />
80: }<br />
81: else if (argv[opt_num][0] == ’+’)<br />
82: {<br />
83: /* + signals end of parameter list */<br />
84: opt_num++;<br />
85: return (NULL);<br />
86: }<br />
87: else if (argv[opt_num][0] != ’-’)<br />
88: {<br />
89: fprintf( stderr, "\n Option-Error !! *********** ");<br />
90: fprintf( stderr,<br />
91: "\n every Option must start with ’-’ (%s)!", argv[opt_num]);<br />
92: /* usage( argv[0]); */<br />
93: return gerrstr;<br />
94: }<br />
95:<br />
96: /***** copy without ’-’ *****/<br />
97: num = opt_num;<br />
98: strcpy( optstring, argv[num]);<br />
99: strcpy( string, &optstring[1]);<br />
100:<br />
101: len = strlen( string);<br />
102: if (len == 0)<br />
103: {<br />
104: /* single ’-’ */<br />
105: fprintf( stderr, "\n Option-Error !! *********** ");<br />
106: fprintf( stderr, "\n lonely dash !");<br />
107: /* usage( argv[0]); */<br />
108: return gerrstr;<br />
109: }<br />
110: ptr = OPTIONSTRING;<br />
111: do<br />
112: {<br />
113: /* search option string in OPTIONSTRING */<br />
114: ptr = (char*)strstr( ptr, string);<br />
115: if (ptr == NULL)<br />
116: {<br />
117: fprintf( stderr, "\n Option-Error !! *********** ");<br />
118: fprintf( stderr, "\n Unknown Option (%s)!", optstring);<br />
119: /* usage( argv[0]); */<br />
120: return gerrstr;<br />
121: }<br />
122: c = ptr[len]; /* remember subsequent character */<br />
123: d = ptr[-1]; /* remember predecessor */<br />
124:<br />
125: /* skip this entry by searching for next ’:’ or ’;’ */<br />
126: ptr = (char*)strpbrk( ptr, ";:.");<br />
127: } while (( (c != ’:’) && (c != ’;’) && (c != ’.’)) || (( d != ’:’)<br />
128: && (d != ’;’)&& (d != ’.’)));<br />
129:<br />
130: if (c == ’;’) /* info, whether argument follows */<br />
131: {<br />
132: OptArg = NULL;<br />
133: opt_num++;<br />
134: }<br />
135: else<br />
136: {<br />
137: opt_num++;<br />
138: if (opt_num > (argc - 1))<br />
139: {<br />
140: fprintf( stderr, "\n Option-Error !! *********** ");<br />
141: fprintf( stderr, "\n Missing Argument for (%s)!", optstring);<br />
142: /* usage( argv[0]); */<br />
143: return gerrstr;<br />
144: }<br />
145: else if (argv[opt_num][0] == ’-’ && c == ’:’)<br />
146: {<br />
147: fprintf( stderr, "\n Option-Error !! *********** ");<br />
148: fprintf( stderr, "\n Missing Argument for (%s)!", optstring);<br />
149: /* usage( argv[0]); */<br />
150: return gerrstr;<br />
151: }<br />
152: else<br />
153: {<br />
154: /* if c == ’.’ then negativ parameter are allowed */<br />
155: }<br />
156: OptArg = (char*)argv[opt_num];<br />
157: opt_num++;<br />
158: }<br />
159: strcpy( string, ":");<br />
160: strcat( string, &optstring[1]);<br />
161: strcat( string, ":");<br />
162: ptr = (char*)strstr( CheckStr, string);<br />
163: if (ptr != NULL)<br />
164: for (i = 0; i < len; i++)<br />
165: ptr[i + 1] = ’ ’;<br />
166:<br />
167: return (( char*)argv[num]);<br />
168: }<br />
0: /****************************************************************<br />
1: *<br />
2: * File........: get_option.h<br />
3: * Function....: prototyping etc. for get_option.c<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 30.03.2006<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: ****************************************************************/<br />
13:<br />
14: #ifndef GETOPT_H<br />
15: #define GETOPT_H<br />
16:<br />
17: /* defined in get_option.c */<br />
18: extern char *OptArg;<br />
19: extern char CheckStr[256];<br />
20: /* CheckStr will be initialised with NEEDEDOPTIONS,<br />
21: * all used optionen are deleted;<br />
22: * if at least one option remains, an error message is output
48 S The Source Code<br />
23: */<br />
24: extern char *optstr;<br />
25: /* can be used in main file to point to filenames */<br />
26: extern int opt_num; /* is defined in get_option.c */<br />
27:<br />
28: /* defined in usage.c */<br />
29: extern char *title;<br />
30: extern char *OPTIONSTRING;<br />
31: extern char *NEEDEDOPTIONS;<br />
32:<br />
33: /* Prototyping */<br />
34: void usage( const char *name);<br />
35: int check_opt( const char *name);<br />
36: char *get_option( int argc, const char **argv);<br />
37:<br />
38: #endif<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: usage.c<br />
3: * Function....: parameters for <strong>Fitting</strong><br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 07.05.2008, 01.10.2009, 6.11.2009, 08.01.2010<br />
6: * 18.02.2010, 10.03.2010<br />
7: *<br />
8: * LICENCE DETAILS: see software manual<br />
9: * free academic use<br />
10: * cite source as<br />
11: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
12: *<br />
13: *****************************************************************/<br />
14: #include <br />
15: #include <br />
16: #include <br />
17:<br />
18: /* allowed options: must start with ’:’ !! */<br />
19: char *OPTIONSTRING =<br />
20: { ":a:a1.a2.a3.a4.a5.a6.a7.a8.a9.b:c;cc:co:f;H;i:I:L;m:M:n;o:s;t:w:x:" };<br />
21: char *NEEDEDOPTIONS = { ":i:o:m:" }; /* required options */<br />
22:<br />
23: char *title = { "<strong>Fitting</strong> WLS version 1.0 (02/2010)" };<br />
24:<br />
25: /*---------------------------------------------------------------<br />
26: * usage()<br />
27: *---------------------------------------------------------------*/<br />
28: void<br />
29: usage( char *name)<br />
30: {<br />
31: fprintf( stderr, "\n\n %s\n", title);<br />
32: fprintf( stderr, "\n\<br />
33: Usage: %s [options]\n\n\<br />
34: Legal Options: \n\<br />
35: -i %%s ... input data file (compulsory)\n\<br />
36: -o %%s ... output file (compulsory)\n\<br />
37: -m %%d ... model function (compulsory)\n\<br />
38: 0 ... constant\n\<br />
39: 1 ... f(x|a) = a1 + SUM_j=2^M a_j * x_(j-1)\n\<br />
40: 2 ... f(x|a) = a1 + a2 * cos( x) + a3 * sin( x) [in degrees]\n\<br />
41: 3 ... f(x|a) = a1 + x[n-1] + a2 * x[n-1] + a3 * x[n-3]\n\<br />
42: 5 ... f(x|a) = a1 + a2 * cos( x - a3) [in degrees]\n\<br />
43: 6 ... f(x|a) = a1 + a2 * exp( a3 * x)\n\<br />
44: 7 ... f(x|a) = log( a1 * x)\n\<br />
45: 8 ... f(x|a) = a1 * exp( (x-a2)^2 * a3) + \n\<br />
46: a4 * exp( (x-a5)^2 * a6)\n\<br />
47: 9 ... f(x|a) = a1 * exp( a2 * x)\n\<br />
48: 10 ... ln(f(x|a)) = ln(a1) + a2 * x\n\<br />
49: 11 ... f(x|a) = a1 * exp( -|x|^a2 * a3)\n\<br />
50: 12 ... f(x|a) = a1 + a2 * x + a3 * cos( x - a4) [in radians]\n\<br />
51: 13 ... f(x|a) = a1 * exp( (x-a2)^2 * a3) + \n\<br />
52: 16 ... f(x|a) = a1 + a2 * x + a3 * x^2\n\<br />
53: 17 ... f(x|a) = a1 + a2 * x + a3 * x^2 + a4 * x^3\n\<br />
54: 18 ... f(x|a) = sum_{j=1}^M aj * x^(j-1) (linear)\n\<br />
55: 19 ... f(x|a) = sum_{j=1}^M aj * x^(j-1) (nonlinear)\n\<br />
56: 20 ... f(x|a) = a1 + a2*x1 + a3*x1^2 + a4*x2 +a5*x2^2\n\<br />
57: 21 ... f1(x|a) = a1 + cos(a3) * x1 - sin(a3) * x2 [in radians]\n\<br />
58: f2(x|a) = a2 + sin(a3) * x1 + cos(a3) * x2 [in radians]\n\<br />
59: 22 ... f(x|a) = a1 + a2*cos(a3*x-a4) [in radians]\n\<br />
60: 23 ... f(x|a) = a1 + a2*cos(a3*x-a4) + a5*cos(2*a3*x-a6)\n\<br />
61: 24 ... f(x|a) = 0 = (x1 - a1)^2 + (x2 - a2)^2 - a3*a3 (circle)\n\<br />
62: 25 ... f(x|a) = x1^2 + x2^2 = a1*x1 + a2*x2 - a3\n\<br />
63: (circle, linear)\n\<br />
64: 26 ... f(x|a) = 0 = (sqrt[(x1 - a1)^2 + (x2 - a2)^2] - a3)^2\n\<br />
65: (circle, TLS)\n\<br />
66: 30 ... neural network 3x3x1, feed forward\n\<br />
67: 31 ... neural network 3x2x1\n\<br />
68: 32 ... neural network 1x2x1\n\<br />
69: 33 ... neural network 2x2x1\n\<br />
70: 34 ... neural network 1x3x1\n\<br />
71: 40 ... f(x|a) =(a1 + a2*x + a3*x*x + a4*x*x*x) /\n\<br />
72: (1 + a5*x + a6*x*x + a7*x*x*x) NIST_THURBER\n\<br />
73: 41 ... f(x|a) = a1 * (x**2 + a2*x) /\n\<br />
74: (x*x + a3*x + a4) NIST_MGH09\n\<br />
75: 42 ... f(x|a) = a1 / (1 + exp(a2 - a3*x)) NIST_Rat42\n\<br />
76: 43 ... f(x|a) = a1 / [1 + exp(a2 - a3*x)]^(1/a4) NIST_Rat43\n\<br />
77: 44 ... f(x|a) = a1 / a2 * exp(-0.5*((x -a3)/ a2)^2) NIST_Eckerle4\n\<br />
78: 45 ... f(x|a) = a1 * exp( a2 / (x+a3)) NIST_MGH10\n\<br />
79: 46 ... f(x|a) = a1 * (x+a2)^(-1/a3) NIST_Bennett5\n\<br />
80: 47 ... f(x|a) = a1 *(1 - exp( -a2 * x) NIST_BoxBOD\n\<br />
81: -a %%d ... inversion algorithm (default: 1)\n\<br />
82: 0 - cofactor method\n\<br />
83: 1 - singular value decomposition\n\<br />
84: 2 - LU decomposition\n\<br />
85: -a[j] %%f ... provides initial value for a_j (j=1,2,..,9)\n\<br />
86: -b %%d ... observations per bin, for ’-w 2’ (default: 50)\n\<br />
87: -c ... enable scaling of conditions \n\<br />
88: -cc %%s ... comma-separated list of column(s) containing \n\<br />
89: conditions x (default: 1,2,...)\n\<br />
90: -co %%d ... column containing observations y (default: 2)\n\<br />
91: -f ... forget weights after outlier removal\n\<br />
92: -H ... enable true Hessian matrix\n\<br />
93: -I %%d ... maximum number of iterations (default: 2000)\n\<br />
94: -M %%d ... number of parameters (for ’-m 1’ only)\n\<br />
95: -n ... force usage of numerical derivation\n\<br />
96: -L ... use Gaus-Newton instead of Levenberg-Marquardt \n\<br />
97: -s ... use special SVD function for solving linear model\n\<br />
98: -t %%f ... target value for chisq (maximum error)\n\<br />
99: default: iteration until convergence\n\<br />
100: -w %%d ... weighting (default: 0)\n\<br />
101: 0 ... no weighting \n\<br />
102: 1 ... based on deviates \n\<br />
103: 2 ... binning \n\<br />
104: -x %%d ... outlier removal (default: 0)\n\<br />
105: 0 ... no outlier removal\n\<br />
106: 1 ... Chauvenet’s criterion\n\<br />
107: 2 ... cluster criterion \n\<br />
108: \n\<br />
109: ", name);<br />
110: }
S.8 Other 49<br />
S.7 Error H<strong>and</strong>ling<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: errmsg.c<br />
3: * Function....: error messages<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2007<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13: #include <br />
14: #include <br />
15: #include "errmsg.h"<br />
16:<br />
17: int<br />
18: errmsg( int err, char *rtn, char *text, int value)<br />
19: {<br />
20: switch (err)<br />
21: {<br />
22: case ERR_CALL:<br />
23: fprintf( stderr, ERR_CALL_MSG, rtn, text);<br />
24: break;<br />
25: case ERR_OPEN_READ:<br />
26: fprintf( stderr, ERR_OPEN_READ_MSG, rtn, text);<br />
27: perror( "\nReason");<br />
28: break;<br />
29: case ERR_OPEN_WRITE:<br />
30: fprintf( stderr, ERR_OPEN_WRITE_MSG, rtn, text);<br />
31: perror( "\nReason");<br />
32: break;<br />
33: case ERR_ALLOCATE:<br />
34: fprintf( stderr, ERR_ALLOCATE_MSG, rtn, text);<br />
35: perror( "\nReason");<br />
36: break;<br />
37: case ERR_NOT_DEFINED:<br />
38: fprintf( stderr, ERR_NOT_DEFINED_MSG, rtn, value, text);<br />
39: break;<br />
40: case ERR_IS_ZERO:<br />
41: fprintf( stderr, ERR_IS_ZERO_MSG, rtn, text);<br />
42: break;<br />
43: case ERR_IS_SINGULAR:<br />
44: fprintf( stderr, ERR_IS_SINGULAR_MSG, rtn, text);<br />
45: break;<br />
46: default:<br />
47: fprintf( stderr, "\nerrmsg: error %d is not defined\n", err);<br />
48: break;<br />
49: }<br />
50: return err;<br />
51: }<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: errmsg.h<br />
3: * Function....: error messages<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 25.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef ERRMSG_H<br />
15: #define ERRMSG_H<br />
16:<br />
17:<br />
18: #define ERR_CALL 1<br />
S.8 Other<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: heap_sort.c<br />
3: * Function....: sorting of values<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 20.10.2007<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #include <br />
15: #include <br />
16: #include <br />
17: #include <br />
18:<br />
19: /*---------------------------------------------------------------<br />
20: * heap_sort_d()<br />
21: * sorting of values in values[0...N-1] in ascending order<br />
22: * values[] is replaced on output by sorted values<br />
23: *--------------------------------------------------------------*/<br />
24: void<br />
25: heap_sort_d( unsigned long N, double values[])<br />
26: {<br />
27: unsigned long i, ir, j, l;<br />
28: double rvalues;<br />
29:<br />
30: if (N < 2)<br />
31: return;<br />
32:<br />
33: l = (N >> 1);<br />
34: ir = N - 1;<br />
35:<br />
36: for (;;)<br />
37: {<br />
38: if (l > 0)<br />
39: {<br />
40: l--;<br />
41: rvalues = values[l];<br />
42: }<br />
43: else<br />
44: {<br />
45: rvalues = values[ir];<br />
46: values[ir] = values[0];<br />
47: ir--;<br />
48: if (ir == 0)<br />
49: {<br />
50: values[0] = rvalues;<br />
51: break;<br />
52: }<br />
53: }<br />
54: i = l;<br />
55:<br />
56: j = l + l + 2;<br />
57: while (j
50 S The Source Code<br />
94:<br />
95: l = (N >> 1);<br />
96: ir = N - 1;<br />
97:<br />
98: for (;;)<br />
99: {<br />
100: if (l > 0)<br />
101: {<br />
102: l--;<br />
103: rvalues = values[l]; iidx = idx[l];<br />
104: }<br />
105: else<br />
106: {<br />
107: rvalues = values[ir]; iidx = idx[ir];<br />
108: values[ir] = values[0]; idx[ir] = idx[0];<br />
109: ir--;<br />
110: if (ir == 0)<br />
111: {<br />
112: values[0] = rvalues; idx[0] = iidx;<br />
113: break;<br />
114: }<br />
115: }<br />
116: i = l;<br />
117:<br />
118: j = l + l + 2;<br />
119: while (j 2.2 */<br />
46: return 1.0 - erfc(x);<br />
47: }<br />
48: do<br />
49: {<br />
50: term *= xsqr / j;<br />
51: sum -= term /(2*j+1);<br />
52: j++;<br />
53: term *= xsqr / j;<br />
54: sum += term /(2*j+1);<br />
55: j++;<br />
56: } while (fabs(term) / sum > rel_error);<br />
57: return two_sqrtpi * sum;<br />
58: }<br />
59:<br />
60: /*---------------------------------------------------------------<br />
61: * erfc()<br />
62: *<br />
63: * erfc(x) = 2/sqrt(pi)*integral(exp(-t^2),t,x,inf)<br />
64: * = exp(-x^2)/sqrt(pi) * [1/x + (1/2)/x + (2/2)/x +<br />
65: * (3/2)/x+ (4/2)/x+ ...]<br />
66: * = 1-erf(x)<br />
67: * expression inside [] is a continued fraction<br />
68: * so ’+’ means add to denominator only<br />
69: *--------------------------------------------------------------*/<br />
70: double erfc(double x)<br />
71: {<br />
72: /* 1/sqrt(pi)*/<br />
73: static const double one_sqrtpi = 0.564189583547756287;<br />
74: double a = 1, b; /* last two convergent numerators */<br />
75: double c, d; /* last two convergent denominators */<br />
76: double q1, q2; /* last two convergents (a/c <strong>and</strong> b/d) */<br />
77: double n = 1.0, t;<br />
78:<br />
79: b = c = x;<br />
80: d = x * x + 0.5;<br />
81: q2 = b / d;<br />
82:<br />
83: if (fabs(x) < 2.2)<br />
84: {<br />
85: return 1.0 - erf(x); /* use series when fabs(x) < 2.2 */<br />
86: }<br />
87: if (x > 0)<br />
88: { /* continued fraction only valid for x>0 */<br />
89: return 2.0 - erfc(-x);<br />
90: }<br />
91: do<br />
92: {<br />
93: t = a*n + b*x;<br />
94: a = b;<br />
95: b = t;<br />
96: t = c*n + d*x;<br />
97: c = d;<br />
98: d = t;<br />
99: n += 0.5;<br />
100: q1 = q2;<br />
101: q2 = b / d;<br />
102: } while (fabs(q1-q2) / q2 > rel_error);<br />
103: return one_sqrtpi * exp(-x*x) * q2;<br />
104: }<br />
105:<br />
106: /*---------------------------------------------------------------<br />
107: * erfinv()<br />
108: *<br />
109: *--------------------------------------------------------------*/<br />
110: int erfinv( double y, double *res )<br />
111: {<br />
112: static double a[] = {0, 0.886226899, -1.645349621,<br />
113: 0.914624893, -0.140543331 };<br />
114: static double b[] = {0, -2.118377725, 1.442710462,<br />
115: -0.329097515, 0.012229801 };<br />
116: static double c[] = {0, -1.970840454, -1.624906493,<br />
117: 3.429567803, 1.641345311 };<br />
118: static double d[] = {0, 3.543889200, 1.637067800 };<br />
119: int err = 0;<br />
120: double x, z;<br />
121:<br />
122: if ( y > -1. )<br />
123: {<br />
124: if ( y >= -.7 )<br />
125: {<br />
126: if ( y
S.8 Other 51<br />
145: z = sqrt(-log((1+y)/2));<br />
146: x = -(((c[4]*z+c[3])*z+c[2])*z+c[1]) / ((d[2]*z+d[1])*z+1);<br />
147: }<br />
148: }<br />
149: else<br />
150: {<br />
151: err = 3;<br />
152: x = 0;<br />
153: }<br />
154: *res = x;<br />
155: return err;<br />
156: }<br />
0: /***************************<br />
1: * File........: erf.h<br />
2: * Function....: prototypes for erf.c<br />
3: * Author......: Tilo Strutz<br />
4: * last changes: 05.02.2008<br />
5: *<br />
6: * LICENCE DETAILS: see software manual<br />
7: * free academic use<br />
8: * cite source as<br />
9: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
10: *<br />
11: ***************************/<br />
12: double erf(double x);<br />
13: double erfc(double x);<br />
14: int erfinv( double y, double *res );<br />
0: /*****************************************************************<br />
1: *<br />
2: * File........: macros.h<br />
3: * Function....: general purpose macros<br />
4: * Author......: Tilo Strutz<br />
5: * last changes: 25.01.2010<br />
6: *<br />
7: * LICENCE DETAILS: see software manual<br />
8: * free academic use<br />
9: * cite source as<br />
10: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
11: *<br />
12: *****************************************************************/<br />
13:<br />
14: #ifndef MACROS_H<br />
15: #define MACROS_H<br />
16:<br />
17: #define MAX(a,b) ((a) > (b) ? (a) : (b))<br />
18: #define MIN(a,b) ((a) < (b) ? (a) : (b))<br />
19:<br />
20: #define M_PI 3.14159265358979323846 /* pi */<br />
21: #define TOL 1.0e-10 /* for convergence criterion */<br />
22: #define TOL_S2 1.0e-14 /* for test of singular values */<br />
23: #define TOL_S 1.0e-12 /* for test of singular values */<br />
24: /* this small value is required, for example,<br />
25: for the Bennett5 data set */<br />
26:<br />
27: #endif<br />
0: /*************************************************************<br />
1: * File........: defines.h<br />
2: * Function....: definition of globally used values<br />
3: * Author......: Tilo Strutz<br />
4: * last changes: 03.07.2009<br />
5: *<br />
6: * LICENCE DETAILS: see software manual<br />
7: * free academic use<br />
8: * cite source as<br />
9: * "Strutz, T.: <strong>Data</strong> <strong>Fitting</strong> <strong>and</strong> <strong>Uncertainty</strong>. Vieweg+Teubner, 2010"<br />
10: *<br />
11: ***********************************************************/<br />
12:<br />
13: #ifndef DEFINES_H<br />
14: #define DEFINES_H<br />
15:<br />
16: /* for est_weights.c <strong>and</strong> outlier_detetction.c */<br />
17:<br />
18: #define MAX_LINES_W 500<br />
19:<br />
20:<br />
21: /* for fitting.c */<br />
22:<br />
23: /* maximal number of conditions per model function */<br />
24: /* see functions.h */<br />
25: #define MAX_CONDITIONS (M_MAX-1)<br />
26: /* output of maximal 100 lines of resulting values as feedback */<br />
27: #define MAX_LINES 100<br />
28: /* input file may contain maximal 512 characters per line */<br />
29: #define MAXLINELENGTH 512<br />
30:<br />
31:<br />
32: /* for functions.c */<br />
33:<br />
34: /* maximal 15 parameters per model function (see f_deriv()) */<br />
35: #define M_MAX 16<br />
36:<br />
37: /* for ls.c */<br />
38: extern long ITERAT_MAX;<br />
39:<br />
40: #endif