29.06.2013 Views

Data Fitting and Uncertainty

Data Fitting and Uncertainty

Data Fitting and Uncertainty

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!