source: Sophya/trunk/SophyaLib/NTools/nbmath.c@ 2882

Last change on this file since 2882 was 2639, checked in by cmv, 21 years ago

factoriel et approx cmv 22/11/04

File size: 75.3 KB
Line 
1#include <unistd.h>
2#include <stdlib.h>
3#include <stdio.h>
4
5#include <math.h>
6#include "nbmath.h"
7#include "matxop.h"
8#include "nbinteg.h"
9#include "nbtri.h"
10
11#define ITMAX 256
12#define EPS 3.0e-7
13#define DEB_GausPiv 0
14#define DEB_MeanSig 0
15
16/*
17++
18 Module Fonction mathematiques (C)
19 Lib LibsUtil
20 include nbmath.h
21
22 Fonction mathematiques (C)
23--
24*/
25
26void FitFun_MrqCof( double (*FunFit) (double ,double *,double *) ,int_4 type
27 ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
28 ,int_4 *ndata,int_4 I1,int_4 I2
29 ,double *parcur,int_4 npar,int_4 *ind
30 ,double *ATGA,double *BETA,double *ci2,int_4 deb);
31void nbgcf(double *gammcf,double a,double x,double *gln);
32void nbgser(double *gamser,double a,double x,double *gln);
33
34
35static int FITFUN_DPOL = -1;
36
37
38/*=========================================================================*/
39/* Christophe 8/11/93 La Silla */
40/*
41++
42double FitFun
43| ( double (*FunFit) (double ,double *,double *) ,int_4 type
44| ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
45| ,int_4 *ndata,int_4 I1,int_4 I2
46| ,double *par,double *epar,double *stepar
47| ,double *minpar,double *maxpar,int_4 npar
48| ,double stochi2,int_4 NstepMX,int_4 deb)
49
50 Pour fitter une fonction parametrique sur des donnees.
51 (Obsolete, utilisez GeneralFit en C++).
52--
53*/
54/*
55++
56| Fonction de fit de la courbe FunFit sur les donnees
57| - Methode: fit des moindres carres dans le cas non lineaire
58| - Reference: Statistical and Computational Methods in Data Analysis
59| Siegmund Brandt, North-Holland 1970 p 204-206.
60| Introduction des limites pour la variation des parametres (cmv).
61| Increment des parametres selon la methode de Levenberg-Marquardt
62| (Numerical Receipes in C p 542)
63| - Remarques diverses:
64| Les points avec erreurs negatives ou nulles ne sont pas
65| utilises dans le fit.
66| Si le fit est hautement non lineaire, il faut donner de bonnes
67| approximations pour les parametres de depart.
68| Les limites minpar,maxpar sont des limites absolues mais possibles
69| - Memo personnel:
70| data = Ti, Fi ERRi i=0,n-1
71| parametres Pj j=1,npar
72| fonction FunFit(t,P1,P2,..,Pnpar)
73| matrice A(n,4) = [Aij] = - [dg(T)/dPj] pour t=Ti
74| matrice G(n,n) = [Gij] = matrice diagonale 1/ERRj**2
75| matrice C(n) = [Ci] = (Fi - FunFit(t,P1,P2,..,Pnpar))
76| Pj(iteration n) = Pj(iteration n-1) + Zj
77--
78*/
79/*
80++
81| -----------
82| | ENTREES |
83| -----------
84| - FunFit fonction a fiter
85| - type type des donnees a fiter (union temps,mag,err):
86| float=FITFUN_FLOAT / double=FITFUN_DOUBLE
87| - temps: union FLOATDOUBLE des tableaux des temps:
88| - mag: union FLOATDOUBLE des tableaux des magnitudes:
89| - err: union FLOATDOUBLE des tableaux des erreurs sur la magnitude
90| - ndata: nombre de donnees en entree, donc en c:
91| - I1: indice de depart pour le fit
92| - I2: indice de fin pour le fit
93| (si I2 <= I1 defaut: 1,*ndata)
94| - par: contient les valeurs d'initialisation des parametres
95| - stepar: si >0. on fit le parametre, sinon parametre fixe
96| - minpar: les valeurs minimum pouvant prendre les parametres
97| - maxpar: les valeurs minimum pouvant prendre les parametres
98| (si maxpar[i] <= minpar[i] pas de limitation sur le parametre i)
99| - stochi2:la valeur de variation du chi2 d'une iteration l'autre
100| en dessous de laquelle on arrete d'iterer:
101| (si <=0 le default est 0.01).
102| - npar: nombre de parametres du fit *par --> *(par+npar-1)
103| - NstepMX:nombre maximum d'iterations
104| - deb: niveau de print (0/1/2/3)
105--
106*/
107/*
108++
109| ----------
110| | SORTIES |
111| ----------
112| - ndata: nombre de donnees utilisees dans le fit
113| - par: contient les valeurs fitees des parametres
114| - epar: contient les erreurs sur les valeurs fitees des parametres
115| - FitFun: la function elle meme retourne le Xi2 du fit si succes
116| -1. si l'inversion de la matrice des erreurs n'a pas ete possible
117| -2. si les parametres initiaux sont en desaccord avec les limites
118| -3. si le nombre de donnees est inferieur au nombre de parametres
119| -4. si le fit n'a pas converge (nstep>nNstepMX)
120--
121*/
122/*
123++
124| --------------
125| | MEMO PERSO |
126| --------------
127| la structure FLOATDOUBLE:
128| union FloatDouble {
129| float *fx;
130| double *dx;
131| };
132| - Si les tableaux temps,mag,emag sont des float alors
133| temps.fx doit contenir l'adresse du tableau des temps
134| (et idem pour mag.fx et err.fx)
135| - Si les tableaux temps,mag,emag sont des double alors
136| temps.dx doit contenir l'adresse du tableau des temps
137| (et idem pour mag.dx et err.dx)
138--
139*/
140double FitFun( double (*FunFit) (double ,double *,double *) ,int_4 type
141 ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
142 ,int_4 *ndata,int_4 I1,int_4 I2
143 ,double *par,double *epar,double *stepar
144 ,double *minpar,double *maxpar,int_4 npar
145 ,double stochi2,int_4 NstepMX,int_4 deb)
146{
147int_4 ind[NPAR_FITFUN], i, j, k, nstep, nparsave, nstop, nstopMX;
148double LimitC2,lambda,eps;
149double ATGA[NPAR_FITFUN][NPAR_FITFUN], COVAR[NPAR_FITFUN][NPAR_FITFUN]
150 , ALPHA[NPAR_FITFUN][NPAR_FITFUN];
151double DA[NPAR_FITFUN], BETA[NPAR_FITFUN];
152double parcur[NPAR_FITFUN],partry[NPAR_FITFUN];
153double ci2, ci20;
154
155/* initialisation */
156if( type != FITFUN_FLOAT && type != FITFUN_DOUBLE) {
157 printf("FitFun: Type de variable non prevue dans union FLOATDOUBLE %d\n",type);
158 exit(-1);
159}
160
161if(npar>NPAR_FITFUN) {
162 printf("FitFun: trop de parametres npar=%d > NPAR_FITFUN=%d\n",npar,NPAR_FITFUN);
163 exit(-1);
164}
165nstopMX = 3;
166eps = 1.e-8;
167LimitC2=0.01;
168if ( stochi2 > 0. ) LimitC2 = stochi2; /* test des valeurs d'arret */
169nstop = 0;
170
171/* fit du centre autour des valeurs estimees */
172nparsave = npar;
173for (i=0;i<nparsave;i++) parcur[i] = *(par+i);
174
175npar=0;
176for (i=0;i<nparsave;i++) {
177 ind[i]= -1;
178 *(epar+i) = 0.;
179 partry[i] = *(parcur+i);
180 if ( stepar[i] > 0. ) {
181 ind[npar]=i;
182 npar++;
183} }
184
185if ( I2 <= I1 ) { I1 = 0; I2 = *ndata-1;}
186if ( I2-I1+1 < npar ) {
187 printf("le nombre de donnees %d est inferieur au nombre de parametres %d\n"
188 ,I2-I1+1,npar);
189 return(-3.);
190}
191
192for (j=0;j<npar;j++) {
193 i = ind[j];
194 if(*(maxpar+i)>*(minpar+i) && (*(parcur+i)<=*(minpar+i) || *(parcur+i)>=*(maxpar+i))) {
195 printf("Parametre %d initialise hors limites: %f # [%f,%f]\n"
196 ,i,*(parcur+i),*(minpar+i),*(maxpar+i));
197 return(-2.);
198} }
199
200if ( deb >= 2 ) {
201 printf("\n******************* ENTREE DANS FitFun ");
202 printf("npar=%d LimitC2=%f\n",npar,LimitC2);
203 printf("parametres"); for(i=0;i<nparsave;i++) printf(" %f",*(parcur+i)); printf("\n");
204 if ( deb >= 3 ) {
205 printf(" ind"); for(i=0;i<nparsave;i++) printf(" %12d",*(ind+i)); printf("\n");
206 printf(" stepar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(stepar+i)); printf("\n");
207 printf(" minpar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(minpar+i)); printf("\n");
208 printf(" maxpar"); for(i=0;i<nparsave;i++) printf(" %12.5g",*(maxpar+i)); printf("\n");
209} }
210
211/* premiere essai avec les parametres d'initialisation */
212
213FitFun_MrqCof(FunFit,type,temps,mag,err,ndata,I1,I2,parcur,npar,ind,ALPHA[0],BETA,&ci2,deb);
214
215ci20 = ci2;
216lambda = 0.001;
217
218if ( *ndata < npar ) {
219 printf("le nombre de donnees %d est inferieur au nombre de parametres %d\n",*ndata,npar);
220 return(-3.);
221}
222
223if ( deb >= 2 ) printf("Passage d'initialisation ci2= %e, lambda=%e\n",ci2,lambda);
224
225/* et maintenant les iterations */
226
227nstep = 0;
228/************************ ITERATIONS *******************************************/
229ITERATE:
230nstep++;
231
232if ( deb >= 2 ) printf("------------------------- pas %d\n",nstep);
233
234if(nstep > NstepMX) {
235 printf("FitFun: Le fit n'a pas converge (trop d'iterations %d).\n",nstep);
236 if (deb>0 ) {
237 printf("== Parametres finals:");
238 for(k=0;k<nparsave;k++) printf(" %15.8e",parcur[k]); printf("\n");
239 for(i=0;i<npar;i++) { *(epar+ind[i]) = -1.; par[ind[i]] = parcur[ind[i]];}
240 }
241 return(-4.);
242}
243
244for(j=0;j<npar;j++) {
245 for(i=0;i<npar;i++) ATGA[j][i] = ALPHA[j][i];
246 ATGA[j][j] *= 1.0 + lambda;
247}
248
249/* inversion de ( At * G * A ) */
250if( GausPiv(ATGA[0],NPAR_FITFUN,npar,COVAR[0],NPAR_FITFUN,npar,1) == 0. ) {
251 printf("La matrice des erreurs n'est pas inversible\n");
252 return(-1.);
253}
254if( deb >= 3 ) {
255 printf("matrice 1/( At * G * A )\n");
256 for ( i=0; i<npar; i++ ) {
257 for ( j=0; j<npar; j++ ) printf(" %15.8e",COVAR[i][j]);
258 printf("\n");
259} }
260
261/* compute next increment */
262for(i=0;i<npar;i++) {
263 DA[i] = 0.;
264 for(j=0;j<npar;j++) DA[i] += COVAR[i][j] * BETA[j];
265}
266if ( deb >= 2 ) {
267 printf("Correction parametres proposee:");
268 for (i=0;i<npar;i++) printf(" %12.5e",DA[i]); printf("\n");
269}
270
271/* on s'arrete la, il y a eu convergence */
272if ( lambda == 0. ) {
273 for(i=0;i<npar;i++) { *(epar+ind[i]) = sqrt(COVAR[i][i]); par[ind[i]] = parcur[ind[i]];}
274 if (deb>0 ) {
275 printf("===============================================================\n");
276 printf("== ci2= %15.8e (%15.8e) ndata= %d nstep= %d\n",ci2,ci2/(*ndata-npar+1),*ndata,nstep);
277 printf("== Parametres finals:"); for(k=0;k<nparsave;k++) printf(" %15.8e", par[k]); printf("\n");
278 printf("== +/- "); for(k=0;k<nparsave;k++) printf(" %15.8e",epar[k]); printf("\n");
279 printf("===============================================================\n");
280 }
281 return( (float) ci2 );
282}
283
284/* essai des nouveaux parametres */
285for(j=0;j<npar;j++) {
286 k = ind[j];
287 if( nstep == 1 && fabs(DA[j]) > stepar[k] ) {
288 partry[k] = parcur[k] + stepar[k] * DA[j] / fabs(DA[j]);
289 } else {
290 partry[k] = parcur[k] + DA[j];
291 }
292 if(maxpar[k] > minpar[k] ) {
293 if( partry[k] < minpar[k] ) {
294 partry[k] = minpar[k];
295 if(deb>=2) printf("Parametre %3d limite au minimum %e\n",k,partry[k]);
296 }
297 if( partry[k] > maxpar[k] ) {
298 partry[k] = maxpar[k];
299 if(deb>=2) printf("Parametre %3d limite au maximum %e\n",k,partry[k]);
300 }
301} }
302if ( deb>=2)
303 {
304 printf("essai avec");
305 for(k=0;k<nparsave;k++) printf(" %15.8e", partry[k]);
306 printf("\n");
307 }
308
309/* calcul du nouveau ci2 avec partry */
310FitFun_MrqCof(FunFit,type,temps,mag,err,ndata,I1,I2,partry,npar,ind,ATGA[0],DA,&ci2,deb);
311if(deb>=2) printf("Ci2: old=%e new=%e %e\n",ci20,ci2,ci2-ci20);
312
313/* test sur l'evolution du ci2 et la strategie a suivre */
314if ( ci2 < ci20 ) {
315 nstop = 0;
316 for (j=0;j<npar;j++) {
317 for(i=0;i<npar;i++) ALPHA[j][i] = ATGA[j][i];
318 BETA[j] = DA[j];
319 parcur[ind[j]] = partry[ind[j]];
320 }
321 lambda *= 0.1;
322 if( ci20 - ci2 < LimitC2 ) lambda = 0.;
323 ci20 = ci2;
324 if(deb>=2) {
325 printf("lambda divided by 10. %e\n",lambda);
326 printf("Nouveaux parametres"); for(k=0;k<nparsave;k++) printf(" %12.5e",parcur[k]); printf("\n");
327 }
328} else {
329 /* on arrete si pas assez de variation de chi2 + pas assez de variation de parametres */
330 if( ci2 - ci20 < LimitC2 ) {
331 k=0;
332 for(i=0;i<npar;i++) if( fabs( parcur[ind[i]] - partry[ind[i]] ) < eps ) k++;
333 if(k == npar) { nstop++; } else { nstop=0;};
334 /* printf("ci2-ci20=%f npar=%d (%d) nstop=%d\n"
335 ,ci2-ci20,npar,k,nstop); */
336 } else {
337 nstop = 0;
338 }
339 lambda *= 10.;
340 if(nstop>=nstopMX) lambda = 0.;
341 ci2 = ci20;
342 if(deb>=2) printf("Echec essai, lambda multiplied by 10. %e\n",lambda);
343}
344
345goto ITERATE;
346
347}
348
349/*=========================================================================*/
350void FitFun_MrqCof(double (*FunFit) (double ,double *,double *) ,int_4 type
351 ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err
352 ,int_4 *ndata,int_4 I1,int_4 I2
353 ,double *parcur,int_4 npar,int_4 *ind
354 ,double *ATGA,double *BETA,double *ci2,int_4 deb)
355{
356int_4 i, j, k;
357double deriv[NPAR_FITFUN], t, f, e, Gkk, Ck, funfit;
358
359for (i=0; i<npar;i++) { BETA[i] = 0.; for (j=0; j<npar;j++) *(ATGA+i*NPAR_FITFUN+j) = 0.;}
360*ci2 = 0.;
361*ndata = 0;
362
363/* calcul de ( At * G * A ) */
364for (k=I1; k<=I2; k++) {
365 e = (type == FITFUN_FLOAT) ? *(err.fx + k) : *(err.dx + k);
366 if ( e > 0. ) {
367 (*ndata)++;
368 t = (type == FITFUN_FLOAT) ? *(temps.fx + k) : *(temps.dx + k);
369 f = (type == FITFUN_FLOAT) ? *(mag.fx + k) : *(mag.dx + k);
370 funfit = FunFit(t,parcur,deriv);
371 Gkk = 1./e/e;
372 Ck = f - funfit;
373 *ci2 += Ck*Ck*Gkk;
374 for ( j=0; j<npar; j++ ) {
375 for ( i=j; i<npar; i++ ) *(ATGA+i*NPAR_FITFUN+j) += deriv[ind[i]] * Gkk * deriv[ind[j]];
376 BETA[j] += deriv[ind[j]] * Gkk * Ck;
377} } }
378
379for(j=1;j<npar;j++) for(i=0;i<j;i++) *(ATGA+i*NPAR_FITFUN+j) = *(ATGA+j*NPAR_FITFUN+i);
380
381if( deb >= 3 ) {
382 printf("matrice ( At * G * A )\n");
383 for ( i=0; i<npar; i++ ) {
384 for ( j=0; j<npar; j++ ) printf(" %15.8e",*(ATGA+i*NPAR_FITFUN+j));
385 printf("\n");
386 }
387 printf("BETA:");
388 for ( j=0; j<npar; j++ ) printf(" %15.8e",BETA[j]);
389 printf("\n");
390}
391
392}
393
394/*=========================================================================*/
395/* Christophe 8/11/93 La Silla */
396/*
397++
398double GausPiv(double *A,int_4 nca,int_4 n,double *B,int_4 ncb,int_4 m,int_4 Inv)
399 Inversion de matrice par la methode du pivot de Gauss.
400--
401*/
402/*
403++
404| Inv=0: resolution d'un systeme A(n,n) * X(n,m) = B(n,m)
405| en entree matrices A,B de taille A[?>=n][nca>=n] et B[?>=n][ncb>=m]
406| en sortie la matrice B contient le resultat X
407| Inv#0: inversion de la matrice A(n,n)
408| en entree matrice A
409| en sortie la matrice B contient le resultat 1/A
410| GausPiv: retourne le determinant (0. si non-inversible!)
411--
412*/
413/*
414++
415|Remarque:
416|-matrice A[?>=n][nca>=n],
417| element Aij = "A'[i][j] de ss matrice A'[n][n]" = *(A+i*nca+j)
418| ou 0<=i<n indice de ligne; ou 0<=j<n indice de colonne;
419|-matrice B[?>=n][ncb>=m],
420| element Bij = "B'[i][j] de ss matrice B'[n][m]" = *(B+i*ncb+j)
421| ou 0<=i<n indice de ligne; ou 0<=j<m indice de colonne;
422|exemple 1: on veut resoudre le systeme A(4,4) * X = B(4,3)
423| et on definit dans le prog appelant: double A[12][7],B[32][5]
424| on appelle: GausPiv(&A[0][0],7,4,&B[0][0],5,3,0)
425|exemple 2: on veut resoudre le systeme A(4,4) * X = B(4)
426| et on definit dans le prog appelant: double A[4][4],B[4]
427| on appelle: GausPiv(A[0],4,4,B,1,1,0)
428|exemple 3: on veut resoudre le systeme A(4,4) * X = B(4)
429| et on definit dans le prog appelant: double A[9][4],B[7,3]
430| on appelle: GausPiv(A[0],4,4,B,3,1,0)
431|Methode: methode de gauss avec choix du pivot maximum
432|Reference: Statistical and Computational Methods in Data Analysis
433| Siegmund Brandt, North-Holland 1970 p 350-361.
434|Attention: la matrice A est detruite et la matrice B aussi (evidemment)
435--
436*/
437double GausPiv(double *A,int_4 nca,int_4 n,double *B,int_4 ncb,int_4 m,int_4 Inv)
438{
439int_4 deb=DEB_GausPiv;
440int_4 i,j,k,l,i1,i2,j1,j2,j3,j4,ij,ii,il,lj,kj,k1,nj,kk,ik,nn,kmax,i1max;
441double amax,save,det;
442
443if ( n < 1 ) {
444 printf("GausPiv: pas de resolution de systeme de dimension %d\n",n);
445 return(0.);
446}
447
448/* ********************************************************** */
449/* cas d'une inversion de matrice: on met B = matrice identite*/
450/* ********************************************************** */
451if ( Inv != 0 ) {
452 if ( m != n ) {
453 printf("GausPiv: Vous voulez inverser une matrice non carree %d %d\n",n,m);
454 return(0.);
455 }
456 for (i=0;i<n;i++) {
457 for (j=0;j<n;j++) {
458 if ( i != j ) { *(B+i*ncb+j) = 0.; } else { *(B+i*ncb+j) = 1.;}
459} } }
460
461if ( deb>0 ) {
462 printf("** Matrices de depart\n");
463 printf("Matrice A %d %d:\n",nca,n);
464 for (i=0;i<n;i++) {
465 for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
466 printf("\n");
467 }
468 printf("Matrice B %d %d:\n",ncb,m);
469 for (i=0;i<n;i++) {
470 for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
471 printf("\n");
472} }
473
474/* ***************************************************************** */
475/* reduction de la matrice A a la forme triangulaire superieure */
476/* ***************************************************************** */
477det=1.;
478kmax = n-1;
479for (k=0;k<kmax;k++) { /* on travaille sur la ligne k */
480 if ( deb>0 ) printf("-----> reduction ligne %d\n",k);
481 amax=0.; /*recherche du plus grand coeff pour le pivot*/
482 j2=k; /* dans col k pour les lignes >= k */
483 for (j1=k;j1<n;j1++) {
484 ik = j1*nca+k;
485 if( fabs(amax)-fabs(*(A+ik)) < 0. ) {
486 amax = *(A+ik);
487 j2 = j1;
488 } }
489 if ( deb>0 ) printf("pivot sur la ligne %d max= %f\n",j2,amax);
490 if ( j2 != k ) { /* echange des lignes k et j2 si necessaire*/
491 for (j=k;j<n;j++) {
492 j3=k*nca+j;
493 j4=j2*nca+j;
494 save = *(A+j3);
495 *(A+j3) = *(A+j4);
496 *(A+j4) = save;
497 }
498 for (j=0;j<m;j++) {
499 j3=k*ncb+j;
500 j4=j2*ncb+j;
501 save = *(B+j3);
502 *(B+j3) = *(B+j4);
503 *(B+j4) = save;
504 }
505 if ( deb>0 ) {
506 printf("Matrice A echange des lignes %d et %d :\n",k,j2);
507 for (i=0;i<n;i++) {
508 for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
509 printf("\n");
510 }
511 printf("Matrice B echange des lignes %d et %d :\n",k,j2);
512 for (i=0;i<n;i++) {
513 for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
514 printf("\n");
515 } } }
516 k1=k+1; /* on effectue la substitution-soustraction sur les lignes qui suivent*/
517 kk = k*nca+k; /* c'est le pivot*/
518 if ( deb>0 ) printf("valeur du pivot %f\n",*(A+kk));
519 if ( *(A+kk) == 0. ) {
520 /* printf("Matrice non-inversible: pivot %d nul\n",k); */
521 return(0.);
522 } else { det *= *(A+kk); }
523 for (i=k1;i<n;i++) {
524 ik = i*nca+k; /* c est le premier element de la ligne i */
525 for (j=k1;j<n;j++) {
526 ij= i*nca+j;
527 kj= k*nca+j;
528 *(A+ij) += -*(A+kj) * *(A+ik) / *(A+kk);
529 }
530 for (j=0;j<m;j++) {
531 ij= i*ncb+j;
532 kj= k*ncb+j;
533 *(B+ij) += -*(B+kj) * *(A+ik) / *(A+kk);
534 } }
535 if ( deb>0 ) {
536 printf("Matrice A:\n");
537 for (i=0;i<n;i++) {
538 for (j=0;j<n;j++) printf(" %15.8e",*(A+i*nca+j));
539 printf("\n");
540 }
541 printf("Matrice B:\n");
542 for (i=0;i<n;i++) {
543 for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
544 printf("\n");
545} } } /* fin du travail sur la ligne k */
546det *= *(A+(n-1)*nca+(n-1));
547if ( deb>0 ) printf("Determinant de A= %e\n",det);
548
549/* ********************************************************** */
550/* back substitution */
551/* ********************************************************** */
552nn=(n-1)*nca+(n-1); /* l'element (n,n) */
553for (j=0;j<m;j++) {
554 nj=(n-1)*ncb+j;
555 if ( *(A+nn) == 0. ) {
556 /* printf("Matrice non-inversible pivot (%d,%d) nul\n",n-1,n-1); */
557 return(0.);
558 }
559 *(B+nj) /= *(A+nn); /* la derniere ligne traitee a part*/
560 i1max=n-1;
561 if( i1max >= 0 ) { /* les lignes n-1 a 1 dans cet ordre*/
562 for(i1=1;i1<=i1max;i1++) {
563 i=n-1-i1; /* ici i va de n-2 a 0 */
564 ij=i*ncb+j;
565 ii=i*nca+i;
566 i2=i+1; /* pour la ligne i on somme de i+1 a n */
567 for (l=i2;l<n;l++) {
568 il=i*nca+l;
569 lj=l*ncb+j;
570 *(B+ij) -= *(A+il) * *(B+lj);
571 }
572 if ( *(A+ii) == 0. ) {
573 /* printf("Matrice non-inversible pivot (%d,%d) nul\n",i,i); */
574 return(0.);
575 }
576 *(B+ij) /= *(A+ii);
577} } }
578if ( deb>0 ) {
579 printf("-----> Matrice B resultat:\n");
580 for (i=0;i<n;i++) {
581 for (j=0;j<m;j++) printf(" %15.8e",*(B+i*ncb+j));
582 printf("\n");
583} }
584return(det);
585}
586
587/*=========================================================================*/
588/* CMV 17/11/92 */
589/*
590++
591int_4 paramga -
592 (float sxin, float syin, float rhoin -
593 , float *smax, float *axisrat, float *tiltdeg)
594
595 Pour transformer le sx,sy,rho d'une gaussienne en sa,sc/sa,teta.
596--
597*/
598/*
599++
600| - input : sx ]0,inf] ,sy ]0,inf] ,rho ]-1,+1[
601| - output : smax (longeur du grand axe), axisrat (rapport des axes ]0.,1.])
602| tiltdeg (angle entre le grand axe et l'axe ox en degre ]-90,+90])
603| - Les fonctions sont:
604| exp[-0.5*{[(x/SX)**2-2*RHO/(SX*SY)*x*y+(y/SY)**2]/(1-RHO**2)}]
605| exp[-0.5*{ (A/SA)**2 +(C/SC)**2 }]
606| - Remarque: sx,sy representent les sigmas des variables x,y et
607| sont differents des sigmas des coupes x=0 et y=0 qui valent:
608| sigmaX(y=0) = sx*sqrt(1-ro^2) different de sx
609| sigmaY(x=0) = sy*sqrt(1-ro^2) different de sy
610--
611*/
612int_4 paramga(float sxin, float syin, float rhoin
613 , float *smax, float *axisrat, float *tiltdeg)
614/*
615Cf Formulae and Methods in Experimental Data Evaluation Vol. 1
616rechercher a Bivariate gaussian distribution
617*/
618{
619double sx,sy,rho,a,b,c,alpha,coscar,sincar,cossin,sa,sc;
620
621*smax = 0.; *axisrat = 0.; *tiltdeg = 0.; a = 0.; b = 0.; c = 0.;
622
623/* lecture des arguments */
624sx = sxin; sy = syin; rho = rhoin;
625
626/* cas des coniques degenerees ou erreurs dans les parametres*/
627if ( sx <= 0. || sy <= 0. || rho > 1. || rho < -1. ) return(-1);
628
629/* sortie fit : [(x/SX)**2 - 2*RHO/(SX*SY)*x*y + (y/SY)**2]/(1-RHO**2) = 1
630 equation ellipse: A*x**2 + 2*B*x*y + C*y**2 = 1 */
631sa = (1.-rho*rho);
632a = 1./sx/sx/sa; b = -rho/sx/sy/sa; c = 1./sy/sy/sa;
633
634/* cas des coniques degenerees (droites limites) */
635if ( rho == 1. || rho == -1. ) return(-2);
636
637/* axes principaux OX OY pour : x = cos(ALPHA)*X - sin(APLHA)*Y
638 (ALPHA = (ox,oX)) y = sin(ALPHA)*X + cos(APLHA)*Y
639 soit ( A*cos**2 + C*sin**2 + 2*B*cos*sin )*X**2
640 + ( A*sin**2 + C*cos**2 - 2*B*cos*sin )*Y**2
641 + 2*( -A*cos*sin + C*cos*sin + B*(cos**2-sin**2) )*X*Y
642 = (X/SA)**2 + (Y/SC)**2 = 1
643 et oX oY axes principaux pour : Tan ( 2*ALPHA ) = 2*B/(A-C) */
644
645if ( a == c && rho == 0. ) {
646 /* cas d'un cercle */
647 coscar = 0.5; sincar = coscar; cossin = coscar; alpha = 0.;
648} else {
649 if ( a == c ) {
650 /* cas SX=SY ellipse a +/-45 degres */
651 if ( rho > 0. ) {
652 /* cas +45 degres */
653 alpha = Pi / 4.;
654 } else {
655 /* cas -45 degres */
656 alpha = -Pi / 4.;
657 }
658 } else {
659 /* cas general */
660 alpha = atan(2.*b/(a-c)) /2.;
661 }
662 coscar = cos(alpha);
663 sincar = sin(alpha);
664 cossin = coscar*sincar;
665 coscar *= coscar;
666 sincar *= sincar;
667 alpha *= 180./Pi;
668}
669
670sa = a*coscar+c*sincar+2.*b*cossin;
671sc = c*coscar+a*sincar-2.*b*cossin;
672sa = ( sa < 0. ) ? 1./sqrt(-sa) : 1./sqrt(sa);
673sc = ( sc < 0. ) ? 1./sqrt(-sc) : 1./sqrt(sc);
674
675if ( sa >= sc ) {
676 *smax = sa;
677 *axisrat = sc/sa;
678 *tiltdeg = alpha;
679} else {
680 *smax = sc;
681 *axisrat = sa/sc;
682 *tiltdeg = alpha+90.;
683 if ( *tiltdeg > 90. ) *tiltdeg = *tiltdeg-180.;
684}
685
686return(0);
687}
688
689/*========================================================================*/
690/* CMV 21/01/94 */
691/*
692++
693int_4 gaparam -
694 (float smax, float axisrat, float tiltdeg -
695 , float *sxin, float *syin, float *rhoin)
696
697 Pour transformer le sa,sc/sa,tiltdeg d'une gaussienne en sx,sy,rho
698 Pour calculer les parametres d'une gaussienne
699--
700*/
701/*
702++
703| - input : sa ]0,inf] ,axisrat ]0,1] ,tiltdeg ]-90,+90]
704| sa (longeur du grand axe), axisrat (rapport des axes )
705| tiltdeg (angle entre le grand axe et l'axe ox en degre)
706| - output : sx ]0,inf] , sy ]0,inf] , rho ]-1,1[
707| - Les fonctions sont:
708| exp[-0.5*{ (A/SA)**2 +(C/SC)**2 }]
709| exp[-0.5*{[(x/SX)**2-2*RHO/(SX*SY)*x*y+(y/SY)**2]/(1-RHO**2)}]
710| - Voir aussi la remarque de la fonction paramga.
711--
712*/
713int_4 gaparam(float smax, float axisrat, float tiltdeg
714 , float *sxin, float *syin, float *rhoin)
715{
716double sx,sy,rho,alpha,coscar,sincar,cossin,sa,sc,a,b,c;
717
718*sxin = 0.; *syin = 0.; *rhoin = 0.;
719
720/* cas des coniques degenerees ou erreurs dans les parametres*/
721if ( smax <= 0. || axisrat <= 0. || axisrat > 1. ) return(-1);
722
723/* lecture des arguments */
724sa = smax; sc = sa*axisrat; alpha = tiltdeg*Pi/180.;
725
726coscar = cos(alpha);
727sincar = sin(alpha);
728cossin = coscar*sincar;
729coscar *= coscar;
730sincar *= sincar;
731
732a = 1./(coscar/sa/sa + sincar/sc/sc);
733 a = sqrt(a); /* = sqrt(1-ro**2)*sx */
734b = 1./(sincar/sa/sa + coscar/sc/sc);
735 b = sqrt(b); /* = sqrt(1-ro**2)*sy */
736c = cossin*(-1./sa/sa + 1./sc/sc);
737rho = c*a*b;
738sx = a / sqrt(1.-rho*rho);
739sy = b / sqrt(1.-rho*rho);
740
741*sxin = sx; *syin = sy; *rhoin = rho;
742
743return(0);
744}
745
746/*===================================================================*/
747/*
748++
749double nberfc(double x)
750 Erreur fonction complementaire: -log10(erfc)
751 Pratiquement pour avoir la proba que
752 ]-inf,-x] U [x,+inf[ selon une loi gaussiene centree et normee
753 il faut appeler nberfc(x/sqrt(2))
754 Le job tiens compte de la saturation machine pour x grand.
755 La valeur est approximee au developpement limite de erfc
756 ( see . Abramowitz p299 7.1.23 )
757--
758*/
759double nberfc(double x)
760{
761double v;
762if(x<0.) return(0.);
763if ( x < 10. ) {
764 v = erfc(x);
765 v = -log10(v);
766} else {
767 v = 2.*x*x;
768 v = 1./v - 3./(v*v) + 15./(v*v*v);
769 v += LnPi/2. + log(x) + x*x;
770 v /= Ln10;
771}
772return(v);
773}
774
775/*=========================================================================*/
776/*
777++
778float probnb(float sci2,int_4 inddl,int_4 *ipass)
779 Retourne -log10(p) ou p est la probabilte que le chi2
780 d'une fluctuation inddl points soit superieur a sci2.
781 ipass est le type de calcul utilise.
782--
783*/
784float probnb(float sci2,int_4 inddl,int_4 *ipass)
785{
786int_4 it;
787float nddl;
788double ci2,a1,a2,p,q,val,terme1,terme2,terme3,terme4,teradd,xnprim;
789
790*ipass = 0;
791val = 0.;
792nddl = inddl;
793ci2 = sci2;
794a1 = nddl/2.;
795a2 = ci2/2.;
796
797q = nbgammq(a1,a2);
798if(q>0. && q<1.) {
799 val = -log10(q); /* moins le log10 de la proba que le chi2 soit > ci2 */
800 *ipass = 1;
801} else if ( q==1.) {
802 p = nbgammp(a1,a2);
803 val = p/Ln10; /* -log10(q) = -log(1-p)/Ln10 = -(p)/Ln10 = p/Ln10 */
804 *ipass = 2;
805} else {
806 /* approximation de mimile */
807 xnprim = nddl / 2. - 1.;
808 terme1 = nddl / 2. * Log2; /* 1/2**n */
809 terme2 = Hln2pi + (xnprim+0.5)*log(xnprim) - xnprim + 1./(12.*xnprim);
810 terme2 /= Ln10; /* formule de stirling pour Gamma[nddl/2] */
811 terme3 = ci2/2. - xnprim*log(ci2);
812 terme3 /= Ln10; /* exp(-ci2/2)*ci2**(n/2-1) */
813 terme4 = teradd = 1.;
814 for ( it=1; it <= inddl-2; it +=2) {
815 teradd *= ( (double) (nddl -1.) - (double) it ) / ci2;
816 terme4 += teradd;
817 if ( teradd < 1.e-4 ) break;
818 }
819 terme4 = -log10(2.*terme4);
820 val = terme1 + terme2 + terme3 + terme4;
821 *ipass = 3;
822}
823return ((float) val);
824}
825
826/*=========================================================================*/
827/*
828++
829double nbgammln(double xx)
830 Fonction log de la fonction Gamma
831--
832*/
833double nbgammln(double xx)
834{
835 double x,tmp,ser;
836 static double cof[6]={76.18009173,-86.50532033,24.01409822,
837 -1.231739516,0.120858003e-2,-0.536382e-5};
838 int_4 j;
839
840 x=xx-1.0;
841 tmp=x+5.5;
842 tmp -= (x+0.5)*log(tmp);
843 ser=1.0;
844 for (j=0;j<=5;j++) {
845 x += 1.0;
846 ser += cof[j]/x;
847 }
848 return -tmp+log(2.50662827465*ser);
849}
850
851/*=========================================================================*/
852/*
853++
854double nbgammq(double a,double x)
855 Fonction GammaQ
856--
857*/
858double nbgammq(double a,double x)
859{
860 double gamser,gammcf,gln;
861
862 if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMQ (%f,%f)\n"
863 ,a,x); exit(-1);}
864 if (x < (a+1.0)) {
865 nbgser(&gamser,a,x,&gln);
866 return 1.0-gamser;
867 } else {
868 nbgcf(&gammcf,a,x,&gln);
869 return gammcf;
870 }
871}
872
873/*=========================================================================*/
874/*
875++
876double nbgammp(double a,double x)
877 Fonction GammaP
878--
879*/
880double nbgammp(double a,double x)
881{
882 double gamser,gammcf,gln;
883
884 if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMP (%f,%f)\n"
885 ,a,x); exit(-1);}
886 if (x < (a+1.0)) {
887 nbgser(&gamser,a,x,&gln);
888 return gamser;
889 } else {
890 nbgcf(&gammcf,a,x,&gln);
891 return 1.0-gammcf;
892 }
893}
894
895/*=========================================================================*/
896void nbgcf(double *gammcf,double a,double x,double *gln)
897{
898 int_4 n;
899 double gold=0.0,g,fac=1.0,b1=1.0;
900 double b0=0.0,anf,ana,an,a1,a0=1.0;
901
902 *gln=nbgammln(a);
903 a1=x;
904 for (n=1;n<=ITMAX;n++) {
905 an=(double) n;
906 ana=an-a;
907 a0=(a1+a0*ana)*fac;
908 b0=(b1+b0*ana)*fac;
909 anf=an*fac;
910 a1=x*a0+anf*a1;
911 b1=x*b0+anf*b1;
912 if (a1) {
913 fac=1.0/a1;
914 g=b1*fac;
915 if (fabs((g-gold)/g) < EPS) {
916 *gammcf=exp(-x+a*log(x)-(*gln))*g;
917 return;
918 }
919 gold=g;
920 }
921 }
922 printf("a too large, ITMAX too small in routine NBGCF (%f,%f)\n",a,x); exit(-1);
923}
924
925/*=========================================================================*/
926void nbgser(double *gamser,double a,double x,double *gln)
927{
928 int_4 n;
929 double sum,del,ap;
930
931 *gln=nbgammln(a);
932 if (x <= 0.0) {
933 if (x < 0.0) { printf("x less than 0 in routine NBGSER (%f,%f)\n",a,x); exit(-1); }
934 *gamser=0.0;
935 return;
936 } else {
937 ap=a;
938 del=sum=1.0/a;
939 for (n=1;n<=ITMAX;n++) {
940 ap += 1.0;
941 del *= x/ap;
942 sum += del;
943 if (fabs(del) < fabs(sum)*EPS) {
944 *gamser=sum*exp(-x+a*log(x)-(*gln));
945 return;
946 }
947 }
948 printf("a too large, ITMAX too small in routine NBGSER (%f,%f)\n",a,x); exit(-1);
949 return;
950 }
951}
952
953/*==========================================================================*/
954/*
955++
956void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW)
957 Set mIhoqN,IhoqNX,IhoqNW pour integration Gauss-Legendre
958--
959*/
960void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW)
961{
962switch (degre) {
963 case 2:
964 *mIhoqN = mIhoq2;
965 IhoqNX = Ihoq2X;
966 IhoqNW = Ihoq2W;
967 break;
968 case 3:
969 *mIhoqN = mIhoq3;
970 IhoqNX = Ihoq3X;
971 IhoqNW = Ihoq3W;
972 break;
973 case 4:
974 *mIhoqN = mIhoq4;
975 IhoqNX = Ihoq4X;
976 IhoqNW = Ihoq4W;
977 break;
978 case 5:
979 *mIhoqN = mIhoq5;
980 IhoqNX = Ihoq5X;
981 IhoqNW = Ihoq5W;
982 break;
983 case 6:
984 *mIhoqN = mIhoq6;
985 IhoqNX = Ihoq6X;
986 IhoqNW = Ihoq6W;
987 break;
988 case 7:
989 *mIhoqN = mIhoq7;
990 IhoqNX = Ihoq7X;
991 IhoqNW = Ihoq7W;
992 break;
993 case 8:
994 *mIhoqN = mIhoq8;
995 IhoqNX = Ihoq8X;
996 IhoqNW = Ihoq8W;
997 break;
998 case 9:
999 *mIhoqN = mIhoq9;
1000 IhoqNX = Ihoq9X;
1001 IhoqNW = Ihoq9W;
1002 break;
1003 case 10:
1004 *mIhoqN = mIhoq10;
1005 IhoqNX = Ihoq10X;
1006 IhoqNW = Ihoq10W;
1007 break;
1008 case 16:
1009 *mIhoqN = mIhoq16;
1010 IhoqNX = Ihoq16X;
1011 IhoqNW = Ihoq16W;
1012 break;
1013 default:
1014 *mIhoqN = mIhoq8;
1015 IhoqNX = Ihoq8X;
1016 IhoqNW = Ihoq8W;
1017 break;
1018}
1019return;
1020}
1021
1022/*==========================================================================*/
1023/*
1024++
1025int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw)
1026 Ecrit les positions et les poids pour l'integration de Gauss-Legendre
1027 dans les tableaux *ihoqnx,*ihoqnw.
1028 Retourne le nombre de points.
1029 Si *ihoqnx==NULL ou *ihoqnw==NULL
1030 retourne seulement le nombre de points (cad la taille minimale
1031 que doivent les tableaux *ihoqnx,*ihoqnw).
1032--
1033*/
1034int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw)
1035{
1036int mIhoqN, i;
1037double *IhoqNX, *IhoqNW;
1038switch (degre) {
1039 case 2:
1040 mIhoqN = mIhoq2;
1041 IhoqNX = Ihoq2X;
1042 IhoqNW = Ihoq2W;
1043 break;
1044 case 3:
1045 mIhoqN = mIhoq3;
1046 IhoqNX = Ihoq3X;
1047 IhoqNW = Ihoq3W;
1048 break;
1049 case 4:
1050 mIhoqN = mIhoq4;
1051 IhoqNX = Ihoq4X;
1052 IhoqNW = Ihoq4W;
1053 break;
1054 case 5:
1055 mIhoqN = mIhoq5;
1056 IhoqNX = Ihoq5X;
1057 IhoqNW = Ihoq5W;
1058 break;
1059 case 6:
1060 mIhoqN = mIhoq6;
1061 IhoqNX = Ihoq6X;
1062 IhoqNW = Ihoq6W;
1063 break;
1064 case 7:
1065 mIhoqN = mIhoq7;
1066 IhoqNX = Ihoq7X;
1067 IhoqNW = Ihoq7W;
1068 break;
1069 case 8:
1070 mIhoqN = mIhoq8;
1071 IhoqNX = Ihoq8X;
1072 IhoqNW = Ihoq8W;
1073 break;
1074 case 9:
1075 mIhoqN = mIhoq9;
1076 IhoqNX = Ihoq9X;
1077 IhoqNW = Ihoq9W;
1078 break;
1079 case 10:
1080 mIhoqN = mIhoq10;
1081 IhoqNX = Ihoq10X;
1082 IhoqNW = Ihoq10W;
1083 break;
1084 case 16:
1085 mIhoqN = mIhoq16;
1086 IhoqNX = Ihoq16X;
1087 IhoqNW = Ihoq16W;
1088 break;
1089 default:
1090 mIhoqN = mIhoq8;
1091 IhoqNX = Ihoq8X;
1092 IhoqNW = Ihoq8W;
1093 break;
1094}
1095if( ihoqnx!=NULL && ihoqnw!=NULL ) {
1096 for(i=0;i<mIhoqN;i++) {
1097 ihoqnx[i] = IhoqNX[i];
1098 ihoqnw[i] = IhoqNW[i];
1099 }
1100}
1101return(mIhoqN);
1102}
1103
1104/*===================================================================*/
1105#define EPS_gauleg 3.0e-11
1106/*
1107++
1108void nbgauleg(double x1,double x2,double *x,double *w,int n)
1109 Integration des fonctions a une dimension y=f(x)
1110 par la Methode de Gauss-Legendre.
1111 Calcul des coefficients du developpement
1112--
1113*/
1114/*
1115++
1116| INPUT:
1117| x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5)
1118| n = degre du developpement
1119| OUTPUT:
1120| x[] = valeur des abscisses ou l'on calcule (dim=n)
1121| w[] = valeur des coefficients associes
1122| REMARQUES:
1123| - x et w doivent au moins etre dimensionner a n.
1124| - l'integration est rigoureuse si sur l'intervalle d'integration
1125| la fonction f(x) peut etre approximee par un polynome
1126| de degre 2*m (monome le + haut x**(2*n-1) )
1127| - Voir la fonction Integ_Fun pour un calcul d'ordre 8
1128--
1129*/
1130void nbgauleg(double x1,double x2,double *x,double *w,int n)
1131{
1132 int m,j,i;
1133 double z1,z,xm,xl,pp,p3,p2,p1;
1134
1135 m=(n+1)/2;
1136 xm=0.5*(x2+x1);
1137 xl=0.5*(x2-x1);
1138 for (i=1;i<=m;i++) {
1139 z=cos(3.141592654*(i-0.25)/(n+0.5));
1140 do {
1141 p1=1.0;
1142 p2=0.0;
1143 for (j=1;j<=n;j++) {
1144 p3=p2;
1145 p2=p1;
1146 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
1147 }
1148 pp=n*(z*p1-p2)/(z*z-1.0);
1149 z1=z;
1150 z=z1-p1/pp;
1151 } while (fabs(z-z1) > EPS_gauleg);
1152 x[i-1]=xm-xl*z;
1153 x[n-i]=xm+xl*z;
1154 w[i-1]=2.0*xl/((1.0-z*z)*pp*pp);
1155 w[n-i]=w[i-1];
1156 }
1157}
1158#undef EPS_gauleg
1159
1160/*==========================================================================*/
1161/*
1162++
1163double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
1164 Pour integrer la fonction fonc de xmin a xmax sur npas.
1165 On emploit une methode Higher-order-gaussienne d'ordre 8, ce qui
1166 fait un calcul equivalent de N*npas pas.
1167--
1168*/
1169double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
1170{
1171int i,j;
1172double dlim,sum,xc,xci;
1173
1174if( xmax <= xmin ) return(0.);
1175if( npas <= 0 ) npas=1;
1176sum = 0.;
1177dlim = (xmax-xmin)/npas;
1178for(i=0;i<npas;i++) {
1179 xci = (double) i + 0.5;
1180 for(j=0;j<mIhoq8;j++) {
1181 xc = xmin + ( xci + Ihoq8X[j] ) * dlim;
1182 sum += fonc(xc) * Ihoq8W[j];
1183} }
1184return(sum*dlim);
1185}
1186
1187/*=========================================================================*/
1188/*
1189++
1190double Integ_Fun_2D -
1191 (double (*fonc)(double x,double y) -
1192 ,double xmin,double xmax,double ymin,double ymax -
1193 ,int npasx,int npasy)
1194
1195 Integration 2D de fonc(x,y) dans le carre [xmin,xmax] et [ymin,ymax]
1196--
1197*/
1198double Integ_Fun_2D(double (*fonc)(double x,double y)
1199 ,double xmin,double xmax,double ymin,double ymax
1200 ,int npasx,int npasy)
1201{
1202int i,j;
1203double x,y,pasx,pasy,sum,sumy;
1204
1205pasx = (xmax-xmin)/npasx;
1206pasy = (ymax-ymin)/npasy;
1207
1208sum = 0.;
1209for(i=0;i<npasx;i++) {
1210 x = xmin + ((double) i + 0.5 ) * pasx;
1211 sumy = 0.;
1212 for(j=0;j<npasy;j++) {
1213 y = ymin + ((double) j + 0.5 ) * pasy;
1214 sumy += fonc(x,y);
1215 }
1216 sum += sumy;
1217}
1218return( sum*pasx*pasy);
1219}
1220
1221/*=========================================================================*/
1222/* Christophe 01/07/94 */
1223/*
1224++
1225void Set_FitFunDPol(int DPol)
1226 Pour donner l'ordre du polynome pour le fit.
1227--
1228*/
1229void Set_FitFunDPol(int DPol)
1230{
1231FITFUN_DPOL = DPol;
1232}
1233
1234/*==================================================================*/
1235/* Christophe 01/07/94 */
1236/*
1237++
1238double Gauss1DPolF(double x,double *Par,double *DgDpar)
1239 Fonction de fit Gausienne+polynome.
1240--
1241*/
1242/*
1243++
1244| f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ]
1245| +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
1246| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1247--
1248*/
1249double Gauss1DPolF(double x,double *Par,double *DgDpar)
1250{
1251double f,xc,xc2,e,xpow;
1252int i;
1253
1254xc = (x-Par[1])/Par[2];
1255xc2 = xc*xc;
1256e = exp(-0.5*xc2);
1257f = Par[0]*e;
1258
1259DgDpar[0] = e;
1260DgDpar[1] = xc / Par[2] *f;
1261DgDpar[2] = xc2/ Par[2] *f;
1262
1263if(FITFUN_DPOL>=0) {
1264 xpow = 1.;
1265 for(i=0;i<=FITFUN_DPOL;i++) {
1266 DgDpar[3+i] = xpow;
1267 f += Par[3+i]*xpow;
1268 xpow *= x;
1269 }
1270}
1271
1272return (f);
1273}
1274
1275/*==================================================================*/
1276/* Christophe 29/08/95 */
1277/*
1278++
1279double GaussI1DPol(double x,double *Par,double *DgDpar)
1280 Fonction de fit Gausienne integree+polynome.
1281--
1282*/
1283/*
1284++
1285| f(x) = par[0] / (sqrt(2*Pi)*par[2]) * exp[-0.5*( (x-par[1]) / par[2] )**2 ]
1286| +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
1287| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1288--
1289*/
1290double GaussI1DPol(double x,double *Par,double *DgDpar)
1291{
1292double f,xc,xc2,e,xpow;
1293int i;
1294
1295xc = (x-Par[1])/Par[2];
1296xc2 = xc*xc;
1297e = exp(-0.5*xc2)/(S2Pi*Par[2]);
1298f = Par[0]*e;
1299
1300DgDpar[0] = e;
1301DgDpar[1] = xc / Par[2] *f;
1302DgDpar[2] = (xc2-1.)/ Par[2] *f;
1303
1304if(FITFUN_DPOL>=0) {
1305 xpow = 1.;
1306 for(i=0;i<=FITFUN_DPOL;i++) {
1307 DgDpar[3+i] = xpow;
1308 f += Par[3+i]*xpow;
1309 xpow *= x;
1310 }
1311}
1312
1313return (f);
1314}
1315
1316/*====================================================================*/
1317/* Christophe 01/07/94 */
1318/*
1319++
1320double Polyn1D(double x,double *Par,double *DgDpar)
1321 Fonction de fit de polynome.
1322--
1323*/
1324/*
1325++
1326| f(x) = par[0] + par[1]*x + .... + par[FITFUN_DPOL]*x**FITFUN_DPOL
1327| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1328--
1329*/
1330double Polyn1D(double x,double *Par,double *DgDpar)
1331{
1332double f,xpow;
1333int i,DPol;
1334
1335DPol = (FITFUN_DPOL<0) ? 0 : FITFUN_DPOL ;
1336xpow = 1.;
1337f = 0.;
1338for(i=0;i<=DPol;i++)
1339 {
1340 DgDpar[i] = xpow;
1341 f += Par[i]*xpow;
1342 xpow *= x;
1343 }
1344return (f);
1345}
1346
1347/*=========================================================================*/
1348/*
1349++
1350double FitProp(double *x,double *y,double *ey,int *n,double *a1)
1351 Fit d'une proportion a1: y = a1 * x
1352--
1353*/
1354/*
1355++
1356| Input:
1357| x = tableau des abscisses
1358| y = tableau des ordonnees
1359| ey = erreurs sur les y
1360| n = nombre de donnees en entree
1361| Output:
1362| n = nombre de points utilises (point non utilise si ey<=0)
1363| a1 coefficient
1364| Return:
1365| valeur du xi2 si fit reussi,
1366| -1. si pas assez de points
1367| -2. si determinant negatif
1368--
1369*/
1370double FitProp(double *x,double *y,double *ey,int *n,double *a1)
1371{
1372register int i,np;
1373register double X2,XY,Y2,w;
1374
1375np=0;
1376X2=XY=Y2=*a1=0.;
1377for(i=0;i<*n;i++) {
1378 if(ey[i]<=0.) continue;
1379 np++;
1380 w = ey[i]*ey[i];
1381 X2 += x[i]*x[i]/w;
1382 XY += x[i]*y[i]/w;
1383 Y2 += y[i]*y[i]/w;
1384}
1385*n = np;
1386if(np<1) return(-1.);
1387if(X2==0.) return(-2.);
1388*a1 = XY/X2;
1389w = Y2 + *a1**a1*X2 -2.**a1*XY;
1390return(w);
1391}
1392
1393/*=========================================================================*/
1394/*
1395++
1396double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
1397 Fit d'une droite: y=a0+a1*x
1398--
1399*/
1400/*
1401++
1402| Input:
1403| x = tableau des abscisses
1404| y = tableau des ordonnees
1405| ey = erreurs sur les y
1406| n = nombre de donnees en entree
1407| Output:
1408| n = nombre de points utilises (point non utilise si ey<=0)
1409| a0,a1 coefficients de la droite
1410| Return:
1411| valeur du xi2 si fit reussi,
1412| -1. si pas assez de points
1413| -2. si determinant negatif
1414--
1415*/
1416double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
1417{
1418register int i,np;
1419register double I,X,X2,Y,XY,Y2,w;
1420
1421np=0;
1422Y2=I=X=X2=Y=XY=*a0=*a1=0.;
1423for(i=0;i<*n;i++) {
1424 if(ey[i]<=0.) continue;
1425 np++;
1426 w = ey[i]*ey[i];
1427 I += 1./w;
1428 X += x[i]/w;
1429 X2 += x[i]*x[i]/w;
1430 Y += y[i]/w;
1431 Y2 += y[i]*y[i]/w;
1432 XY += x[i]*y[i]/w;
1433}
1434*n = np;
1435if(np<2) return(-1.);
1436w = X*X-X2*I;
1437if(w==0.) return(-2.);
1438*a1 = (Y*X-XY*I)/w;
1439*a0 = (X*XY-X2*Y)/w;
1440w = Y2 + *a0**a0*I + *a1**a1*X2
1441 + 2.*( - Y**a0 - *a1*XY + *a0**a1*X );
1442return(w);
1443}
1444
1445/*=========================================================================*/
1446/*
1447++
1448double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
1449 Fit d'une parabole: y=a0+a1.x+a2.x^2
1450--
1451*/
1452/*
1453++
1454| Input:
1455| x = tableau des abscisses
1456| y = tableau des ordonnees
1457| ey = erreurs sur les y
1458| n = nombre de donnees en entree
1459| Output:
1460| n = nombre de points utilises (point non utilise si ey<=0)
1461| a0,a1 coefficients de la droite
1462| Return:
1463| valeur du xi2 si fit reussi,
1464| -1. si pas assez de points
1465| -2. si determinant negatif
1466--
1467*/
1468double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
1469{
1470register int i,np;
1471register double I,X,X2,X3,X4,Y,Y2,XY,X2Y,w,x2;
1472
1473np=0;
1474I=X=X2=X3=X4=Y=Y2=XY=X2Y=*a0=*a1=*a2=0.;
1475
1476for(i=0;i<*n;i++) {
1477 if(ey[i]<=0.) continue;
1478 np++;
1479 x2 = x[i]*x[i];
1480 w = ey[i]*ey[i];
1481 I += 1./w;
1482 X += x[i]/w;
1483 X2 += x2/w;
1484 X3 += x2*x[i]/w;
1485 X4 += x2*x2/w;
1486 Y += y[i]/w;
1487 Y2 += y[i]*y[i]/w;
1488 XY += x[i]*y[i]/w;
1489 X2Y += x2*y[i]/w;
1490}
1491*n = np;
1492if(np<3) return(-1.);
1493w = X2*(X2*X2-X3*X) -X*(X3*X2-X4*X) +I*(X3*X3-X4*X2);
1494if(w==0.) return(-2.);
1495*a2 = (Y*(X2*X2-X3*X) -XY*(X*X2-X3*I) +X2Y*(X*X-X2*I) )/w;
1496*a1 = -(Y*(X3*X2-X4*X) -XY*(X2*X2-X4*I) +X2Y*(X2*X-X3*I) )/w;
1497*a0 = (Y*(X3*X3-X4*X2) -XY*(X2*X3-X4*X) +X2Y*(X2*X2-X3*X))/w;
1498w = Y2 + *a0**a0*I + *a1**a1*X2 + *a2**a2*X4
1499 +2.*( -Y**a0 -*a1*XY -*a2*X2Y
1500 +*a0**a1*X +*a0**a2*X2+*a1**a2*X3 );
1501return(w);
1502}
1503
1504/*=========================================================================*/
1505/*
1506++
1507double FitParLin -
1508 (double *xx,double *y,double *ey,int *n,double x0,int Deg_d -
1509 ,double *a0,double *a1,double *b1,double *b2)
1510
1511--
1512*/
1513/*
1514++
1515| Fit d'une parabole: y=a0+b1*(x-x0)+b2*(x-x0)**2
1516| pour x>x0
1517| et d'une droite: y=a0+a1*(x-x0) pour x<=x0
1518| Input:
1519| x = tableau des abscisses
1520| y = tableau des ordonnees
1521| ey = erreurs sur les y
1522| n = nombre de donnees en entree
1523| x0 = abscisse du point pivot (il n'est pas fitte)
1524| Deg_d = degre du fit a droite de x0 (1 ou 2)
1525| Output:
1526| n = nombre de points utilises (point non utilise si ey<=0)
1527| a0,a1 coefficients de la droite
1528| a0,b1,b2 coefficients de la parabole
1529--
1530*/
1531/*
1532++
1533| Return:
1534| valeur du xi2 si fit reussi,
1535| -1. si pas assez de points
1536| -2. si determinant negatif
1537| Remarque:
1538| Il faut evidemment au moins 2 points a gauche du pivot x0
1539| et 3 points a droite du pivot x0
1540| Matrices A * a = B :
1541| | I_ X_g X_d X2_d | | a0 | | Y_ |
1542| | X_g X2_g 0 0 | * | a1 | = | XY_g |
1543| | X_d 0 X2_d X3_d | | b1 | | XY_d |
1544| | X2_d 0 X3_d X4_d | | b2 | | X2Y_d |
1545--
1546*/
1547double FitParLin(double *xx,double *y,double *ey,int *n,double x0,int Deg_d
1548 ,double *a0,double *a1,double *b1,double *b2)
1549{
1550int i,np,npg,npd,nddl;
1551double w,x,x2,A[4][4],B[4];
1552double Y2,I,Y,X_g,X2_g,XY_g,X_d,X2_d,X3_d,X4_d,XY_d,X2Y_d;
1553
1554if( Deg_d<1 || Deg_d>2 ) Deg_d=2;
1555nddl = Deg_d + 2;
1556*a0=*a1=*b1=*b2=0.;
1557Y2=I=Y=X_g=X2_g=XY_g=X_d=X2_d=X3_d=X4_d=XY_d=X2Y_d=0.;
1558np=npg=npd=0;
1559for(i=0;i<*n;i++) {
1560 if(ey[i]<=0.) continue;
1561 np++;
1562 x = xx[i]-x0;
1563 x2 = x*x;
1564 w = ey[i]*ey[i];
1565 I += 1./w;
1566 Y += y[i]/w;
1567 Y2 += y[i]*y[i]/w;
1568 if(x<=0.) {
1569 if(x<0.) npg++;
1570 X_g += x/w;
1571 X2_g += x2/w;
1572 XY_g += x*y[i]/w;;
1573 } else {
1574 npd++;
1575 X_d += x/w;
1576 X2_d += x2/w;
1577 X3_d += x2*x/w;
1578 X4_d += x2*x2/w;
1579 XY_d += x*y[i]/w;;
1580 X2Y_d += x2*y[i]/w;;
1581 }
1582}
1583*n = np;
1584A[0][0] = I;
1585A[1][1] = X2_g;
1586A[3][3] = X4_d;
1587A[0][1] = A[1][0] = X_g;
1588A[0][2] = A[2][0] = X_d;
1589A[3][2] = A[2][3] = X3_d;
1590A[0][3] = A[3][0] = A[2][2] = X2_d;
1591A[1][2] = A[2][1] = A[1][3] = A[3][1] = 0.;
1592B[0] = Y;
1593B[1] = XY_g;
1594B[2] = XY_d;
1595B[3] = X2Y_d;
1596if( np<4 || npg < 1 || npd < 2 ) return(-1.);
1597w = GausPiv(&A[0][0],4,nddl,B,1,1,0);
1598if(w==0.) return(-2.);
1599*a0 = B[0];
1600*a1 = B[1];
1601*b1 = B[2];
1602if(nddl==4) *b2 = B[3];
1603w = Y2 + *a0**a0*I + *a1**a1*X2_g + *b1**b1*X2_d + *b2**b2*X4_d
1604 + 2.*( - *a0*Y - *a1*XY_g + *a0**a1*X_g
1605 - *b1*XY_d - *b2*X2Y_d + *a0**b1*X_d + *a0**b2*X2_d + *b1**b2*X3_d
1606 );
1607return(w);
1608}
1609
1610/*=========================================================================*/
1611/*
1612++
1613double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
1614 Fit de y(i) = a1*x(i) en deux passes:
1615--
1616*/
1617/*
1618++
1619| 1-/ fit avec tous les points
1620| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1621| Input:
1622| x = tableau des abscisses
1623| y = tableau des ordonnees
1624| ey = erreurs sur les y
1625| n = nombre de donnees en entree
1626| per_clean = pourcentage des points a tuer pour la seconde passe
1627--
1628*/
1629/*
1630++
1631| Output:
1632| n = nombre de points utilises (point non utilise si ey<=0)
1633| a1 = coefficients de proportionalite
1634| Return:
1635| valeur du xi2 si fit reussi,
1636| -1. si echec fit passe no 1
1637| -2. si echec fit passe no 2
1638| -3. si probleme malloc
1639| -4. si probleme nombre de points a tuer
1640--
1641*/
1642double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
1643{
1644int npt,k,i,nclass;
1645double *clas,aa1,c2,cut;
1646
1647*a1 =0.;
1648
1649/* 1ere passe */
1650npt = *n;
1651c2 = FitProp(x,y,ey,&npt,&aa1);
1652if(c2<0.) {*n = npt; return(-1.);}
1653*a1 = aa1;
1654/* printf("pass 1: %g*x c2=%g/%d\n",*a1,c2,npt); */
1655
1656clas = (double*) malloc( *n * sizeof(double) );
1657if( clas == NULL ) {*n=npt; return(-3.);}
1658
1659/* elimination des mauvais points */
1660nclass = 0;
1661for(i=0;i<*n;i++) {
1662 if(ey[i]<=0.) continue;
1663 c2 = (y[i]-aa1*x[i])/ey[i];
1664 clas[nclass] = c2*c2;
1665 nclass++;
1666}
1667qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1668k = (int) ( (1. - per_clean ) * (double) nclass );
1669if(k<0) k=0;
1670if(k>=nclass) k = nclass-1;
1671cut = clas[k];
1672k = 0;
1673for(i=0;i<*n;i++) {
1674 clas[i] = ey[i];
1675 c2 = (y[i]-aa1*x[i])/ey[i];
1676 c2 *= c2;
1677 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1678}
1679/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1680
1681/* 2sd passe */
1682npt = *n;
1683c2 = FitProp(x,y,clas,&npt,&aa1);
1684if(c2<0.) {*n = npt; free(clas); return(-2.);}
1685*a1 = aa1;
1686*n = npt;
1687/* printf("pass 2: %g*x c2=%g/%d\n",*a1,c2,npt); */
1688
1689free(clas);
1690return(c2);
1691}
1692
1693/*=========================================================================*/
1694/*
1695++
1696double FitLinClean -
1697 (double *x,double *y,double *ey,int *n -
1698 ,double per_clean,double *a0,double *a1)
1699
1700 Fit de y(i) = a0 + a1*x(i) en deux passes:
1701--
1702*/
1703/*
1704++
1705| 1-/ fit avec tous les points
1706| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1707| Input:
1708| x = tableau des abscisses
1709| y = tableau des ordonnees
1710| ey = erreurs sur les y
1711| n = nombre de donnees en entree
1712| per_clean = pourcentage des points a tuer pour la seconde passe
1713| Output:
1714| n = nombre de points utilises (point non utilise si ey<=0)
1715| a0,a1 = coefficients de la droite
1716--
1717*/
1718/*
1719++
1720| Return:
1721| valeur du xi2 si fit reussi,
1722| -1. si echec fit passe no 1
1723| -2. si echec fit passe no 2
1724| -3. si probleme malloc
1725| -4. si probleme nombre de points a tuer
1726--
1727*/
1728double FitLinClean(double *x,double *y,double *ey,int *n
1729 ,double per_clean,double *a0,double *a1)
1730{
1731int npt,k,i,nclass;
1732double *clas,aa0,aa1,c2,cut;
1733
1734*a0 = *a1 =0.;
1735
1736/* 1ere passe */
1737npt = *n;
1738c2 = FitLin(x,y,ey,&npt,&aa0,&aa1);
1739if(c2<0.) {*n = npt; return(-1.);}
1740*a0 = aa0;
1741*a1 = aa1;
1742/* printf("pass 1: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
1743
1744clas = (double*) malloc( *n * sizeof(double) );
1745if( clas == NULL ) {*n=npt; return(-3.);}
1746
1747/* elimination des mauvais points */
1748nclass = 0;
1749for(i=0;i<*n;i++) {
1750 if(ey[i]<=0.) continue;
1751 c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
1752 clas[nclass] = c2*c2;
1753 nclass++;
1754}
1755qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1756k = (int) ( (1. - per_clean ) * (double) nclass );
1757if(k<0) k=0;
1758if(k>=nclass) k = nclass-1;
1759cut = clas[k];
1760k = 0;
1761for(i=0;i<*n;i++) {
1762 clas[i] = ey[i];
1763 c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
1764 c2 *= c2;
1765 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1766}
1767/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1768
1769/* 2sd passe */
1770npt = *n;
1771c2 = FitLin(x,y,clas,&npt,&aa0,&aa1);
1772if(c2<0.) {*n = npt; free(clas); return(-2.);}
1773*a0 = aa0;
1774*a1 = aa1;
1775*n = npt;
1776/* printf("pass 2: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
1777
1778free(clas);
1779return(c2);
1780}
1781
1782/*===================================================================*/
1783/*
1784++
1785double FitParClean -
1786 (double *x,double *y,double *ey,int *n -
1787 ,double per_clean,double *a0,double *a1,double *a2)
1788
1789 Fit de y(i) = a0 + a1*x(i) + a2*x(i)^2 en deux passes:
1790--
1791*/
1792/*
1793++
1794| 1-/ fit avec tous les points
1795| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1796| Input:
1797| x = tableau des abscisses
1798| y = tableau des ordonnees
1799| ey = erreurs sur les y
1800| n = nombre de donnees en entree
1801| per_clean = pourcentage des points a tuer pour la seconde passe
1802| Output:
1803| n = nombre de points utilises (point non utilise si ey<=0)
1804| a0,a1,a2 = coefficients de la parabole
1805| Return:
1806| valeur du xi2 si fit reussi,
1807| -1. si echec fit passe no 1
1808| -2. si echec fit passe no 2
1809| -3. si probleme malloc
1810| -4. si probleme nombre de points a tuer
1811--
1812*/
1813double FitParClean(double *x,double *y,double *ey,int *n
1814 ,double per_clean,double *a0,double *a1,double *a2)
1815{
1816int npt,k,i,nclass;
1817double *clas,aa0,aa1,aa2,c2,cut;
1818
1819*a0 = *a1 = *a2 =0.;
1820
1821/* 1ere passe */
1822npt = *n;
1823c2 = FitPar(x,y,ey,&npt,&aa0,&aa1,&aa2);
1824if(c2<0.) {*n = npt; return(-1.);}
1825*a0 = aa0;
1826*a1 = aa1;
1827*a2 = aa2;
1828/* printf("pass 1: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
1829
1830clas = (double*) malloc( *n * sizeof(double) );
1831if( clas == NULL ) {*n=npt; return(-3.);}
1832
1833/* elimination des mauvais points */
1834nclass = 0;
1835for(i=0;i<*n;i++) {
1836 if(ey[i]<=0.) continue;
1837 c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
1838 clas[nclass] = c2*c2;
1839 nclass++;
1840}
1841qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1842k = (int) ( (1. - per_clean ) * (double) nclass );
1843if(k<0) k=0;
1844if(k>=nclass) k = nclass-1;
1845cut = clas[k];
1846k = 0;
1847for(i=0;i<*n;i++) {
1848 clas[i] = ey[i];
1849 c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
1850 c2 *= c2;
1851 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1852}
1853/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1854
1855/* 2sd passe */
1856npt = *n;
1857c2 = FitPar(x,y,clas,&npt,&aa0,&aa1,&aa2);
1858if(c2<0.) {*n = npt; free(clas); return(-2.);}
1859*a0 = aa0;
1860*a1 = aa1;
1861*a2 = aa2;
1862*n = npt;
1863/* printf("pass 2: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
1864
1865free(clas);
1866return(c2);
1867}
1868
1869/*===========================================================*/
1870/*
1871++
1872float interpole(float m,int n,float *t1,float *t2)
1873 Interpolation lineaire y=f(x):
1874--
1875*/
1876/*
1877++
1878| t1[n] = tableau des x
1879| t2[n] = tableau des y
1880| m = valeur ou on interpole
1881| RETURN: f(m)
1882--
1883*/
1884float interpole(float m,int n,float *t1,float *t2)
1885{
1886int i,n1;
1887float r;
1888
1889if ( n == 1 ) return ( t2[0] );
1890
1891n1=n-1;
1892if ( m < t1[0] ) m=t1[0];
1893if ( m > t1[n1] ) m=t1[n1];
1894
1895for(i=0;i<n;i++) if ( m <= t1[i] ) break;
1896i = (i==0) ? 1 : i;
1897i = (i==n) ? n1 : i;
1898
1899r = t2[i-1] + (t2[i]-t2[i-1]) / (t1[i]-t1[i-1]) * (m-t1[i-1]);
1900
1901/*
1902printf("interpole: i=%3d m=%g t1=%g %g t2=%g %g r=%g\n"
1903 ,i,m,t1[i-1],t1[i],t2[i-1],t2[i],r);
1904for(i=0;i<n;i++) printf(" (%g,%g)",t1[i],t2[i]); printf("\n");
1905*/
1906
1907return(r);
1908}
1909
1910/*=========================================================*/
1911/* Christophe 10/11/93 La Silla */
1912/*
1913++
1914int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
1915 Fonction de calcul de la moyenne tronquee et du sigma d'un tableau
1916--
1917*/
1918/*
1919++
1920| Methode: 1-/ moyenne-sigma, 2-/ moyenne tronquee et sigma,
1921| ENTREE:
1922| mag: magnitude
1923| err: erreur sur la magnitude
1924| ndata: nombre de donnees
1925| nsigma: nombre de sigma dans lequel on calcule le maximum
1926| si <=0, une seule passe pour la moyenne
1927| SORTIE:
1928| ndata: nombre de data utilises pour calculer mean et sigma
1929| mean: moyenne des donnees
1930| sigma: sigma des donnees
1931| MeanSig: 0 si calcul ok, <0 sinon
1932--
1933*/
1934int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
1935{
1936int_4 deb=DEB_MeanSig;
1937int_4 pass,passmx,i,n=0;
1938double m,s2,v,scut;
1939
1940*mean = *sigma = 0.;
1941passmx = ( nsigma <= 0. ) ? 1 : 2 ;
1942for (pass=1;pass<=passmx;pass++) {
1943 m = s2 = 0.;
1944 n=0;
1945 scut = GRAND;
1946 if( pass == 2 ) scut=nsigma* *sigma;
1947 for (i=0;i<*ndata;i++) {
1948 v = *(mag+i);
1949 if( *(err+i) > 0. && fabs(v-*mean) < scut ) {
1950 n++;
1951 m += v;
1952 s2 += v * v;
1953 } }
1954 if ( n >= 2 ) {
1955 *mean = m / n;
1956 *sigma = sqrt( s2 / n - m/n * m/n );
1957 } else {
1958 *mean = *sigma = 0.;
1959 *ndata=n;
1960 return(-1);
1961 }
1962 if ( deb>0 ) printf("MeanSig: pass=%d mean=%f sigma=%f n=%d\n"
1963 ,pass,*mean,*sigma,n);
1964}
1965*ndata=n;
1966return(0);
1967}
1968
1969/*=========================================================================*/
1970/*
1971++
1972int Most_Probable -
1973 ( float *val, int nval, float binin, int nmoy -
1974 , float low, float high, float *most, int deb)
1975
1976 Pour calculer la valeur la plus probable par maximum d'histogramme.
1977--
1978*/
1979/*
1980++
1981| INPUT:
1982| - val= pointeur sur un tableau de valeurs (float).
1983| - nval= nombre de valeurs a traiter.
1984| - binin= taille du bin.
1985| - nmoy= la valeur retournee est la moyenne de +/- nmoy bins
1986| autour du max de l'histo.
1987| - low, high= les valeurs permises mini et maxi des valeurs
1988| (si low>high calcul automatique).
1989| - deb= niveau de debug.
1990| OUTPUT:
1991| - most = valeur la plus probable.
1992| RETURN CODE:
1993| -1 : nval <=0
1994| -2 : bin <=0
1995| -3 : low>=high apres cadrage automatique
1996| -4 : nombre de valeurs remplies nul au niveau de la 1ere passe
1997| -51 : pas trouve de maximum 1ere passe
1998| -52 : pas trouve de maximum 2sd passe
1999--
2000*/
2001int Most_Probable( float *val, int nval, float binin, int nmoy
2002 , float low, float high, float *most, int deb)
2003{
2004int histo[503],i,nbin,n,ib,ibmax,vmax,pass;
2005float bin,xmax=0.;
2006double moy,sum;
2007
2008if(deb>1) printf("Most_Probable: nval=%d binin=%f nmoy=%d low,high=%f %f\n"
2009 ,nval,binin,nmoy,low,high);
2010if (nval<=0) return(-1);
2011if (binin<=0.) return(-2);
2012nmoy = (nmoy<0) ? 0 : nmoy;
2013if(low>= high) {
2014 low = GRAND;
2015 high = -low;
2016 for(i=0;i<nval;i++) {if(val[i]>high) high=val[i]; if(val[i]<low) low=val[i];}
2017}
2018if(deb>1) printf("nmoy=%d low,high=%f %f\n",nmoy,low,high);
2019if(low>= high) return(-3);
2020
2021/* premiere passe "nbin" bins entre low et high, nbin=min(high-low)/bin+1,501) */
2022/* seconde passe "nbin" autour du maxi 1ere passe, nbin=min(high-low)/bin,501) */
2023
2024for ( pass=1;pass<=2;pass++) {
2025
2026 bin=binin;
2027 nbin = (int) ( (high-low)/bin ) + 1;
2028 if(nbin>501) {
2029 nbin = 501;
2030 if(pass!=1){
2031 low = xmax - 250*binin - binin/2.;
2032 high = xmax + 250*binin + binin/2.;
2033 } }
2034 /* re-scaling du bin pour etre sur */
2035 bin=(high-low)/nbin;
2036 if(deb>1) printf("pass=%2d low,high=%f %f bin=%f nbin=%d\n"
2037 ,pass,low,high,bin,nbin);
2038 for(i=0;i<nbin;i++) histo[i]=0;
2039 n=0;
2040 for(i=0;i<nval;i++) {
2041 if( val[i]>=high || val[i]<low ) continue;
2042 ib = (int) ((val[i]-low)/bin);
2043 if( ib<0 && ib >= nbin ) continue;
2044 histo[ib]++;
2045 n++;
2046 }
2047 if(n<=0) return (-4);
2048 vmax = -1; ibmax= -1;
2049 if(n<=0) return (-4);
2050 for(i=0;i<nbin;i++) {
2051 if(histo[i]<vmax) continue;
2052 vmax = histo[i];
2053 ibmax = i;
2054 }
2055 if(ibmax<0) return (-50-pass);
2056 xmax = low + ibmax*bin + bin/2.;
2057 if(deb>1) printf("bin du maximum %5d (%d) abscisse=%f\n",ibmax,vmax,xmax);
2058 if(deb>3) {
2059 printf("histogramme:\n");
2060 for (i= ibmax-25;i<=ibmax+25;i++) {
2061 if (i<0) continue;
2062 if (i>=nbin) break;
2063 printf(" %5d",histo[i]);
2064 if(i%10==9) printf("\n");
2065 }
2066 printf("\n");
2067 }
2068}
2069
2070sum = moy =0.; n=0;
2071for (i= -nmoy;i<=nmoy;i++) {
2072 if (ibmax-i>=0 && ibmax+i<nbin) {
2073 moy += ( xmax + i * bin ) * histo[ibmax+i];
2074 sum += (double) histo[ibmax+i];
2075 n++;
2076} }
2077
2078*most = moy / sum;
2079if(deb>0) printf("Most_probable: most=%f (avec %d points)\n",*most,n);
2080
2081return(0);
2082
2083}
2084
2085/*============================================================*/
2086/* Christophe 27/01/95 */
2087/*
2088++
2089float Ajust_GaFn
2090| (int Ns,float *fcfr
2091| ,float *haut,float *ehaut,float *mean,float *emean
2092| ,float *sigma,float *esigma,float *fond,float *efond
2093| ,int fixfond,int NBIN_RESOL
2094| ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
2095
2096 Fonction de fit gaussienne + fond (1D) du tableau fcfr
2097 avec reglage des parametres d'entree.
2098--
2099*/
2100/*
2101++
2102| ATTENTION: le tableau fcfr est modifie !!!
2103| ---------
2104| ENTREES:
2105| Ns = nombre d'entrees dans fcfr
2106| fcfr = tableau des valeurs a fitter
2107| fond = valeur a donner au fond si fixfond = 1
2108| fixfond = 1 fond fixe dans le fit a la valeur fond
2109| = 2 fond fixe dans le fit a une valeur
2110| calculee automatiquement sur
2111| les bords de l'histogramme
2112| > 2 fond fixe a zero (<=> 1 + fond=0)
2113| <= 0 fond libre dans le fit
2114| NBIN_RESOL = nombre maxi de bins pour l'histo de fit
2115| de la resolution
2116| perc_net = pourcentage de donnees a nettoyer pour
2117| calculer mean,sigma de la 1ere passe
2118| frac_sgb = le bin de fit sera sigma*fracsgb
2119| ou sigma est calcule en premiere passe
2120| dyn_sgb = limites de l'histo de fit
2121| xmin=mean-dyn_sgb*sigma , xmax=mean+dyn_sgb*sigma
2122| deb = niveau de debug
2123--
2124*/
2125/*
2126++
2127| SORTIES:
2128| haut = valeur de la hauteur
2129| ehaut = erreur sur la valeur de la hauteur
2130| mean = valeur moyenne du decalage
2131| emean = erreur sur la valeur moyenne du decalage
2132| sigma = valeur de la resolution
2133| esigma = erreur sur la valeur de la resolution
2134| fond = valeur du fond
2135| efond = erreur sur la valeur du fond
2136| return code = chi2 du fit (<0 si Pb)
2137--
2138*/
2139float Ajust_GaFn(int Ns,float *fcfr
2140 ,float *haut,float *ehaut,float *mean,float *emean
2141 ,float *sigma,float *esigma,float *fond,float *efond
2142 ,int fixfond,int NBIN_RESOL
2143 ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
2144{
2145int_4 i,j,i1,i2,nbin,ibin,entries;
2146float c2,xmin,xmax,binw,ymax;
2147float *y,*ey,*x;
2148double m,s;
2149FLOATDOUBLE X,Y,EY;
2150double (*Fun) (double ,double *,double *);
2151int_4 npar,n;
2152double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
2153
2154fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
2155perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
2156NBIN_RESOL = ( NBIN_RESOL <= 0 ) ? 50 : NBIN_RESOL;
2157frac_sgb = ( frac_sgb <= 0. ) ? 0.5 : frac_sgb;
2158dyn_sgb = ( dyn_sgb <= 0. ) ? 5.0 : dyn_sgb;
2159x = y = ey = NULL;
2160x = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2161y = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2162ey = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2163if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
2164
2165if(deb>0) printf("Ajust_GaFn[%d] perc_net=%f nbin=%d frac_sgb=%f dyn_sgb=%f\n"
2166 ,Ns,perc_net,NBIN_RESOL,frac_sgb,dyn_sgb);
2167
2168/* on vire perc_net % des points a gauche et a droite de la distribution */
2169qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2170i = perc_net * Ns;
2171if(perc_net>0. && i==0) i=1;
2172i1 = i; i2 = Ns-1-i;
2173if(deb>1) {
2174 printf(" df/f=");
2175 for(j=0;j<10;j++) printf("%8.2f ",fcfr[j]);
2176 printf("\n");
2177 printf("selection de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
2178}
2179if(i2<=i1) { c2= -101.; goto END;}
2180
2181/* calcul mean et sigma 1ere passe */
2182m = s = 0.; j = 0;
2183for(i=i1;i<=i2;i++) {m += fcfr[i]; s += fcfr[i]*fcfr[i]; j++;}
2184m /= j;
2185s = sqrt(s/j - m*m);
2186*mean = m; *sigma = s;
2187if(deb>1) printf("premiere passe: mean=%f sigma=%f\n",*mean,*sigma);
2188
2189/* remplissage histo a +/- dyn_sgb * sigma */
2190xmin = *mean - dyn_sgb* *sigma;
2191xmax = *mean + dyn_sgb* *sigma;
2192if(xmin>=xmax) {c2 = -102.; goto END;}
2193binw = *sigma * frac_sgb;
2194nbin = (xmax-xmin)/binw;
2195if(nbin<6) nbin=6; if(nbin>NBIN_RESOL) nbin=NBIN_RESOL;
2196binw = (xmax-xmin)/nbin;
2197for(i=0;i<nbin;i++)
2198 {x[i] = xmin + ((float) i + 0.5)*binw; y[i] = 0.;}
2199if(deb>1) {
2200 printf("histo[%d] lim=[%f,%f] bw=%f x=\n"
2201 ,nbin,xmin,xmax,binw);
2202 for(j=0;j<nbin;j++)
2203 {printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
2204 if(j%10!=0) printf("\n");
2205}
2206entries = 0;
2207for(i=0;i<Ns;i++) { ibin = (fcfr[i]-xmin)/binw;
2208 if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;} }
2209ymax = 0.;
2210for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
2211 if(y[i]>ymax) ymax=y[i];}
2212if(deb>1) {
2213 printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
2214 for(j=0;j<nbin;j++)
2215 {printf("%8.0f ",y[j]); if(j%10==9) printf("\n");}
2216 if(j%10!=0) printf("\n");
2217 if(deb>2) {
2218 printf("histo ey=\n");
2219 for(j=0;j<nbin;j++)
2220 {printf("%8.0f ",ey[j]); if(j%10==9) printf("\n");}
2221 if(j%10!=0) printf("\n"); }
2222}
2223if(ymax<2.) {c2 = -103.; goto END;}
2224
2225if(fixfond!=1) {
2226 *fond = (y[0]+y[1]+y[nbin-1]+y[nbin-2])/4.;
2227 if(fixfond>2) *fond = 0.;
2228}
2229*haut = ymax - *fond;
2230
2231/* fit gaussienne + fond constant */
2232Fun = Gauss1DPolF ; Set_FitFunDPol(0);
2233X.fx = x;
2234Y.fx = y;
2235EY.fx = ey;
2236par[0] = *haut;
2237par[1] = *mean;
2238par[2] = *sigma;
2239par[3] = *fond;
2240stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
2241stepar[2] = par[2]/10.; stepar[3] = 0.5;
2242if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
2243for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
2244minpar[2] = 0.00001; maxpar[2] = 9999.;
2245npar = 4;
2246stochi2 = 0.0001;
2247n = nbin;
2248j = (deb>2)? 1:0;
2249c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
2250 ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
2251
2252END:
2253
2254if( c2 > 0. ) {
2255 *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3];
2256 *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
2257} else {
2258 *ehaut = *emean = *esigma = *efond = 0.;
2259}
2260if(x !=NULL) free(x);
2261if(y !=NULL) free(y);
2262if(ey!=NULL) free(ey);
2263
2264return(c2);
2265}
2266
2267/*==========================================================*/
2268/* Christophe 27/03/95 */
2269/*
2270++
2271float HFit_GaFn -
2272 (int Ns,float *fcfr -
2273 ,float *haut,float *ehaut,float *mean,float *emean -
2274 ,float *sigma,float *esigma,float *fond,float *efond -
2275 ,int fixfond,int nbin,float xmin,float xmax,int deb)
2276
2277 Fonction de fit gaussienne + fond (1D) du tableau fcfr
2278 dans un histo de "nbin" bins de "xmin a xmax"
2279--
2280*/
2281/*
2282++
2283| ENTREES:
2284| Ns = nombre d'entrees dans fcfr
2285| fcfr = tableau des valeurs a fitter
2286| mean = valeur de depart pour la moyenne
2287| sigma = valeur de depart pour le sigma
2288| fond = valeur de depart pour le fond
2289| fixfond > 0 fond fixe dans le fit a la valeur fond
2290| <= 0 fond libre dans le fit
2291| nbin = nombre de bins pour l'histo de fit
2292| xmin = valeur inferieure de l'histo
2293| xmax = valeur superieure de l'histo
2294| deb = niveau de debug
2295--
2296*/
2297/*
2298++
2299| SORTIES:
2300| haut = valeur de la hauteur
2301| ehaut = erreur sur la valeur de la hauteur
2302| mean = valeur moyenne du decalage
2303| emean = erreur sur la valeur moyenne du decalage
2304| sigma = valeur de la resolution
2305| esigma = erreur sur la valeur de la resolution
2306| fond = valeur du fond
2307| efond = erreur sur la valeur du fond
2308| return code = chi2 du fit (<0 si Pb)
2309--
2310*/
2311float HFit_GaFn(int Ns,float *fcfr
2312 ,float *haut,float *ehaut,float *mean,float *emean
2313 ,float *sigma,float *esigma,float *fond,float *efond
2314 ,int fixfond,int nbin,float xmin,float xmax,int deb)
2315{
2316int_4 i,j,ibin,entries;
2317float c2,binw,ymax;
2318float *y,*ey,*x;
2319FLOATDOUBLE X,Y,EY;
2320double (*Fun) (double ,double *,double *);
2321int_4 npar,n;
2322double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
2323
2324if(xmax<=xmin) return(-102);
2325fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
2326nbin = ( nbin <= 0 ) ? 50 : nbin;
2327x = y = ey = NULL;
2328x = (float *) calloc(nbin+2,sizeof(float));
2329y = (float *) calloc(nbin+2,sizeof(float));
2330ey = (float *) calloc(nbin+2,sizeof(float));
2331if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
2332
2333if(deb>0) printf("HFit_GaFn[%d pts] nbin=%d de %g a %g\n"
2334 ,Ns,nbin,xmin,xmax);
2335
2336/* remplissage histo */
2337binw = (xmax-xmin)/nbin;
2338for(i=0;i<nbin;i++) {x[i]=xmin+((float) i +0.5)*binw; y[i]=0.;}
2339if(deb>1) {
2340 printf("histo[%d] lim=[%f,%f] bw=%f x=\n",nbin,xmin,xmax,binw);
2341 for(j=0;j<nbin;j++){printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
2342 if(j%10!=0) printf("\n");
2343}
2344entries = 0;
2345for(i=0;i<Ns;i++) {
2346 ibin = (fcfr[i]-xmin)/binw;
2347 if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;}
2348}
2349
2350ymax = 0.;
2351for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
2352 if(y[i]>ymax) ymax=y[i];}
2353if(deb>1) {
2354 printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
2355 for(j=0;j<nbin;j++){printf("%8.0f ",y[j]); if(j%10==9)printf("\n");}
2356 if(j%10!=0) printf("\n");
2357 if(deb>2) {
2358 printf("histo ey=\n");
2359 for(j=0;j<nbin;j++){printf("%8.0f ",ey[j]); if(j%10==9)printf("\n");}
2360 if(j%10!=0) printf("\n");
2361} }
2362if(ymax<2.) {c2 = -103.; goto END;}
2363
2364*haut = ymax - *fond;
2365
2366/* fit gaussienne + fond constant */
2367Fun = Gauss1DPolF ; Set_FitFunDPol(0);
2368X.fx = x;
2369Y.fx = y;
2370EY.fx = ey;
2371par[0] = *haut;
2372par[1] = *mean;
2373par[2] = *sigma;
2374par[3] = *fond;
2375stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
2376stepar[2] = par[2]/10.; stepar[3] = 0.5;
2377if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
2378for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
2379minpar[2] = 0.00001; maxpar[2] = 9999.;
2380npar = 4;
2381stochi2 = 0.0001;
2382n = nbin;
2383j = (deb>2)? 1:0;
2384c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
2385 ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
2386
2387END:
2388
2389if( c2 > 0. ) {
2390 *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3];
2391 *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
2392} else {
2393 *ehaut = *emean = *esigma = *efond = 0.;
2394}
2395if(x !=NULL) free(x);
2396if(y !=NULL) free(y);
2397if(ey!=NULL) free(ey);
2398
2399return(c2);
2400}
2401
2402/*==============================================================*/
2403/* Christophe 15/02/95 */
2404/*
2405++
2406int Ajust_MnSg -
2407 (int Ns,float *fcfr -
2408 ,float *mean,float *emean,float *sigma,float *esigma -
2409 ,float perc_net,float n_sigma,int deb)
2410
2411 Calcul mean sigma tronques du tableau fcfr.
2412--
2413*/
2414/*
2415++
2416| ATTENTION: le tableau fcfr est modifie
2417| ---------
2418| Methode:
2419| 1- calcul de la moyenne Mcent en enlevant perc_net% des pts
2420| les + faibles et perc_net% des pts les + forts
2421| 2- calcul de la valeur cutup correspondant a 2*perc_net%
2422| des pts les + hauts en valeur absolue (fcfr-Mcent)
2423| 3- calcul moyenne et sigma en enlevant les points ayant
2424| abs(fcfr-Mcent) > cutup (1ere passe)
2425| 4- calcul moyenne et sigma en enlevant les points ayant
2426| abs(fcfr-Mcent) > cutup et
2427| abs(fcfr-M(1ere passe)) > n_sigma*sigma(1ere passe)
2428--
2429*/
2430/*
2431++
2432| ENTREES:
2433| Ns = nombre d'entrees dans fcfr
2434| fcfr = tableau des valeurs a fitter
2435| perc_net = pourcentage de donnees a nettoyer pour
2436| calculer mean,sigma
2437| n_sigma = nombre de sigma en passe 2 pour
2438| calculer mean,sigma
2439| deb = niveau de debug
2440| SORTIES:
2441| mean = valeur moyenne du decalage
2442| emean = erreur sur la valeur moyenne du decalage
2443| sigma = valeur de la resolution
2444| esigma = erreur sur la valeur de la resolution
2445| return code = nombre de points utilises (<0 si Pb)
2446--
2447*/
2448int Ajust_MnSg(int Ns,float *fcfr
2449 ,float *mean,float *emean,float *sigma,float *esigma
2450 ,float perc_net,float n_sigma,int deb)
2451{
2452int i,i1,i2,n,nvire,pass;
2453double m,s,mcent,cutup,cuts;
2454float *dum;
2455
2456/* set up des valeurs par defaut */
2457perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
2458n_sigma = ( n_sigma <= 0. ) ? 3.0 : n_sigma;
2459nvire = perc_net * Ns;
2460if(perc_net>0. && nvire==0) nvire=1;
2461*emean = *esigma = -1.;
2462if(deb>0) printf("Ajust_MnSg[%d] perc_net=%f (vire=%d) n_sigma=%f\n"
2463 ,Ns,perc_net,nvire,n_sigma);
2464
2465/* on ordonne par ordre croissant de fcfr */
2466qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2467i1 = nvire; i2 = Ns-1-nvire;
2468if(deb>1) printf(" select de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
2469if(i2<=i1) return(-101);
2470
2471/* on vire perc_net % des points a gauche et a droite de la distribution */
2472mcent = 0.; n = 0;
2473for(i=i1;i<=i2;i++) {mcent += fcfr[i]; n++;}
2474if(n<1) return(-102);
2475mcent /= (double) n;
2476if(deb>1) printf(" mean cent=%f sur %d points\n",mcent,n);
2477
2478/* allocate space and fill absolute value */
2479if( (dum = (float *) calloc(Ns,sizeof(float))) == NULL ) return(-103);
2480for(i=0;i<Ns;i++) dum[i] = fabs( mcent - fcfr[i] );
2481
2482/* on ordonne par ordre croissant de abs(fcfr-mcent) */
2483qsort(dum,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2484i = Ns-1-2*nvire;
2485if(i<0) {n= -104; goto END_Ajust_MnSg;}
2486
2487/* on vire 2.*perc_net % des points les + hauts de la distribution */
2488cutup = dum[i];
2489if(deb>1) printf(" cutup=%f sur %d points\n",cutup,i);
2490
2491/* calcul mean et sigma en 2 passes avec coupure n_sigma*sigma(1ere passe)*/
2492cuts = GRAND2;
2493for(pass=1;pass<=2;pass++) {
2494 m = s = 0.; n = 0;
2495 for(i=0;i<Ns;i++) {
2496 if( fabs(mcent-fcfr[i]) > cutup ) continue;
2497 if( fabs((double) (*mean-fcfr[i])) > cuts ) continue;
2498 m += fcfr[i];
2499 s += fcfr[i]*fcfr[i];
2500 n++;
2501 }
2502 if(n<=2) {n= -105; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
2503 m /= n;
2504 s = s/n - m*m;
2505 if(s<=0.) {n= -106; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
2506 s = sqrt(s);
2507 *mean = m;
2508 *sigma = s;
2509 cuts = n_sigma * s;
2510 if(deb>1)
2511 printf(" pass=%d mean=%g sigma=%g (%d pts) cuts=%f\n"
2512 ,pass,*mean,*sigma,n,cuts);
2513}
2514
2515*emean = s/sqrt((double) n);
2516*esigma = s/sqrt(2. * (double) n);
2517if(deb>0) printf("mean=%g (+/-%g) sigma=%g (+/-%g) sur %d pts\n"
2518 ,*mean,*emean,*sigma,*esigma,n);
2519
2520END_Ajust_MnSg:
2521if( dum != NULL ) free(dum);
2522return(n);
2523}
2524
2525/*=================================================================*/
2526/* Nathalie 16/02/95 */
2527/*
2528++
2529float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
2530 Cette fonction calcule l'integrale 3D: f(x,y,z)dx.dy.dz
2531 L'integrale est calculee en incrementant des couronnes cubiques
2532 centrees sur le point de coordonnees (0,0,0)
2533--
2534*/
2535/*
2536++
2537| ENTREES:
2538| fonction = f(x,y,z)
2539| step = pas de l'integration
2540| precision = coupure en dV(couronne i)/Vtot(couronnes 0 a i)
2541| SORTIES:
2542| return: l'integrale
2543| REMARQUES:
2544| la fonction f(x,y,z) doit decroitre tres vite en r**2
2545--
2546*/
2547float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
2548{
2549
2550 float f;
2551 double vol,volprec;
2552 int ecart,i,j,k,l;
2553 int encore,deb=0;
2554
2555 vol = volprec = 0.;
2556
2557 /* contribution du cube central */
2558 for(l=0;l<nd3d;l++) {
2559 f = fonction(dx3d[l]*step,dy3d[l]*step,dz3d[l]*step);
2560 vol += f*w3d[l];
2561 }
2562 ecart = 1;
2563
2564 /* increment en couronnes cubiques de 2*ecart+1 de cote */
2565 do {
2566 volprec = vol;
2567 for (i= -ecart;i<=ecart;i++) for(l=0;l<nd3d;l++) {
2568 for(j= -ecart;j<=ecart;j++) {
2569 f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,(-ecart+dz3d[l])*step);
2570 vol += f*w3d[l];
2571 f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,( ecart+dz3d[l])*step);
2572 vol += f*w3d[l];
2573 }
2574
2575 for(k= -ecart+1;k<=ecart-1;k++) {
2576 f=fonction((i+dx3d[l])*step,(-ecart+dy3d[l])*step,(k+dz3d[l])*step);
2577 vol += f*w3d[l];
2578 f=fonction((i+dx3d[l])*step,( ecart+dy3d[l])*step,(k+dz3d[l])*step);
2579 vol += f*w3d[l];
2580 }
2581 }
2582 for (j= -ecart+1;j<=ecart-1;j++) for(k= -ecart+1;k<=ecart-1;k++)
2583 for(l=0;l<nd3d;l++) {
2584 f=fonction((-ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
2585 vol += f*w3d[l];
2586 f=fonction(( ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
2587 vol += f*w3d[l];
2588 }
2589
2590 ecart = ecart + 1;
2591 encore = ((fabs((vol-volprec)/vol) > precision) || (ecart <= 2) );
2592 if(deb>1) printf("ec=%d v=%g deltav/v=%g\n"
2593 ,ecart-1,vol*step*step*step,((vol-volprec)/vol));
2594 } while(encore);
2595
2596 vol *= step * step* step;
2597 if(deb>0) printf("\nVol = %g\n",vol);
2598 return(vol);
2599}
2600
2601
2602/*=================================================================*/
2603/* cmv 6/11/97 */
2604/*
2605++
2606int IntFaisDr -
2607 (int n,float *cs,float *sn,float *p,float *x0,float *y0 -
2608 ,int npass,float perclean,int lp)
2609
2610 Pour calculer le point d'intersection moyen
2611 d'un faisceau de droites.
2612--
2613*/
2614/*
2615++
2616| L'equation des droites est sous la forme:
2617| cos(alpha)*x + sin(alpha)*y = p
2618| [cos(alpha),sin(alpha)] coordonnees du vecteur unitaire joignant
2619| l'origine au point de moindre approche de la droite a l'origine.
2620| p est la distance de la droite a l'origine.
2621--
2622*/
2623/*
2624++
2625| -- Input:
2626| n : nombre de droites
2627| cs : tableau des coefficients cos(alpha)
2628| sn : tableau des coefficients sin(alpha)
2629| p : tableau des coefficients p
2630| npass : nombre de passes de nettoyage
2631| perclean : pourcentage d'etoiles a tuer
2632| d'une passe a la suivante
2633| ex: perclean=0.2, si il y a 200 etoiles dans une passe
2634| la passe suivante en utilisera 160 et la suivante 128.
2635| lp : niveau d'impression
2636--
2637*/
2638/*
2639++
2640| -- Output:
2641| x0 : valeur de l'abscisse du point d'intersection moyen trouve
2642| y0 : ordonnee
2643| -- Return:
2644| nombre de droites utilisees pour le calcul de x0,y0
2645--
2646*/
2647int IntFaisDr(int n,float *cs,float *sn,float *p,float *x0,float *y0
2648 ,int npass,float perclean,int lp)
2649{
2650int i,j,ns, nsuse=-9, ipass;
2651double sumC2,sumS2,sumCS,sumCP,sumSP,den;
2652float *d2=NULL, d2cut=-1.;
2653unsigned short *good=NULL;
2654
2655*x0 = *y0 = 0.;
2656if(n<=1) return(-1);
2657if(lp<0) lp=0;\
2658if(npass<=0) npass=1;
2659if(perclean<=0.) { perclean=0.; npass=1;}
2660if(lp)
2661 printf("IntFaisDr avec %d points en %d passes avec nettoyage de %g%%\n"
2662 ,n,npass,perclean*100);
2663
2664d2 = (float *) malloc(n * sizeof(float));
2665if(d2==NULL) {
2666 if(lp)
2667 printf("allocation de %d float impossible\n",n);
2668 return(-2);
2669}
2670good = (unsigned short *) malloc(n * sizeof(unsigned short));
2671if(good==NULL) {
2672 if(lp)
2673 printf("allocation de %d unsigned short impossible\n",n);
2674 free(d2);
2675 return(-3);
2676}
2677for(i=0;i<n;i++) good[i]=1;
2678
2679for(ipass=1;ipass<=npass;ipass++) {
2680
2681 /* Calcul du point d'intersection pour la passe ipass */
2682 sumC2=sumS2=sumCS=sumCP=sumSP=0.;
2683 ns=0;
2684 for(i=0;i<n;i++) {
2685 if( !good[i] ) continue;
2686 sumC2 += cs[i]*cs[i];
2687 sumS2 += sn[i]*sn[i];
2688 sumCS += cs[i]*sn[i];
2689 sumCP += cs[i]*p[i];
2690 sumSP += sn[i]*p[i];
2691 ns++;
2692 }
2693 den = sumCS*sumCS - sumC2*sumS2;
2694 if(den==0.) {
2695 if(lp)
2696 printf("denominateur nul pass=%d, sumCS=%g sumC2=%g sumS2=%g pour %d dr\n"
2697 ,ipass,sumCS,sumC2,sumS2,ns);
2698 free(d2); free(good);
2699 return(-100-ipass);
2700 }
2701 if(ns<2) {
2702 if(lp) printf("Pas ou plus assez de droites %d\n",ns);
2703 return(nsuse);
2704 }
2705 *x0 = (sumSP*sumCS - sumCP*sumS2)/den;
2706 *y0 = (sumCP*sumCS - sumSP*sumC2)/den;
2707 nsuse = ns;
2708 if(lp) printf("Pass=%d, %d dr x0=%g y0=%g\n",ipass,nsuse,*x0,*y0);
2709 if(ipass==npass) break;
2710
2711 /* Calcul de la coupure en distance**2 pour la passe suivante */
2712 ns = 0;
2713 for(i=0;i<n;i++) {
2714 if( !good[i] ) continue;
2715 d2[ns] = (*x0*cs[i] * *y0*sn[i]-p[i]);
2716 d2[ns] *= d2[ns];
2717 ns++;
2718 }
2719 qsort(d2,(size_t) ns,sizeof(float),qSort_Float);
2720 j = (int) (ns-ns*perclean); if(j<0) j=0; if(j>=ns) j=ns-1;
2721 d2cut = d2[j];
2722 ns=0;
2723 for(i=0;i<n;i++) {
2724 if( !good[i] ) continue;
2725 den = (*x0*cs[i] * *y0*sn[i]-p[i]);
2726 den *= den;
2727 if( den>d2cut ) good[i]=0; else ns++;
2728 }
2729 if(lp>1)
2730 printf(" next pass: i=%d cut=%g -> restera %d dr\n",j,d2cut,ns);
2731}
2732
2733free(d2); free(good);
2734return(nsuse);
2735}
2736
2737/*=========================================== cmv 22/11/04 ===*/
2738/*
2739++
2740double log_factoriel(unsigned int n)
2741
2742 Compute the neperian log of n!
2743--
2744*/
2745double log_factoriel(unsigned int n)
2746{
2747 unsigned int i;
2748 double sum=0.;
2749 if(n<2) return sum;
2750 for(i=n;i>1;i--) sum += log((double)i);
2751 return sum;
2752}
2753
2754/*
2755++
2756double log_stirling(unsigned int n)
2757
2758 Compute the neperian log of the Stirling approx of n!
2759--
2760*/
2761double log_stirling(unsigned int n)
2762/*
2763Approx: n! ~ sqrt(2Pi n) n^n exp(-n) = sqrt(2Pi) n^(n+1/2) exp(-n)
2764 log(n!) ~ (n+1/2) log(n) -n + 1/2 log(2Pi)
2765(ordre 0: log(n!) ~ n (log(n)-1)
2766*/
2767{
2768 if(n<1) return 0.;
2769 return (n+0.5)*log(n) - n + Hln2pi;
2770}
2771
2772/*
2773++
2774double log_gosper(unsigned int n);
2775
2776 Compute the neperian log of the Gosper approx of n!
2777--
2778*/
2779double log_gosper(unsigned int n)
2780/*
2781Approx: n! ~ sqrt( (2n+1/3) Pi ) n^n exp(-n)
2782 log(n!) ~ 1/2 log( (2n+1/3) Pi ) + n log(n) -n
2783*/
2784{
2785 if(n<1) return 0.;
2786 return 0.5*log((2.*n+1./3.)*M_PI) + n*log(n) -n;
2787}
2788
2789/*
2790++
2791double give_log_factoriel(unsigned int n);
2792
2793 Compute the neperian log of the approx of n!
2794--
2795*/
2796static short give_log_factoriel_OK = 0;
2797#define give_log_factoriel_LIM 21
2798static double give_log_factoriel_TAB[give_log_factoriel_LIM];
2799double give_log_factoriel(unsigned int n)
2800{
2801 int i;
2802 if(give_log_factoriel_OK==0) {
2803 give_log_factoriel_OK=1;
2804 for(i=0;i<give_log_factoriel_LIM;i++)
2805 give_log_factoriel_TAB[i]=log_factoriel(i);
2806 }
2807
2808 if(n<give_log_factoriel_LIM) return give_log_factoriel_TAB[n];
2809 return log_gosper(n);
2810}
2811#undef give_log_factoriel_LIM
Note: See TracBrowser for help on using the repository browser.