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

Last change on this file since 3669 was 3514, checked in by cmv, 17 years ago

3.14159 _> M_PI + commentaires dans nbgauleg cmv 08/08/2008

File size: 75.9 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 dimensionnes a n.
1124| - l'integration est exacte sur l'intervalle [x1,x2]
1125| si f(x) est un polynome de degre inferieur ou egal a 2*n-1
1126| - Voir la fonction Integ_Fun pour un calcul d'ordre 8
1127--
1128*/
1129void nbgauleg(double x1,double x2,double *x,double *w,int n)
1130{
1131 int m,j,i;
1132 double z1,z,xm,xl,pp,p3,p2,p1; // Need high precision
1133
1134 m=(n+1)/2;
1135 xm=0.5*(x2+x1); // The root are symetric in the intervalle
1136 xl=0.5*(x2-x1); // we just need to find half of them
1137 for (i=1;i<=m;i++) { // Loop over the desired root
1138 z=cos(M_PI*(i-0.25)/(n+0.5)); // Starting with the approx for the i-ieme root
1139 do { // Entering the main loop of refinement by Newton's method
1140 p1=1.0;
1141 p2=0.0;
1142 for (j=1;j<=n;j++) { // Loop up the reccurence relation to get the Legendre polynomial at z
1143 p3=p2;
1144 p2=p1;
1145 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
1146 }
1147 // p1 is now the desired Legendre polynomial. We next compute pp, its derivative,
1148 // by a standard relation involving also p2, the polynomial of one lower order
1149 pp=n*(z*p1-p2)/(z*z-1.0);
1150 z1=z;
1151 z=z1-p1/pp; // Newton's method
1152 } while (fabs(z-z1) > EPS_gauleg);
1153 x[i-1]=xm-xl*z; // Scale the root to the desired interval,
1154 x[n-i]=xm+xl*z; // and put in its symetric counterpart.
1155 w[i-1]=2.0*xl/((1.0-z*z)*pp*pp); // Compute the weight
1156 w[n-i]=w[i-1]; // and its symetric counterpart
1157 }
1158}
1159#undef EPS_gauleg
1160
1161/*==========================================================================*/
1162/*
1163++
1164double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
1165 Pour integrer la fonction fonc de xmin a xmax sur npas.
1166 On emploit une methode Higher-order-gaussienne d'ordre 8, ce qui
1167 fait un calcul equivalent de N*npas pas.
1168--
1169*/
1170double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas)
1171{
1172int i,j;
1173double dlim,sum,xc,xci;
1174
1175if( xmax <= xmin ) return(0.);
1176if( npas <= 0 ) npas=1;
1177sum = 0.;
1178dlim = (xmax-xmin)/npas;
1179for(i=0;i<npas;i++) {
1180 xci = (double) i + 0.5;
1181 for(j=0;j<mIhoq8;j++) {
1182 xc = xmin + ( xci + Ihoq8X[j] ) * dlim;
1183 sum += fonc(xc) * Ihoq8W[j];
1184} }
1185return(sum*dlim);
1186}
1187
1188/*=========================================================================*/
1189/*
1190++
1191double Integ_Fun_2D -
1192 (double (*fonc)(double x,double y) -
1193 ,double xmin,double xmax,double ymin,double ymax -
1194 ,int npasx,int npasy)
1195
1196 Integration 2D de fonc(x,y) dans le carre [xmin,xmax] et [ymin,ymax]
1197--
1198*/
1199double Integ_Fun_2D(double (*fonc)(double x,double y)
1200 ,double xmin,double xmax,double ymin,double ymax
1201 ,int npasx,int npasy)
1202{
1203int i,j;
1204double x,y,pasx,pasy,sum,sumy;
1205
1206pasx = (xmax-xmin)/npasx;
1207pasy = (ymax-ymin)/npasy;
1208
1209sum = 0.;
1210for(i=0;i<npasx;i++) {
1211 x = xmin + ((double) i + 0.5 ) * pasx;
1212 sumy = 0.;
1213 for(j=0;j<npasy;j++) {
1214 y = ymin + ((double) j + 0.5 ) * pasy;
1215 sumy += fonc(x,y);
1216 }
1217 sum += sumy;
1218}
1219return( sum*pasx*pasy);
1220}
1221
1222/*=========================================================================*/
1223/* Christophe 01/07/94 */
1224/*
1225++
1226void Set_FitFunDPol(int DPol)
1227 Pour donner l'ordre du polynome pour le fit.
1228--
1229*/
1230void Set_FitFunDPol(int DPol)
1231{
1232FITFUN_DPOL = DPol;
1233}
1234
1235/*==================================================================*/
1236/* Christophe 01/07/94 */
1237/*
1238++
1239double Gauss1DPolF(double x,double *Par,double *DgDpar)
1240 Fonction de fit Gausienne+polynome.
1241--
1242*/
1243/*
1244++
1245| f(x) = par[0]*exp[-0.5*( (x-par[1]) / par[2] )**2 ]
1246| +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
1247| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1248--
1249*/
1250double Gauss1DPolF(double x,double *Par,double *DgDpar)
1251{
1252double f,xc,xc2,e,xpow;
1253int i;
1254
1255xc = (x-Par[1])/Par[2];
1256xc2 = xc*xc;
1257e = exp(-0.5*xc2);
1258f = Par[0]*e;
1259
1260DgDpar[0] = e;
1261DgDpar[1] = xc / Par[2] *f;
1262DgDpar[2] = xc2/ Par[2] *f;
1263
1264if(FITFUN_DPOL>=0) {
1265 xpow = 1.;
1266 for(i=0;i<=FITFUN_DPOL;i++) {
1267 DgDpar[3+i] = xpow;
1268 f += Par[3+i]*xpow;
1269 xpow *= x;
1270 }
1271}
1272
1273return (f);
1274}
1275
1276/*==================================================================*/
1277/* Christophe 29/08/95 */
1278/*
1279++
1280double GaussI1DPol(double x,double *Par,double *DgDpar)
1281 Fonction de fit Gausienne integree+polynome.
1282--
1283*/
1284/*
1285++
1286| f(x) = par[0] / (sqrt(2*Pi)*par[2]) * exp[-0.5*( (x-par[1]) / par[2] )**2 ]
1287| +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL
1288| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1289--
1290*/
1291double GaussI1DPol(double x,double *Par,double *DgDpar)
1292{
1293double f,xc,xc2,e,xpow;
1294int i;
1295
1296xc = (x-Par[1])/Par[2];
1297xc2 = xc*xc;
1298e = exp(-0.5*xc2)/(S2Pi*Par[2]);
1299f = Par[0]*e;
1300
1301DgDpar[0] = e;
1302DgDpar[1] = xc / Par[2] *f;
1303DgDpar[2] = (xc2-1.)/ Par[2] *f;
1304
1305if(FITFUN_DPOL>=0) {
1306 xpow = 1.;
1307 for(i=0;i<=FITFUN_DPOL;i++) {
1308 DgDpar[3+i] = xpow;
1309 f += Par[3+i]*xpow;
1310 xpow *= x;
1311 }
1312}
1313
1314return (f);
1315}
1316
1317/*====================================================================*/
1318/* Christophe 01/07/94 */
1319/*
1320++
1321double Polyn1D(double x,double *Par,double *DgDpar)
1322 Fonction de fit de polynome.
1323--
1324*/
1325/*
1326++
1327| f(x) = par[0] + par[1]*x + .... + par[FITFUN_DPOL]*x**FITFUN_DPOL
1328| FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol
1329--
1330*/
1331double Polyn1D(double x,double *Par,double *DgDpar)
1332{
1333double f,xpow;
1334int i,DPol;
1335
1336DPol = (FITFUN_DPOL<0) ? 0 : FITFUN_DPOL ;
1337xpow = 1.;
1338f = 0.;
1339for(i=0;i<=DPol;i++)
1340 {
1341 DgDpar[i] = xpow;
1342 f += Par[i]*xpow;
1343 xpow *= x;
1344 }
1345return (f);
1346}
1347
1348/*=========================================================================*/
1349/*
1350++
1351double FitProp(double *x,double *y,double *ey,int *n,double *a1)
1352 Fit d'une proportion a1: y = a1 * x
1353--
1354*/
1355/*
1356++
1357| Input:
1358| x = tableau des abscisses
1359| y = tableau des ordonnees
1360| ey = erreurs sur les y
1361| n = nombre de donnees en entree
1362| Output:
1363| n = nombre de points utilises (point non utilise si ey<=0)
1364| a1 coefficient
1365| Return:
1366| valeur du xi2 si fit reussi,
1367| -1. si pas assez de points
1368| -2. si determinant negatif
1369--
1370*/
1371double FitProp(double *x,double *y,double *ey,int *n,double *a1)
1372{
1373register int i,np;
1374register double X2,XY,Y2,w;
1375
1376np=0;
1377X2=XY=Y2=*a1=0.;
1378for(i=0;i<*n;i++) {
1379 if(ey[i]<=0.) continue;
1380 np++;
1381 w = ey[i]*ey[i];
1382 X2 += x[i]*x[i]/w;
1383 XY += x[i]*y[i]/w;
1384 Y2 += y[i]*y[i]/w;
1385}
1386*n = np;
1387if(np<1) return(-1.);
1388if(X2==0.) return(-2.);
1389*a1 = XY/X2;
1390w = Y2 + *a1**a1*X2 -2.**a1*XY;
1391return(w);
1392}
1393
1394/*=========================================================================*/
1395/*
1396++
1397double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
1398 Fit d'une droite: y=a0+a1*x
1399--
1400*/
1401/*
1402++
1403| Input:
1404| x = tableau des abscisses
1405| y = tableau des ordonnees
1406| ey = erreurs sur les y
1407| n = nombre de donnees en entree
1408| Output:
1409| n = nombre de points utilises (point non utilise si ey<=0)
1410| a0,a1 coefficients de la droite
1411| Return:
1412| valeur du xi2 si fit reussi,
1413| -1. si pas assez de points
1414| -2. si determinant negatif
1415--
1416*/
1417double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1)
1418{
1419register int i,np;
1420register double I,X,X2,Y,XY,Y2,w;
1421
1422np=0;
1423Y2=I=X=X2=Y=XY=*a0=*a1=0.;
1424for(i=0;i<*n;i++) {
1425 if(ey[i]<=0.) continue;
1426 np++;
1427 w = ey[i]*ey[i];
1428 I += 1./w;
1429 X += x[i]/w;
1430 X2 += x[i]*x[i]/w;
1431 Y += y[i]/w;
1432 Y2 += y[i]*y[i]/w;
1433 XY += x[i]*y[i]/w;
1434}
1435*n = np;
1436if(np<2) return(-1.);
1437w = X*X-X2*I;
1438if(w==0.) return(-2.);
1439*a1 = (Y*X-XY*I)/w;
1440*a0 = (X*XY-X2*Y)/w;
1441w = Y2 + *a0**a0*I + *a1**a1*X2
1442 + 2.*( - Y**a0 - *a1*XY + *a0**a1*X );
1443return(w);
1444}
1445
1446/*=========================================================================*/
1447/*
1448++
1449double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
1450 Fit d'une parabole: y=a0+a1.x+a2.x^2
1451--
1452*/
1453/*
1454++
1455| Input:
1456| x = tableau des abscisses
1457| y = tableau des ordonnees
1458| ey = erreurs sur les y
1459| n = nombre de donnees en entree
1460| Output:
1461| n = nombre de points utilises (point non utilise si ey<=0)
1462| a0,a1 coefficients de la droite
1463| Return:
1464| valeur du xi2 si fit reussi,
1465| -1. si pas assez de points
1466| -2. si determinant negatif
1467--
1468*/
1469double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2)
1470{
1471register int i,np;
1472register double I,X,X2,X3,X4,Y,Y2,XY,X2Y,w,x2;
1473
1474np=0;
1475I=X=X2=X3=X4=Y=Y2=XY=X2Y=*a0=*a1=*a2=0.;
1476
1477for(i=0;i<*n;i++) {
1478 if(ey[i]<=0.) continue;
1479 np++;
1480 x2 = x[i]*x[i];
1481 w = ey[i]*ey[i];
1482 I += 1./w;
1483 X += x[i]/w;
1484 X2 += x2/w;
1485 X3 += x2*x[i]/w;
1486 X4 += x2*x2/w;
1487 Y += y[i]/w;
1488 Y2 += y[i]*y[i]/w;
1489 XY += x[i]*y[i]/w;
1490 X2Y += x2*y[i]/w;
1491}
1492*n = np;
1493if(np<3) return(-1.);
1494w = X2*(X2*X2-X3*X) -X*(X3*X2-X4*X) +I*(X3*X3-X4*X2);
1495if(w==0.) return(-2.);
1496*a2 = (Y*(X2*X2-X3*X) -XY*(X*X2-X3*I) +X2Y*(X*X-X2*I) )/w;
1497*a1 = -(Y*(X3*X2-X4*X) -XY*(X2*X2-X4*I) +X2Y*(X2*X-X3*I) )/w;
1498*a0 = (Y*(X3*X3-X4*X2) -XY*(X2*X3-X4*X) +X2Y*(X2*X2-X3*X))/w;
1499w = Y2 + *a0**a0*I + *a1**a1*X2 + *a2**a2*X4
1500 +2.*( -Y**a0 -*a1*XY -*a2*X2Y
1501 +*a0**a1*X +*a0**a2*X2+*a1**a2*X3 );
1502return(w);
1503}
1504
1505/*=========================================================================*/
1506/*
1507++
1508double FitParLin -
1509 (double *xx,double *y,double *ey,int *n,double x0,int Deg_d -
1510 ,double *a0,double *a1,double *b1,double *b2)
1511
1512--
1513*/
1514/*
1515++
1516| Fit d'une parabole: y=a0+b1*(x-x0)+b2*(x-x0)**2
1517| pour x>x0
1518| et d'une droite: y=a0+a1*(x-x0) pour x<=x0
1519| Input:
1520| x = tableau des abscisses
1521| y = tableau des ordonnees
1522| ey = erreurs sur les y
1523| n = nombre de donnees en entree
1524| x0 = abscisse du point pivot (il n'est pas fitte)
1525| Deg_d = degre du fit a droite de x0 (1 ou 2)
1526| Output:
1527| n = nombre de points utilises (point non utilise si ey<=0)
1528| a0,a1 coefficients de la droite
1529| a0,b1,b2 coefficients de la parabole
1530--
1531*/
1532/*
1533++
1534| Return:
1535| valeur du xi2 si fit reussi,
1536| -1. si pas assez de points
1537| -2. si determinant negatif
1538| Remarque:
1539| Il faut evidemment au moins 2 points a gauche du pivot x0
1540| et 3 points a droite du pivot x0
1541| Matrices A * a = B :
1542| | I_ X_g X_d X2_d | | a0 | | Y_ |
1543| | X_g X2_g 0 0 | * | a1 | = | XY_g |
1544| | X_d 0 X2_d X3_d | | b1 | | XY_d |
1545| | X2_d 0 X3_d X4_d | | b2 | | X2Y_d |
1546--
1547*/
1548double FitParLin(double *xx,double *y,double *ey,int *n,double x0,int Deg_d
1549 ,double *a0,double *a1,double *b1,double *b2)
1550{
1551int i,np,npg,npd,nddl;
1552double w,x,x2,A[4][4],B[4];
1553double Y2,I,Y,X_g,X2_g,XY_g,X_d,X2_d,X3_d,X4_d,XY_d,X2Y_d;
1554
1555if( Deg_d<1 || Deg_d>2 ) Deg_d=2;
1556nddl = Deg_d + 2;
1557*a0=*a1=*b1=*b2=0.;
1558Y2=I=Y=X_g=X2_g=XY_g=X_d=X2_d=X3_d=X4_d=XY_d=X2Y_d=0.;
1559np=npg=npd=0;
1560for(i=0;i<*n;i++) {
1561 if(ey[i]<=0.) continue;
1562 np++;
1563 x = xx[i]-x0;
1564 x2 = x*x;
1565 w = ey[i]*ey[i];
1566 I += 1./w;
1567 Y += y[i]/w;
1568 Y2 += y[i]*y[i]/w;
1569 if(x<=0.) {
1570 if(x<0.) npg++;
1571 X_g += x/w;
1572 X2_g += x2/w;
1573 XY_g += x*y[i]/w;;
1574 } else {
1575 npd++;
1576 X_d += x/w;
1577 X2_d += x2/w;
1578 X3_d += x2*x/w;
1579 X4_d += x2*x2/w;
1580 XY_d += x*y[i]/w;;
1581 X2Y_d += x2*y[i]/w;;
1582 }
1583}
1584*n = np;
1585A[0][0] = I;
1586A[1][1] = X2_g;
1587A[3][3] = X4_d;
1588A[0][1] = A[1][0] = X_g;
1589A[0][2] = A[2][0] = X_d;
1590A[3][2] = A[2][3] = X3_d;
1591A[0][3] = A[3][0] = A[2][2] = X2_d;
1592A[1][2] = A[2][1] = A[1][3] = A[3][1] = 0.;
1593B[0] = Y;
1594B[1] = XY_g;
1595B[2] = XY_d;
1596B[3] = X2Y_d;
1597if( np<4 || npg < 1 || npd < 2 ) return(-1.);
1598w = GausPiv(&A[0][0],4,nddl,B,1,1,0);
1599if(w==0.) return(-2.);
1600*a0 = B[0];
1601*a1 = B[1];
1602*b1 = B[2];
1603if(nddl==4) *b2 = B[3];
1604w = Y2 + *a0**a0*I + *a1**a1*X2_g + *b1**b1*X2_d + *b2**b2*X4_d
1605 + 2.*( - *a0*Y - *a1*XY_g + *a0**a1*X_g
1606 - *b1*XY_d - *b2*X2Y_d + *a0**b1*X_d + *a0**b2*X2_d + *b1**b2*X3_d
1607 );
1608return(w);
1609}
1610
1611/*=========================================================================*/
1612/*
1613++
1614double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
1615 Fit de y(i) = a1*x(i) en deux passes:
1616--
1617*/
1618/*
1619++
1620| 1-/ fit avec tous les points
1621| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1622| Input:
1623| x = tableau des abscisses
1624| y = tableau des ordonnees
1625| ey = erreurs sur les y
1626| n = nombre de donnees en entree
1627| per_clean = pourcentage des points a tuer pour la seconde passe
1628--
1629*/
1630/*
1631++
1632| Output:
1633| n = nombre de points utilises (point non utilise si ey<=0)
1634| a1 = coefficients de proportionalite
1635| Return:
1636| valeur du xi2 si fit reussi,
1637| -1. si echec fit passe no 1
1638| -2. si echec fit passe no 2
1639| -3. si probleme malloc
1640| -4. si probleme nombre de points a tuer
1641--
1642*/
1643double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1)
1644{
1645int npt,k,i,nclass;
1646double *clas,aa1,c2,cut;
1647
1648*a1 =0.;
1649
1650/* 1ere passe */
1651npt = *n;
1652c2 = FitProp(x,y,ey,&npt,&aa1);
1653if(c2<0.) {*n = npt; return(-1.);}
1654*a1 = aa1;
1655/* printf("pass 1: %g*x c2=%g/%d\n",*a1,c2,npt); */
1656
1657clas = (double*) malloc( *n * sizeof(double) );
1658if( clas == NULL ) {*n=npt; return(-3.);}
1659
1660/* elimination des mauvais points */
1661nclass = 0;
1662for(i=0;i<*n;i++) {
1663 if(ey[i]<=0.) continue;
1664 c2 = (y[i]-aa1*x[i])/ey[i];
1665 clas[nclass] = c2*c2;
1666 nclass++;
1667}
1668qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1669k = (int) ( (1. - per_clean ) * (double) nclass );
1670if(k<0) k=0;
1671if(k>=nclass) k = nclass-1;
1672cut = clas[k];
1673k = 0;
1674for(i=0;i<*n;i++) {
1675 clas[i] = ey[i];
1676 c2 = (y[i]-aa1*x[i])/ey[i];
1677 c2 *= c2;
1678 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1679}
1680/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1681
1682/* 2sd passe */
1683npt = *n;
1684c2 = FitProp(x,y,clas,&npt,&aa1);
1685if(c2<0.) {*n = npt; free(clas); return(-2.);}
1686*a1 = aa1;
1687*n = npt;
1688/* printf("pass 2: %g*x c2=%g/%d\n",*a1,c2,npt); */
1689
1690free(clas);
1691return(c2);
1692}
1693
1694/*=========================================================================*/
1695/*
1696++
1697double FitLinClean -
1698 (double *x,double *y,double *ey,int *n -
1699 ,double per_clean,double *a0,double *a1)
1700
1701 Fit de y(i) = a0 + a1*x(i) en deux passes:
1702--
1703*/
1704/*
1705++
1706| 1-/ fit avec tous les points
1707| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1708| Input:
1709| x = tableau des abscisses
1710| y = tableau des ordonnees
1711| ey = erreurs sur les y
1712| n = nombre de donnees en entree
1713| per_clean = pourcentage des points a tuer pour la seconde passe
1714| Output:
1715| n = nombre de points utilises (point non utilise si ey<=0)
1716| a0,a1 = coefficients de la droite
1717--
1718*/
1719/*
1720++
1721| Return:
1722| valeur du xi2 si fit reussi,
1723| -1. si echec fit passe no 1
1724| -2. si echec fit passe no 2
1725| -3. si probleme malloc
1726| -4. si probleme nombre de points a tuer
1727--
1728*/
1729double FitLinClean(double *x,double *y,double *ey,int *n
1730 ,double per_clean,double *a0,double *a1)
1731{
1732int npt,k,i,nclass;
1733double *clas,aa0,aa1,c2,cut;
1734
1735*a0 = *a1 =0.;
1736
1737/* 1ere passe */
1738npt = *n;
1739c2 = FitLin(x,y,ey,&npt,&aa0,&aa1);
1740if(c2<0.) {*n = npt; return(-1.);}
1741*a0 = aa0;
1742*a1 = aa1;
1743/* printf("pass 1: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
1744
1745clas = (double*) malloc( *n * sizeof(double) );
1746if( clas == NULL ) {*n=npt; return(-3.);}
1747
1748/* elimination des mauvais points */
1749nclass = 0;
1750for(i=0;i<*n;i++) {
1751 if(ey[i]<=0.) continue;
1752 c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
1753 clas[nclass] = c2*c2;
1754 nclass++;
1755}
1756qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1757k = (int) ( (1. - per_clean ) * (double) nclass );
1758if(k<0) k=0;
1759if(k>=nclass) k = nclass-1;
1760cut = clas[k];
1761k = 0;
1762for(i=0;i<*n;i++) {
1763 clas[i] = ey[i];
1764 c2 = (y[i]-(aa0+aa1*x[i]))/ey[i];
1765 c2 *= c2;
1766 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1767}
1768/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1769
1770/* 2sd passe */
1771npt = *n;
1772c2 = FitLin(x,y,clas,&npt,&aa0,&aa1);
1773if(c2<0.) {*n = npt; free(clas); return(-2.);}
1774*a0 = aa0;
1775*a1 = aa1;
1776*n = npt;
1777/* printf("pass 2: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */
1778
1779free(clas);
1780return(c2);
1781}
1782
1783/*===================================================================*/
1784/*
1785++
1786double FitParClean -
1787 (double *x,double *y,double *ey,int *n -
1788 ,double per_clean,double *a0,double *a1,double *a2)
1789
1790 Fit de y(i) = a0 + a1*x(i) + a2*x(i)^2 en deux passes:
1791--
1792*/
1793/*
1794++
1795| 1-/ fit avec tous les points
1796| 2-/ fit ou on enleve les per_clean*n points les plus eloignes
1797| Input:
1798| x = tableau des abscisses
1799| y = tableau des ordonnees
1800| ey = erreurs sur les y
1801| n = nombre de donnees en entree
1802| per_clean = pourcentage des points a tuer pour la seconde passe
1803| Output:
1804| n = nombre de points utilises (point non utilise si ey<=0)
1805| a0,a1,a2 = coefficients de la parabole
1806| Return:
1807| valeur du xi2 si fit reussi,
1808| -1. si echec fit passe no 1
1809| -2. si echec fit passe no 2
1810| -3. si probleme malloc
1811| -4. si probleme nombre de points a tuer
1812--
1813*/
1814double FitParClean(double *x,double *y,double *ey,int *n
1815 ,double per_clean,double *a0,double *a1,double *a2)
1816{
1817int npt,k,i,nclass;
1818double *clas,aa0,aa1,aa2,c2,cut;
1819
1820*a0 = *a1 = *a2 =0.;
1821
1822/* 1ere passe */
1823npt = *n;
1824c2 = FitPar(x,y,ey,&npt,&aa0,&aa1,&aa2);
1825if(c2<0.) {*n = npt; return(-1.);}
1826*a0 = aa0;
1827*a1 = aa1;
1828*a2 = aa2;
1829/* printf("pass 1: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
1830
1831clas = (double*) malloc( *n * sizeof(double) );
1832if( clas == NULL ) {*n=npt; return(-3.);}
1833
1834/* elimination des mauvais points */
1835nclass = 0;
1836for(i=0;i<*n;i++) {
1837 if(ey[i]<=0.) continue;
1838 c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
1839 clas[nclass] = c2*c2;
1840 nclass++;
1841}
1842qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble);
1843k = (int) ( (1. - per_clean ) * (double) nclass );
1844if(k<0) k=0;
1845if(k>=nclass) k = nclass-1;
1846cut = clas[k];
1847k = 0;
1848for(i=0;i<*n;i++) {
1849 clas[i] = ey[i];
1850 c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i];
1851 c2 *= c2;
1852 if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;}
1853}
1854/* printf("nombre pt tues %d cut=%g\n",k,cut); */
1855
1856/* 2sd passe */
1857npt = *n;
1858c2 = FitPar(x,y,clas,&npt,&aa0,&aa1,&aa2);
1859if(c2<0.) {*n = npt; free(clas); return(-2.);}
1860*a0 = aa0;
1861*a1 = aa1;
1862*a2 = aa2;
1863*n = npt;
1864/* printf("pass 2: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */
1865
1866free(clas);
1867return(c2);
1868}
1869
1870/*===========================================================*/
1871/*
1872++
1873float interpole(float m,int n,float *t1,float *t2)
1874 Interpolation lineaire y=f(x):
1875--
1876*/
1877/*
1878++
1879| t1[n] = tableau des x
1880| t2[n] = tableau des y
1881| m = valeur ou on interpole
1882| RETURN: f(m)
1883--
1884*/
1885float interpole(float m,int n,float *t1,float *t2)
1886{
1887int i,n1;
1888float r;
1889
1890if ( n == 1 ) return ( t2[0] );
1891
1892n1=n-1;
1893if ( m < t1[0] ) m=t1[0];
1894if ( m > t1[n1] ) m=t1[n1];
1895
1896for(i=0;i<n;i++) if ( m <= t1[i] ) break;
1897i = (i==0) ? 1 : i;
1898i = (i==n) ? n1 : i;
1899
1900r = t2[i-1] + (t2[i]-t2[i-1]) / (t1[i]-t1[i-1]) * (m-t1[i-1]);
1901
1902/*
1903printf("interpole: i=%3d m=%g t1=%g %g t2=%g %g r=%g\n"
1904 ,i,m,t1[i-1],t1[i],t2[i-1],t2[i],r);
1905for(i=0;i<n;i++) printf(" (%g,%g)",t1[i],t2[i]); printf("\n");
1906*/
1907
1908return(r);
1909}
1910
1911/*=========================================================*/
1912/* Christophe 10/11/93 La Silla */
1913/*
1914++
1915int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
1916 Fonction de calcul de la moyenne tronquee et du sigma d'un tableau
1917--
1918*/
1919/*
1920++
1921| Methode: 1-/ moyenne-sigma, 2-/ moyenne tronquee et sigma,
1922| ENTREE:
1923| mag: magnitude
1924| err: erreur sur la magnitude
1925| ndata: nombre de donnees
1926| nsigma: nombre de sigma dans lequel on calcule le maximum
1927| si <=0, une seule passe pour la moyenne
1928| SORTIE:
1929| ndata: nombre de data utilises pour calculer mean et sigma
1930| mean: moyenne des donnees
1931| sigma: sigma des donnees
1932| MeanSig: 0 si calcul ok, <0 sinon
1933--
1934*/
1935int_4 MeanSig(float *mag,float *err,int_4 *ndata,float nsigma,float *mean,float *sigma)
1936{
1937int_4 deb=DEB_MeanSig;
1938int_4 pass,passmx,i,n=0;
1939double m,s2,v,scut;
1940
1941*mean = *sigma = 0.;
1942passmx = ( nsigma <= 0. ) ? 1 : 2 ;
1943for (pass=1;pass<=passmx;pass++) {
1944 m = s2 = 0.;
1945 n=0;
1946 scut = GRAND;
1947 if( pass == 2 ) scut=nsigma* *sigma;
1948 for (i=0;i<*ndata;i++) {
1949 v = *(mag+i);
1950 if( *(err+i) > 0. && fabs(v-*mean) < scut ) {
1951 n++;
1952 m += v;
1953 s2 += v * v;
1954 } }
1955 if ( n >= 2 ) {
1956 *mean = m / n;
1957 *sigma = sqrt( s2 / n - m/n * m/n );
1958 } else {
1959 *mean = *sigma = 0.;
1960 *ndata=n;
1961 return(-1);
1962 }
1963 if ( deb>0 ) printf("MeanSig: pass=%d mean=%f sigma=%f n=%d\n"
1964 ,pass,*mean,*sigma,n);
1965}
1966*ndata=n;
1967return(0);
1968}
1969
1970/*=========================================================================*/
1971/*
1972++
1973int Most_Probable -
1974 ( float *val, int nval, float binin, int nmoy -
1975 , float low, float high, float *most, int deb)
1976
1977 Pour calculer la valeur la plus probable par maximum d'histogramme.
1978--
1979*/
1980/*
1981++
1982| INPUT:
1983| - val= pointeur sur un tableau de valeurs (float).
1984| - nval= nombre de valeurs a traiter.
1985| - binin= taille du bin.
1986| - nmoy= la valeur retournee est la moyenne de +/- nmoy bins
1987| autour du max de l'histo.
1988| - low, high= les valeurs permises mini et maxi des valeurs
1989| (si low>high calcul automatique).
1990| - deb= niveau de debug.
1991| OUTPUT:
1992| - most = valeur la plus probable.
1993| RETURN CODE:
1994| -1 : nval <=0
1995| -2 : bin <=0
1996| -3 : low>=high apres cadrage automatique
1997| -4 : nombre de valeurs remplies nul au niveau de la 1ere passe
1998| -51 : pas trouve de maximum 1ere passe
1999| -52 : pas trouve de maximum 2sd passe
2000--
2001*/
2002int Most_Probable( float *val, int nval, float binin, int nmoy
2003 , float low, float high, float *most, int deb)
2004{
2005int histo[503],i,nbin,n,ib,ibmax,vmax,pass;
2006float bin,xmax=0.;
2007double moy,sum;
2008
2009if(deb>1) printf("Most_Probable: nval=%d binin=%f nmoy=%d low,high=%f %f\n"
2010 ,nval,binin,nmoy,low,high);
2011if (nval<=0) return(-1);
2012if (binin<=0.) return(-2);
2013nmoy = (nmoy<0) ? 0 : nmoy;
2014if(low>= high) {
2015 low = GRAND;
2016 high = -low;
2017 for(i=0;i<nval;i++) {if(val[i]>high) high=val[i]; if(val[i]<low) low=val[i];}
2018}
2019if(deb>1) printf("nmoy=%d low,high=%f %f\n",nmoy,low,high);
2020if(low>= high) return(-3);
2021
2022/* premiere passe "nbin" bins entre low et high, nbin=min(high-low)/bin+1,501) */
2023/* seconde passe "nbin" autour du maxi 1ere passe, nbin=min(high-low)/bin,501) */
2024
2025for ( pass=1;pass<=2;pass++) {
2026
2027 bin=binin;
2028 nbin = (int) ( (high-low)/bin ) + 1;
2029 if(nbin>501) {
2030 nbin = 501;
2031 if(pass!=1){
2032 low = xmax - 250*binin - binin/2.;
2033 high = xmax + 250*binin + binin/2.;
2034 } }
2035 /* re-scaling du bin pour etre sur */
2036 bin=(high-low)/nbin;
2037 if(deb>1) printf("pass=%2d low,high=%f %f bin=%f nbin=%d\n"
2038 ,pass,low,high,bin,nbin);
2039 for(i=0;i<nbin;i++) histo[i]=0;
2040 n=0;
2041 for(i=0;i<nval;i++) {
2042 if( val[i]>=high || val[i]<low ) continue;
2043 ib = (int) ((val[i]-low)/bin);
2044 if( ib<0 && ib >= nbin ) continue;
2045 histo[ib]++;
2046 n++;
2047 }
2048 if(n<=0) return (-4);
2049 vmax = -1; ibmax= -1;
2050 if(n<=0) return (-4);
2051 for(i=0;i<nbin;i++) {
2052 if(histo[i]<vmax) continue;
2053 vmax = histo[i];
2054 ibmax = i;
2055 }
2056 if(ibmax<0) return (-50-pass);
2057 xmax = low + ibmax*bin + bin/2.;
2058 if(deb>1) printf("bin du maximum %5d (%d) abscisse=%f\n",ibmax,vmax,xmax);
2059 if(deb>3) {
2060 printf("histogramme:\n");
2061 for (i= ibmax-25;i<=ibmax+25;i++) {
2062 if (i<0) continue;
2063 if (i>=nbin) break;
2064 printf(" %5d",histo[i]);
2065 if(i%10==9) printf("\n");
2066 }
2067 printf("\n");
2068 }
2069}
2070
2071sum = moy =0.; n=0;
2072for (i= -nmoy;i<=nmoy;i++) {
2073 if (ibmax-i>=0 && ibmax+i<nbin) {
2074 moy += ( xmax + i * bin ) * histo[ibmax+i];
2075 sum += (double) histo[ibmax+i];
2076 n++;
2077} }
2078
2079*most = moy / sum;
2080if(deb>0) printf("Most_probable: most=%f (avec %d points)\n",*most,n);
2081
2082return(0);
2083
2084}
2085
2086/*============================================================*/
2087/* Christophe 27/01/95 */
2088/*
2089++
2090float Ajust_GaFn
2091| (int Ns,float *fcfr
2092| ,float *haut,float *ehaut,float *mean,float *emean
2093| ,float *sigma,float *esigma,float *fond,float *efond
2094| ,int fixfond,int NBIN_RESOL
2095| ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
2096
2097 Fonction de fit gaussienne + fond (1D) du tableau fcfr
2098 avec reglage des parametres d'entree.
2099--
2100*/
2101/*
2102++
2103| ATTENTION: le tableau fcfr est modifie !!!
2104| ---------
2105| ENTREES:
2106| Ns = nombre d'entrees dans fcfr
2107| fcfr = tableau des valeurs a fitter
2108| fond = valeur a donner au fond si fixfond = 1
2109| fixfond = 1 fond fixe dans le fit a la valeur fond
2110| = 2 fond fixe dans le fit a une valeur
2111| calculee automatiquement sur
2112| les bords de l'histogramme
2113| > 2 fond fixe a zero (<=> 1 + fond=0)
2114| <= 0 fond libre dans le fit
2115| NBIN_RESOL = nombre maxi de bins pour l'histo de fit
2116| de la resolution
2117| perc_net = pourcentage de donnees a nettoyer pour
2118| calculer mean,sigma de la 1ere passe
2119| frac_sgb = le bin de fit sera sigma*fracsgb
2120| ou sigma est calcule en premiere passe
2121| dyn_sgb = limites de l'histo de fit
2122| xmin=mean-dyn_sgb*sigma , xmax=mean+dyn_sgb*sigma
2123| deb = niveau de debug
2124--
2125*/
2126/*
2127++
2128| SORTIES:
2129| haut = valeur de la hauteur
2130| ehaut = erreur sur la valeur de la hauteur
2131| mean = valeur moyenne du decalage
2132| emean = erreur sur la valeur moyenne du decalage
2133| sigma = valeur de la resolution
2134| esigma = erreur sur la valeur de la resolution
2135| fond = valeur du fond
2136| efond = erreur sur la valeur du fond
2137| return code = chi2 du fit (<0 si Pb)
2138--
2139*/
2140float Ajust_GaFn(int Ns,float *fcfr
2141 ,float *haut,float *ehaut,float *mean,float *emean
2142 ,float *sigma,float *esigma,float *fond,float *efond
2143 ,int fixfond,int NBIN_RESOL
2144 ,float perc_net,float frac_sgb,float dyn_sgb,int deb)
2145{
2146int_4 i,j,i1,i2,nbin,ibin,entries;
2147float c2,xmin,xmax,binw,ymax;
2148float *y,*ey,*x;
2149double m,s;
2150FLOATDOUBLE X,Y,EY;
2151double (*Fun) (double ,double *,double *);
2152int_4 npar,n;
2153double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
2154
2155fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
2156perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
2157NBIN_RESOL = ( NBIN_RESOL <= 0 ) ? 50 : NBIN_RESOL;
2158frac_sgb = ( frac_sgb <= 0. ) ? 0.5 : frac_sgb;
2159dyn_sgb = ( dyn_sgb <= 0. ) ? 5.0 : dyn_sgb;
2160x = y = ey = NULL;
2161x = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2162y = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2163ey = (float *) calloc(NBIN_RESOL+2,sizeof(float));
2164if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
2165
2166if(deb>0) printf("Ajust_GaFn[%d] perc_net=%f nbin=%d frac_sgb=%f dyn_sgb=%f\n"
2167 ,Ns,perc_net,NBIN_RESOL,frac_sgb,dyn_sgb);
2168
2169/* on vire perc_net % des points a gauche et a droite de la distribution */
2170qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2171i = perc_net * Ns;
2172if(perc_net>0. && i==0) i=1;
2173i1 = i; i2 = Ns-1-i;
2174if(deb>1) {
2175 printf(" df/f=");
2176 for(j=0;j<10;j++) printf("%8.2f ",fcfr[j]);
2177 printf("\n");
2178 printf("selection de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
2179}
2180if(i2<=i1) { c2= -101.; goto END;}
2181
2182/* calcul mean et sigma 1ere passe */
2183m = s = 0.; j = 0;
2184for(i=i1;i<=i2;i++) {m += fcfr[i]; s += fcfr[i]*fcfr[i]; j++;}
2185m /= j;
2186s = sqrt(s/j - m*m);
2187*mean = m; *sigma = s;
2188if(deb>1) printf("premiere passe: mean=%f sigma=%f\n",*mean,*sigma);
2189
2190/* remplissage histo a +/- dyn_sgb * sigma */
2191xmin = *mean - dyn_sgb* *sigma;
2192xmax = *mean + dyn_sgb* *sigma;
2193if(xmin>=xmax) {c2 = -102.; goto END;}
2194binw = *sigma * frac_sgb;
2195nbin = (xmax-xmin)/binw;
2196if(nbin<6) nbin=6; if(nbin>NBIN_RESOL) nbin=NBIN_RESOL;
2197binw = (xmax-xmin)/nbin;
2198for(i=0;i<nbin;i++)
2199 {x[i] = xmin + ((float) i + 0.5)*binw; y[i] = 0.;}
2200if(deb>1) {
2201 printf("histo[%d] lim=[%f,%f] bw=%f x=\n"
2202 ,nbin,xmin,xmax,binw);
2203 for(j=0;j<nbin;j++)
2204 {printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
2205 if(j%10!=0) printf("\n");
2206}
2207entries = 0;
2208for(i=0;i<Ns;i++) { ibin = (fcfr[i]-xmin)/binw;
2209 if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;} }
2210ymax = 0.;
2211for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
2212 if(y[i]>ymax) ymax=y[i];}
2213if(deb>1) {
2214 printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
2215 for(j=0;j<nbin;j++)
2216 {printf("%8.0f ",y[j]); if(j%10==9) printf("\n");}
2217 if(j%10!=0) printf("\n");
2218 if(deb>2) {
2219 printf("histo ey=\n");
2220 for(j=0;j<nbin;j++)
2221 {printf("%8.0f ",ey[j]); if(j%10==9) printf("\n");}
2222 if(j%10!=0) printf("\n"); }
2223}
2224if(ymax<2.) {c2 = -103.; goto END;}
2225
2226if(fixfond!=1) {
2227 *fond = (y[0]+y[1]+y[nbin-1]+y[nbin-2])/4.;
2228 if(fixfond>2) *fond = 0.;
2229}
2230*haut = ymax - *fond;
2231
2232/* fit gaussienne + fond constant */
2233Fun = Gauss1DPolF ; Set_FitFunDPol(0);
2234X.fx = x;
2235Y.fx = y;
2236EY.fx = ey;
2237par[0] = *haut;
2238par[1] = *mean;
2239par[2] = *sigma;
2240par[3] = *fond;
2241stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
2242stepar[2] = par[2]/10.; stepar[3] = 0.5;
2243if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
2244for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
2245minpar[2] = 0.00001; maxpar[2] = 9999.;
2246npar = 4;
2247stochi2 = 0.0001;
2248n = nbin;
2249j = (deb>2)? 1:0;
2250c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
2251 ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
2252
2253END:
2254
2255if( c2 > 0. ) {
2256 *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3];
2257 *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
2258} else {
2259 *ehaut = *emean = *esigma = *efond = 0.;
2260}
2261if(x !=NULL) free(x);
2262if(y !=NULL) free(y);
2263if(ey!=NULL) free(ey);
2264
2265return(c2);
2266}
2267
2268/*==========================================================*/
2269/* Christophe 27/03/95 */
2270/*
2271++
2272float HFit_GaFn -
2273 (int Ns,float *fcfr -
2274 ,float *haut,float *ehaut,float *mean,float *emean -
2275 ,float *sigma,float *esigma,float *fond,float *efond -
2276 ,int fixfond,int nbin,float xmin,float xmax,int deb)
2277
2278 Fonction de fit gaussienne + fond (1D) du tableau fcfr
2279 dans un histo de "nbin" bins de "xmin a xmax"
2280--
2281*/
2282/*
2283++
2284| ENTREES:
2285| Ns = nombre d'entrees dans fcfr
2286| fcfr = tableau des valeurs a fitter
2287| mean = valeur de depart pour la moyenne
2288| sigma = valeur de depart pour le sigma
2289| fond = valeur de depart pour le fond
2290| fixfond > 0 fond fixe dans le fit a la valeur fond
2291| <= 0 fond libre dans le fit
2292| nbin = nombre de bins pour l'histo de fit
2293| xmin = valeur inferieure de l'histo
2294| xmax = valeur superieure de l'histo
2295| deb = niveau de debug
2296--
2297*/
2298/*
2299++
2300| SORTIES:
2301| haut = valeur de la hauteur
2302| ehaut = erreur sur la valeur de la hauteur
2303| mean = valeur moyenne du decalage
2304| emean = erreur sur la valeur moyenne du decalage
2305| sigma = valeur de la resolution
2306| esigma = erreur sur la valeur de la resolution
2307| fond = valeur du fond
2308| efond = erreur sur la valeur du fond
2309| return code = chi2 du fit (<0 si Pb)
2310--
2311*/
2312float HFit_GaFn(int Ns,float *fcfr
2313 ,float *haut,float *ehaut,float *mean,float *emean
2314 ,float *sigma,float *esigma,float *fond,float *efond
2315 ,int fixfond,int nbin,float xmin,float xmax,int deb)
2316{
2317int_4 i,j,ibin,entries;
2318float c2,binw,ymax;
2319float *y,*ey,*x;
2320FLOATDOUBLE X,Y,EY;
2321double (*Fun) (double ,double *,double *);
2322int_4 npar,n;
2323double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2;
2324
2325if(xmax<=xmin) return(-102);
2326fixfond = ( fixfond <= 0 ) ? 0 : fixfond;
2327nbin = ( nbin <= 0 ) ? 50 : nbin;
2328x = y = ey = NULL;
2329x = (float *) calloc(nbin+2,sizeof(float));
2330y = (float *) calloc(nbin+2,sizeof(float));
2331ey = (float *) calloc(nbin+2,sizeof(float));
2332if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;}
2333
2334if(deb>0) printf("HFit_GaFn[%d pts] nbin=%d de %g a %g\n"
2335 ,Ns,nbin,xmin,xmax);
2336
2337/* remplissage histo */
2338binw = (xmax-xmin)/nbin;
2339for(i=0;i<nbin;i++) {x[i]=xmin+((float) i +0.5)*binw; y[i]=0.;}
2340if(deb>1) {
2341 printf("histo[%d] lim=[%f,%f] bw=%f x=\n",nbin,xmin,xmax,binw);
2342 for(j=0;j<nbin;j++){printf("%8.2f ",x[j]); if(j%10==9) printf("\n");}
2343 if(j%10!=0) printf("\n");
2344}
2345entries = 0;
2346for(i=0;i<Ns;i++) {
2347 ibin = (fcfr[i]-xmin)/binw;
2348 if(ibin>=0 && ibin<nbin) {y[ibin]+=1.; entries++;}
2349}
2350
2351ymax = 0.;
2352for(i=0;i<nbin;i++) {ey[i] = (y[i]>1.)? sqrt((double) y[i]) : 1.;
2353 if(y[i]>ymax) ymax=y[i];}
2354if(deb>1) {
2355 printf("histo (entries=%d) ymax=%f y=\n",entries,ymax);
2356 for(j=0;j<nbin;j++){printf("%8.0f ",y[j]); if(j%10==9)printf("\n");}
2357 if(j%10!=0) printf("\n");
2358 if(deb>2) {
2359 printf("histo ey=\n");
2360 for(j=0;j<nbin;j++){printf("%8.0f ",ey[j]); if(j%10==9)printf("\n");}
2361 if(j%10!=0) printf("\n");
2362} }
2363if(ymax<2.) {c2 = -103.; goto END;}
2364
2365*haut = ymax - *fond;
2366
2367/* fit gaussienne + fond constant */
2368Fun = Gauss1DPolF ; Set_FitFunDPol(0);
2369X.fx = x;
2370Y.fx = y;
2371EY.fx = ey;
2372par[0] = *haut;
2373par[1] = *mean;
2374par[2] = *sigma;
2375par[3] = *fond;
2376stepar[0] = par[0]/10.; stepar[1] = par[2]/5.;
2377stepar[2] = par[2]/10.; stepar[3] = 0.5;
2378if(fixfond) { stepar[3] = 0.; epar[3]=0.;}
2379for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;}
2380minpar[2] = 0.00001; maxpar[2] = 9999.;
2381npar = 4;
2382stochi2 = 0.0001;
2383n = nbin;
2384j = (deb>2)? 1:0;
2385c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par
2386 ,epar,stepar,minpar,maxpar,npar,stochi2,60,j);
2387
2388END:
2389
2390if( c2 > 0. ) {
2391 *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3];
2392 *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3];
2393} else {
2394 *ehaut = *emean = *esigma = *efond = 0.;
2395}
2396if(x !=NULL) free(x);
2397if(y !=NULL) free(y);
2398if(ey!=NULL) free(ey);
2399
2400return(c2);
2401}
2402
2403/*==============================================================*/
2404/* Christophe 15/02/95 */
2405/*
2406++
2407int Ajust_MnSg -
2408 (int Ns,float *fcfr -
2409 ,float *mean,float *emean,float *sigma,float *esigma -
2410 ,float perc_net,float n_sigma,int deb)
2411
2412 Calcul mean sigma tronques du tableau fcfr.
2413--
2414*/
2415/*
2416++
2417| ATTENTION: le tableau fcfr est modifie
2418| ---------
2419| Methode:
2420| 1- calcul de la moyenne Mcent en enlevant perc_net% des pts
2421| les + faibles et perc_net% des pts les + forts
2422| 2- calcul de la valeur cutup correspondant a 2*perc_net%
2423| des pts les + hauts en valeur absolue (fcfr-Mcent)
2424| 3- calcul moyenne et sigma en enlevant les points ayant
2425| abs(fcfr-Mcent) > cutup (1ere passe)
2426| 4- calcul moyenne et sigma en enlevant les points ayant
2427| abs(fcfr-Mcent) > cutup et
2428| abs(fcfr-M(1ere passe)) > n_sigma*sigma(1ere passe)
2429--
2430*/
2431/*
2432++
2433| ENTREES:
2434| Ns = nombre d'entrees dans fcfr
2435| fcfr = tableau des valeurs a fitter
2436| perc_net = pourcentage de donnees a nettoyer pour
2437| calculer mean,sigma
2438| n_sigma = nombre de sigma en passe 2 pour
2439| calculer mean,sigma
2440| deb = niveau de debug
2441| SORTIES:
2442| mean = valeur moyenne du decalage
2443| emean = erreur sur la valeur moyenne du decalage
2444| sigma = valeur de la resolution
2445| esigma = erreur sur la valeur de la resolution
2446| return code = nombre de points utilises (<0 si Pb)
2447--
2448*/
2449int Ajust_MnSg(int Ns,float *fcfr
2450 ,float *mean,float *emean,float *sigma,float *esigma
2451 ,float perc_net,float n_sigma,int deb)
2452{
2453int i,i1,i2,n,nvire,pass;
2454double m,s,mcent,cutup,cuts;
2455float *dum;
2456
2457/* set up des valeurs par defaut */
2458perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net;
2459n_sigma = ( n_sigma <= 0. ) ? 3.0 : n_sigma;
2460nvire = perc_net * Ns;
2461if(perc_net>0. && nvire==0) nvire=1;
2462*emean = *esigma = -1.;
2463if(deb>0) printf("Ajust_MnSg[%d] perc_net=%f (vire=%d) n_sigma=%f\n"
2464 ,Ns,perc_net,nvire,n_sigma);
2465
2466/* on ordonne par ordre croissant de fcfr */
2467qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2468i1 = nvire; i2 = Ns-1-nvire;
2469if(deb>1) printf(" select de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]);
2470if(i2<=i1) return(-101);
2471
2472/* on vire perc_net % des points a gauche et a droite de la distribution */
2473mcent = 0.; n = 0;
2474for(i=i1;i<=i2;i++) {mcent += fcfr[i]; n++;}
2475if(n<1) return(-102);
2476mcent /= (double) n;
2477if(deb>1) printf(" mean cent=%f sur %d points\n",mcent,n);
2478
2479/* allocate space and fill absolute value */
2480if( (dum = (float *) calloc(Ns,sizeof(float))) == NULL ) return(-103);
2481for(i=0;i<Ns;i++) dum[i] = fabs( mcent - fcfr[i] );
2482
2483/* on ordonne par ordre croissant de abs(fcfr-mcent) */
2484qsort(dum,(size_t) Ns,(size_t) sizeof(float),qSort_Float);
2485i = Ns-1-2*nvire;
2486if(i<0) {n= -104; goto END_Ajust_MnSg;}
2487
2488/* on vire 2.*perc_net % des points les + hauts de la distribution */
2489cutup = dum[i];
2490if(deb>1) printf(" cutup=%f sur %d points\n",cutup,i);
2491
2492/* calcul mean et sigma en 2 passes avec coupure n_sigma*sigma(1ere passe)*/
2493cuts = GRAND2;
2494for(pass=1;pass<=2;pass++) {
2495 m = s = 0.; n = 0;
2496 for(i=0;i<Ns;i++) {
2497 if( fabs(mcent-fcfr[i]) > cutup ) continue;
2498 if( fabs((double) (*mean-fcfr[i])) > cuts ) continue;
2499 m += fcfr[i];
2500 s += fcfr[i]*fcfr[i];
2501 n++;
2502 }
2503 if(n<=2) {n= -105; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
2504 m /= n;
2505 s = s/n - m*m;
2506 if(s<=0.) {n= -106; *mean = *sigma = -1.; goto END_Ajust_MnSg;}
2507 s = sqrt(s);
2508 *mean = m;
2509 *sigma = s;
2510 cuts = n_sigma * s;
2511 if(deb>1)
2512 printf(" pass=%d mean=%g sigma=%g (%d pts) cuts=%f\n"
2513 ,pass,*mean,*sigma,n,cuts);
2514}
2515
2516*emean = s/sqrt((double) n);
2517*esigma = s/sqrt(2. * (double) n);
2518if(deb>0) printf("mean=%g (+/-%g) sigma=%g (+/-%g) sur %d pts\n"
2519 ,*mean,*emean,*sigma,*esigma,n);
2520
2521END_Ajust_MnSg:
2522if( dum != NULL ) free(dum);
2523return(n);
2524}
2525
2526/*=================================================================*/
2527/* Nathalie 16/02/95 */
2528/*
2529++
2530float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
2531 Cette fonction calcule l'integrale 3D: f(x,y,z)dx.dy.dz
2532 L'integrale est calculee en incrementant des couronnes cubiques
2533 centrees sur le point de coordonnees (0,0,0)
2534--
2535*/
2536/*
2537++
2538| ENTREES:
2539| fonction = f(x,y,z)
2540| step = pas de l'integration
2541| precision = coupure en dV(couronne i)/Vtot(couronnes 0 a i)
2542| SORTIES:
2543| return: l'integrale
2544| REMARQUES:
2545| la fonction f(x,y,z) doit decroitre tres vite en r**2
2546--
2547*/
2548float Int3DCube(float(*fonction)(float,float,float),float step,float precision)
2549{
2550
2551 float f;
2552 double vol,volprec;
2553 int ecart,i,j,k,l;
2554 int encore,deb=0;
2555
2556 vol = volprec = 0.;
2557
2558 /* contribution du cube central */
2559 for(l=0;l<nd3d;l++) {
2560 f = fonction(dx3d[l]*step,dy3d[l]*step,dz3d[l]*step);
2561 vol += f*w3d[l];
2562 }
2563 ecart = 1;
2564
2565 /* increment en couronnes cubiques de 2*ecart+1 de cote */
2566 do {
2567 volprec = vol;
2568 for (i= -ecart;i<=ecart;i++) for(l=0;l<nd3d;l++) {
2569 for(j= -ecart;j<=ecart;j++) {
2570 f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,(-ecart+dz3d[l])*step);
2571 vol += f*w3d[l];
2572 f=fonction((i+dx3d[l])*step,(j+dy3d[l])*step,( ecart+dz3d[l])*step);
2573 vol += f*w3d[l];
2574 }
2575
2576 for(k= -ecart+1;k<=ecart-1;k++) {
2577 f=fonction((i+dx3d[l])*step,(-ecart+dy3d[l])*step,(k+dz3d[l])*step);
2578 vol += f*w3d[l];
2579 f=fonction((i+dx3d[l])*step,( ecart+dy3d[l])*step,(k+dz3d[l])*step);
2580 vol += f*w3d[l];
2581 }
2582 }
2583 for (j= -ecart+1;j<=ecart-1;j++) for(k= -ecart+1;k<=ecart-1;k++)
2584 for(l=0;l<nd3d;l++) {
2585 f=fonction((-ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
2586 vol += f*w3d[l];
2587 f=fonction(( ecart+dx3d[l])*step,(j+dy3d[l])*step,(k+dz3d[l])*step);
2588 vol += f*w3d[l];
2589 }
2590
2591 ecart = ecart + 1;
2592 encore = ((fabs((vol-volprec)/vol) > precision) || (ecart <= 2) );
2593 if(deb>1) printf("ec=%d v=%g deltav/v=%g\n"
2594 ,ecart-1,vol*step*step*step,((vol-volprec)/vol));
2595 } while(encore);
2596
2597 vol *= step * step* step;
2598 if(deb>0) printf("\nVol = %g\n",vol);
2599 return(vol);
2600}
2601
2602
2603/*=================================================================*/
2604/* cmv 6/11/97 */
2605/*
2606++
2607int IntFaisDr -
2608 (int n,float *cs,float *sn,float *p,float *x0,float *y0 -
2609 ,int npass,float perclean,int lp)
2610
2611 Pour calculer le point d'intersection moyen
2612 d'un faisceau de droites.
2613--
2614*/
2615/*
2616++
2617| L'equation des droites est sous la forme:
2618| cos(alpha)*x + sin(alpha)*y = p
2619| [cos(alpha),sin(alpha)] coordonnees du vecteur unitaire joignant
2620| l'origine au point de moindre approche de la droite a l'origine.
2621| p est la distance de la droite a l'origine.
2622--
2623*/
2624/*
2625++
2626| -- Input:
2627| n : nombre de droites
2628| cs : tableau des coefficients cos(alpha)
2629| sn : tableau des coefficients sin(alpha)
2630| p : tableau des coefficients p
2631| npass : nombre de passes de nettoyage
2632| perclean : pourcentage d'etoiles a tuer
2633| d'une passe a la suivante
2634| ex: perclean=0.2, si il y a 200 etoiles dans une passe
2635| la passe suivante en utilisera 160 et la suivante 128.
2636| lp : niveau d'impression
2637--
2638*/
2639/*
2640++
2641| -- Output:
2642| x0 : valeur de l'abscisse du point d'intersection moyen trouve
2643| y0 : ordonnee
2644| -- Return:
2645| nombre de droites utilisees pour le calcul de x0,y0
2646--
2647*/
2648int IntFaisDr(int n,float *cs,float *sn,float *p,float *x0,float *y0
2649 ,int npass,float perclean,int lp)
2650{
2651int i,j,ns, nsuse=-9, ipass;
2652double sumC2,sumS2,sumCS,sumCP,sumSP,den;
2653float *d2=NULL, d2cut=-1.;
2654unsigned short *good=NULL;
2655
2656*x0 = *y0 = 0.;
2657if(n<=1) return(-1);
2658if(lp<0) lp=0;\
2659if(npass<=0) npass=1;
2660if(perclean<=0.) { perclean=0.; npass=1;}
2661if(lp)
2662 printf("IntFaisDr avec %d points en %d passes avec nettoyage de %g%%\n"
2663 ,n,npass,perclean*100);
2664
2665d2 = (float *) malloc(n * sizeof(float));
2666if(d2==NULL) {
2667 if(lp)
2668 printf("allocation de %d float impossible\n",n);
2669 return(-2);
2670}
2671good = (unsigned short *) malloc(n * sizeof(unsigned short));
2672if(good==NULL) {
2673 if(lp)
2674 printf("allocation de %d unsigned short impossible\n",n);
2675 free(d2);
2676 return(-3);
2677}
2678for(i=0;i<n;i++) good[i]=1;
2679
2680for(ipass=1;ipass<=npass;ipass++) {
2681
2682 /* Calcul du point d'intersection pour la passe ipass */
2683 sumC2=sumS2=sumCS=sumCP=sumSP=0.;
2684 ns=0;
2685 for(i=0;i<n;i++) {
2686 if( !good[i] ) continue;
2687 sumC2 += cs[i]*cs[i];
2688 sumS2 += sn[i]*sn[i];
2689 sumCS += cs[i]*sn[i];
2690 sumCP += cs[i]*p[i];
2691 sumSP += sn[i]*p[i];
2692 ns++;
2693 }
2694 den = sumCS*sumCS - sumC2*sumS2;
2695 if(den==0.) {
2696 if(lp)
2697 printf("denominateur nul pass=%d, sumCS=%g sumC2=%g sumS2=%g pour %d dr\n"
2698 ,ipass,sumCS,sumC2,sumS2,ns);
2699 free(d2); free(good);
2700 return(-100-ipass);
2701 }
2702 if(ns<2) {
2703 if(lp) printf("Pas ou plus assez de droites %d\n",ns);
2704 return(nsuse);
2705 }
2706 *x0 = (sumSP*sumCS - sumCP*sumS2)/den;
2707 *y0 = (sumCP*sumCS - sumSP*sumC2)/den;
2708 nsuse = ns;
2709 if(lp) printf("Pass=%d, %d dr x0=%g y0=%g\n",ipass,nsuse,*x0,*y0);
2710 if(ipass==npass) break;
2711
2712 /* Calcul de la coupure en distance**2 pour la passe suivante */
2713 ns = 0;
2714 for(i=0;i<n;i++) {
2715 if( !good[i] ) continue;
2716 d2[ns] = (*x0*cs[i] * *y0*sn[i]-p[i]);
2717 d2[ns] *= d2[ns];
2718 ns++;
2719 }
2720 qsort(d2,(size_t) ns,sizeof(float),qSort_Float);
2721 j = (int) (ns-ns*perclean); if(j<0) j=0; if(j>=ns) j=ns-1;
2722 d2cut = d2[j];
2723 ns=0;
2724 for(i=0;i<n;i++) {
2725 if( !good[i] ) continue;
2726 den = (*x0*cs[i] * *y0*sn[i]-p[i]);
2727 den *= den;
2728 if( den>d2cut ) good[i]=0; else ns++;
2729 }
2730 if(lp>1)
2731 printf(" next pass: i=%d cut=%g -> restera %d dr\n",j,d2cut,ns);
2732}
2733
2734free(d2); free(good);
2735return(nsuse);
2736}
2737
2738/*=========================================== cmv 22/11/04 ===*/
2739/*
2740++
2741double log_factoriel(unsigned int n)
2742
2743 Compute the neperian log of n!
2744--
2745*/
2746double log_factoriel(unsigned int n)
2747{
2748 unsigned int i;
2749 double sum=0.;
2750 if(n<2) return sum;
2751 for(i=n;i>1;i--) sum += log((double)i);
2752 return sum;
2753}
2754
2755/*
2756++
2757double log_stirling(unsigned int n)
2758
2759 Compute the neperian log of the Stirling approx of n!
2760--
2761*/
2762double log_stirling(unsigned int n)
2763/*
2764Approx: n! ~ sqrt(2Pi n) n^n exp(-n) = sqrt(2Pi) n^(n+1/2) exp(-n)
2765 log(n!) ~ (n+1/2) log(n) -n + 1/2 log(2Pi)
2766(ordre 0: log(n!) ~ n (log(n)-1)
2767*/
2768{
2769 if(n<1) return 0.;
2770 return (n+0.5)*log(n) - n + Hln2pi;
2771}
2772
2773/*
2774++
2775double log_gosper(unsigned int n);
2776
2777 Compute the neperian log of the Gosper approx of n!
2778--
2779*/
2780double log_gosper(unsigned int n)
2781/*
2782Approx: n! ~ sqrt( (2n+1/3) Pi ) n^n exp(-n)
2783 log(n!) ~ 1/2 log( (2n+1/3) Pi ) + n log(n) -n
2784*/
2785{
2786 if(n<1) return 0.;
2787 return 0.5*log((2.*n+1./3.)*M_PI) + n*log(n) -n;
2788}
2789
2790/*
2791++
2792double give_log_factoriel(unsigned int n);
2793
2794 Compute the neperian log of the approx of n!
2795--
2796*/
2797static short give_log_factoriel_OK = 0;
2798#define give_log_factoriel_LIM 21
2799static double give_log_factoriel_TAB[give_log_factoriel_LIM];
2800double give_log_factoriel(unsigned int n)
2801{
2802 int i;
2803 if(give_log_factoriel_OK==0) {
2804 give_log_factoriel_OK=1;
2805 for(i=0;i<give_log_factoriel_LIM;i++)
2806 give_log_factoriel_TAB[i]=log_factoriel(i);
2807 }
2808
2809 if(n<give_log_factoriel_LIM) return give_log_factoriel_TAB[n];
2810 return log_gosper(n);
2811}
2812#undef give_log_factoriel_LIM
Note: See TracBrowser for help on using the repository browser.