1 | #include "machdefs.h"
|
---|
2 | #include <iostream>
|
---|
3 | #include <stdlib.h>
|
---|
4 | #include <stdio.h>
|
---|
5 | #include <string.h>
|
---|
6 | #include <math.h>
|
---|
7 | #include <vector>
|
---|
8 |
|
---|
9 | #include "pexceptions.h"
|
---|
10 |
|
---|
11 | #include "histos.h"
|
---|
12 | #include "hisprof.h"
|
---|
13 | #include "srandgen.h"
|
---|
14 |
|
---|
15 | #include "geneutils.h"
|
---|
16 |
|
---|
17 | namespace SOPHYA {
|
---|
18 |
|
---|
19 | //-------------------------------------------------------------------
|
---|
20 | // Classe d'interpolation lineaire:
|
---|
21 | // Le vecteur y a n elements y_i tels que y_i = f(x_i)
|
---|
22 | // ou les x_i sont regulierement espaces
|
---|
23 | // et x_0=xmin et x_{n-1}=xmax (xmax inclus!)
|
---|
24 | InterpFunc::InterpFunc(double xmin,double xmax,vector<double>& y)
|
---|
25 | : _xmin(xmin), _xmax(xmax), _y(y)
|
---|
26 | {
|
---|
27 | if(_xmin>=_xmax || _y.size()<=2) { // au moins 3 points!
|
---|
28 | cout<<"InterpFunc::InterpFunc : bad arguments values"<<endl;
|
---|
29 | throw ParmError("InterpFunc::InterpFunc : bad arguments values");
|
---|
30 | }
|
---|
31 | _nm1 = _y.size()-1;
|
---|
32 | _dx = (_xmax-_xmin)/(double)_nm1;
|
---|
33 | }
|
---|
34 |
|
---|
35 | double InterpFunc::Linear(double x,unsigned short& ok)
|
---|
36 | {
|
---|
37 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
|
---|
38 | x -= _xmin;
|
---|
39 | long i = long(x/_dx); // On prend le "i" juste en dessous
|
---|
40 | if(i<0) i=0; else if(i>=_nm1) i=_nm1-1;
|
---|
41 | return _y[i] + (_y[i+1]-_y[i])/_dx*(x-i*_dx);
|
---|
42 | }
|
---|
43 |
|
---|
44 | double InterpFunc::Parab(double x,unsigned short& ok)
|
---|
45 | {
|
---|
46 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
|
---|
47 | x -= _xmin;
|
---|
48 | long i = long(x/_dx+0.5); // On prend le "i" le + proche
|
---|
49 | if(i<1) i=1; else if(i>=_nm1-1) i=_nm1-2;
|
---|
50 | double a = (_y[i+1]-2.*_y[i]+_y[i-1])/(2.*_dx*_dx);
|
---|
51 | double b = (_y[i+1]-_y[i-1])/(2.*_dx);
|
---|
52 | return _y[i] + (x-i*_dx)*(a*(x-i*_dx)+b);
|
---|
53 | }
|
---|
54 |
|
---|
55 | //-------------------------------------------------------------------
|
---|
56 | // Classe d'inversion d'une fonction STRICTEMENT MONOTONE CROISSANTE
|
---|
57 | //
|
---|
58 | // - On part de deux vecteurs x,y de "Nin" elements tels que "y_i = f[x_i]"
|
---|
59 | // ou la fonction "f" est strictement monotone croissante:
|
---|
60 | // x(i) < x(i+1) et y(i) < y(i+1)
|
---|
61 | // - Le but de la classe est de remplir un vecteur X de "Nout" elements
|
---|
62 | // tels que: X_j = f^-1[Y_j] avec j=[0,Nout[
|
---|
63 | // avec les Y_j regulierement espaces entre ymin=y(0) , ymax=y(Nin -1)
|
---|
64 | // cad: X_j = f^-1[ ymin+j*(ymax-ymin)/(Nout-1) ]
|
---|
65 | // - La construction du vecteur X est realisee
|
---|
66 | // par interpolation lineaire (ComputeLinear) ou parabolique (ComputeParab)
|
---|
67 | InverseFunc::InverseFunc(vector<double>& x,vector<double>& y)
|
---|
68 | : _ymin(0.) , _ymax(0.) , _x(x) , _y(y)
|
---|
69 | {
|
---|
70 | uint_4 ns = _x.size();
|
---|
71 | if(ns<3 || _y.size()<=0 || ns!=_y.size())
|
---|
72 | throw ParmError("InverseFunc::InverseFunc_Error: bad array size");
|
---|
73 |
|
---|
74 | // Check "x" strictement monotone croissant
|
---|
75 | for(uint_4 i=0;i<ns-1;i++)
|
---|
76 | if(_x[i+1]<=_x[i]) {
|
---|
77 | cout<<"InverseFunc::InverseFunc_Error: _x array not stricly growing"<<endl;
|
---|
78 | throw ParmError("InverseFunc::InverseFunc_Error: _x array not stricly growing");
|
---|
79 | }
|
---|
80 |
|
---|
81 | // Check "y" monotone croissant
|
---|
82 | for(uint_4 i=0;i<ns-1;i++)
|
---|
83 | if(_y[i+1]<_y[i]) {
|
---|
84 | cout<<"InverseFunc::InverseFunc_Error: _y array not growing"<<endl;
|
---|
85 | throw ParmError("InverseFunc::InverseFunc_Error: _y array not growing");
|
---|
86 | }
|
---|
87 |
|
---|
88 | // define limits
|
---|
89 | _ymin = _y[0];
|
---|
90 | _ymax = _y[ns-1];
|
---|
91 |
|
---|
92 | }
|
---|
93 |
|
---|
94 | InverseFunc::~InverseFunc(void)
|
---|
95 | {
|
---|
96 | }
|
---|
97 |
|
---|
98 | int InverseFunc::ComputeLinear(long nout,vector<double>& xfcty)
|
---|
99 | // Compute table "xfcty" by linear interpolation of "x" versus "y"
|
---|
100 | // on "nout" points from "ymin" to "ymax":
|
---|
101 | // xfcty[i] = interpolation of function "x" for "ymin+i*(ymax-ymin)/(nout-1)"
|
---|
102 | {
|
---|
103 | if(nout<3) return -1;
|
---|
104 |
|
---|
105 | xfcty.resize(nout);
|
---|
106 |
|
---|
107 | long i1,i2;
|
---|
108 | double x;
|
---|
109 | for(int_4 i=0;i<nout;i++) {
|
---|
110 | double y = _ymin + i*(_ymax-_ymin)/(nout-1.);
|
---|
111 | find_in_y(y,i1,i2);
|
---|
112 | double dy = _y[i2]-_y[i1];
|
---|
113 | if(dy==0.) {
|
---|
114 | x = (_x[i2]+_x[i1])/2.; // la fct a inverser est plate!
|
---|
115 | } else {
|
---|
116 | x = _x[i1] + (_x[i2]-_x[i1])/dy * (y-_y[i1]);
|
---|
117 | }
|
---|
118 | xfcty[i] = x;
|
---|
119 | }
|
---|
120 |
|
---|
121 | return 0;
|
---|
122 | }
|
---|
123 |
|
---|
124 | int InverseFunc::ComputeParab(long nout,vector<double>& xfcty)
|
---|
125 | {
|
---|
126 | if(nout<3) return -1;
|
---|
127 |
|
---|
128 | xfcty.resize(nout);
|
---|
129 |
|
---|
130 | long i1,i2,i3;
|
---|
131 | double x;
|
---|
132 | for(int_4 i=0;i<nout;i++) {
|
---|
133 | double y = _ymin + i*(_ymax-_ymin)/(nout-1.);
|
---|
134 | find_in_y(y,i1,i2);
|
---|
135 | // On cherche le 3ieme point selon la position de y / au 2 premiers
|
---|
136 | double my = (_y[i1]+_y[i2])/2.;
|
---|
137 | if(y<my) {i3=i2; i2=i1; i1--;} else {i3=i2+1;}
|
---|
138 | // Protection
|
---|
139 | if(i1<0) {i1++; i2++; i3++;}
|
---|
140 | if(i3==(long)_y.size()) {i1--; i2--; i3--;}
|
---|
141 | // Interpolation parabolique
|
---|
142 | double dy = _y[i3]-_y[i1];
|
---|
143 | if(dy==0.) {
|
---|
144 | x = (_x[i3]+_x[i1])/2.; // la fct a inverser est plate!
|
---|
145 | } else {
|
---|
146 | double X1=_x[i1]-_x[i2], X3=_x[i3]-_x[i2];
|
---|
147 | double Y1=_y[i1]-_y[i2], Y3=_y[i3]-_y[i2];
|
---|
148 | double den = Y1*Y3*dy;
|
---|
149 | double a = (X3*Y1-X1*Y3)/den;
|
---|
150 | double b = (X1*Y3*Y3-X3*Y1*Y1)/den;
|
---|
151 | y -= _y[i2];
|
---|
152 | x = (a*y+b)*y + _x[i2];
|
---|
153 | }
|
---|
154 | xfcty[i] = x;
|
---|
155 | }
|
---|
156 |
|
---|
157 | return 0;
|
---|
158 | }
|
---|
159 |
|
---|
160 | //----------------------------------------------------
|
---|
161 | double InterpTab(double x0,vector<double>& X,vector<double>& Y,unsigned short typint)
|
---|
162 | // Interpole in x0 the table Y = f(X)
|
---|
163 | // X doit etre ordonne par ordre croissant (strictement)
|
---|
164 | // typint = 0 : nearest value
|
---|
165 | // 1 : linear interpolation
|
---|
166 | // 2 : parabolique interpolation
|
---|
167 | {
|
---|
168 | long n = X.size();
|
---|
169 | if(n>(long)Y.size() || n<2)
|
---|
170 | throw ParmError("InterpTab_Error : incompatible size between X and Y tables!");
|
---|
171 |
|
---|
172 | if(x0<X[0] || x0>X[n-1]) return 0.;
|
---|
173 | if(typint>2) typint = 0;
|
---|
174 |
|
---|
175 | // Recherche des indices encadrants par dichotomie
|
---|
176 | long k, klo=0, khi=n-1;
|
---|
177 | while (khi-klo > 1) {
|
---|
178 | k = (khi+klo) >> 1;
|
---|
179 | if (X[k] > x0) khi=k; else klo=k;
|
---|
180 | }
|
---|
181 |
|
---|
182 | // Quel est le plus proche?
|
---|
183 | k = (x0-X[klo]<X[khi]-x0) ? klo: khi;
|
---|
184 |
|
---|
185 | // On retourne le plus proche
|
---|
186 | if(typint==0) return Y[k];
|
---|
187 |
|
---|
188 | // On retourne l'extrapolation lineaire
|
---|
189 | if(typint==1 || n<3)
|
---|
190 | return Y[klo] + (Y[khi]-Y[klo])/(X[khi]-X[klo])*(x0-X[klo]);
|
---|
191 |
|
---|
192 | // On retourne l'extrapolation parabolique
|
---|
193 | if(k==0) k++; else if(k==n-1) k--;
|
---|
194 | klo = k-1; khi = k+1;
|
---|
195 | double x1 = X[klo]-X[k], x2 = X[khi]-X[k];
|
---|
196 | double y1 = Y[klo]-Y[k], y2 = Y[khi]-Y[k];
|
---|
197 | double den = x1*x2*(x1-x2);
|
---|
198 | double a = (y1*x2-y2*x1)/den;
|
---|
199 | double b = (y2*x1*x1-y1*x2*x2)/den;
|
---|
200 | x0 -= X[k];
|
---|
201 | return Y[k] + (a*x0+b)*x0;;
|
---|
202 |
|
---|
203 | }
|
---|
204 |
|
---|
205 | //-------------------------------------------------------------------
|
---|
206 | int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex)
|
---|
207 | // Remplit l'histo 1D "h" avec la fonction "func"
|
---|
208 | // INPUT:
|
---|
209 | // logaxex = false : remplissage lineaire
|
---|
210 | // les abscisses "x" des bins sont remplis avec f(x)
|
---|
211 | // logaxex = true : remplissage logarithmique (base 10)
|
---|
212 | // les abscisses "x" des bins sont remplis avec f(10^x)
|
---|
213 | // RETURN:
|
---|
214 | // 0 = OK
|
---|
215 | // 1 = error
|
---|
216 | {
|
---|
217 | if(h.NBins()<=0) return 1;
|
---|
218 |
|
---|
219 | h.Zero();
|
---|
220 |
|
---|
221 | for(int_4 i=0;i<h.NBins();i++) {
|
---|
222 | double x = h.BinCenter(i);
|
---|
223 | if(logaxex) x = pow(10.,x);
|
---|
224 | h.SetBin(i,func(x));
|
---|
225 | }
|
---|
226 |
|
---|
227 | return 0;
|
---|
228 | }
|
---|
229 |
|
---|
230 | int FuncToVec(GenericFunc& func,TVector<r_8>& v,double xmin,double xmax,bool logaxex)
|
---|
231 | // Remplit le TVector avec la fonction "func"
|
---|
232 | // INPUT:
|
---|
233 | // logaxex = false : remplissage lineaire
|
---|
234 | // les abscisses "x" des bins sont remplis avec f(x)
|
---|
235 | // logaxex = true : remplissage logarithmique (base 10)
|
---|
236 | // les abscisses "x" des bins sont remplis avec f(10^x)
|
---|
237 | // RETURN:
|
---|
238 | // 0 = OK
|
---|
239 | // 1 = error
|
---|
240 | // Remarque:
|
---|
241 | // v(i) = f(xmin+i*dx) avec dx = (xmax-xmin)/v.NElts()
|
---|
242 | {
|
---|
243 | if(v.NElts()<=0 || xmax<=xmin) return 1;
|
---|
244 |
|
---|
245 | v = 0.;
|
---|
246 | double dx = (xmax-xmin)/v.NElts();
|
---|
247 |
|
---|
248 | for(int_4 i=0;i<v.NElts();i++) {
|
---|
249 | double x = xmin + i * dx;;
|
---|
250 | if(logaxex) x = pow(10.,x);
|
---|
251 | v(i) = func(x);
|
---|
252 | }
|
---|
253 |
|
---|
254 | return 0;
|
---|
255 | }
|
---|
256 |
|
---|
257 | //-------------------------------------------------------------------
|
---|
258 | double AngSol(double dtheta,double dphi,double theta0)
|
---|
259 | // Retourne l'angle solide d'un "rectangle" et coordonnees spheriques
|
---|
260 | // de DEMI-COTE "dtheta" x "dphi" et centre en "theta0"
|
---|
261 | // Attention: Le "theta0" de l'equateur est Pi/2 (et non pas zero)
|
---|
262 | // Les unites des angles sont en radians
|
---|
263 | // theta0 in [0,Pi]
|
---|
264 | // dtheta in [0,Pi]
|
---|
265 | // dphi in [0,2Pi]
|
---|
266 | // Return: l'angle solide en steradian
|
---|
267 | {
|
---|
268 | double theta1 = theta0-dtheta, theta2 = theta0+dtheta;
|
---|
269 | if(theta1<0.) theta1=0.;
|
---|
270 | if(theta2>M_PI) theta2=M_PI;
|
---|
271 |
|
---|
272 | return 2.*dphi * (cos(theta1)-cos(theta2));
|
---|
273 | }
|
---|
274 |
|
---|
275 | double AngSol(double dtheta)
|
---|
276 | // Retourne l'angle solide d'une calotte spherique de demi-ouverture "dtheta"
|
---|
277 | // Attention: Les unites des angles sont en radians
|
---|
278 | // dtheta in [0,Pi]
|
---|
279 | // Return: l'angle solide en steradian
|
---|
280 | // Approx pour theta petit: PI * theta^2
|
---|
281 | {
|
---|
282 | return 2.*M_PI * (1.-cos(dtheta));
|
---|
283 | }
|
---|
284 |
|
---|
285 | double FrAngSol(double angsol)
|
---|
286 | // Retourne la demi-ouverture "dtheta" d'une calotte spherique d'angle solide "angsol"
|
---|
287 | // Input: angle solide de la calotte spherique en steradians
|
---|
288 | // Return: demi-ouverture de la calotte spherique en radians
|
---|
289 | {
|
---|
290 | angsol = 1. - angsol/(2.*M_PI);
|
---|
291 | if(angsol<-1. || angsol>1.) return -1.;
|
---|
292 | return acos(angsol);
|
---|
293 | }
|
---|
294 |
|
---|
295 | //-------------------------------------------------------------------
|
---|
296 | double SinXsX(double x,bool app)
|
---|
297 | // Calcul de sin(x)/x
|
---|
298 | // Le Dl est en O[x]^10 (cad on va jusqu'au terme en x^8 compris)
|
---|
299 | // Approx: terme en x^6/(6*20*42) ~ 1e-13 -> x^2 ~ 1.7e-4
|
---|
300 | {
|
---|
301 | double x2 = x*x;
|
---|
302 | if(app || x2<1.7e-4) return 1.-x2/6.*(1.-x2/20.*(1.-x2/42.*(1.-x2/72.)));
|
---|
303 | return sin(x)/x;
|
---|
304 | }
|
---|
305 |
|
---|
306 | double SinXsX_Sqr(double x,bool app)
|
---|
307 | // Calcul de (sin(x)/x)^2
|
---|
308 | // Le Dl est en O[x]^10 (cad on va jusqu'au terme en x^8 compris)
|
---|
309 | // Approx: terme 2*x^6/(3*15*14) ~ 1e-13 -> x^2 ~ 6.8e-5
|
---|
310 | {
|
---|
311 | double x2 = x*x;
|
---|
312 | if(app || x2<6.8e-5) return 1.-x2/3.*(1.-2.*x2/15.*(1.-x2/14.*(1.-2.*x2/45.)));
|
---|
313 | x2 = sin(x)/x;
|
---|
314 | return x2*x2;
|
---|
315 | }
|
---|
316 |
|
---|
317 | double SinNXsX(double x,unsigned long N,bool app)
|
---|
318 | // Calcul de sin(N*x)/sin(x) avec N entier positif
|
---|
319 | // ATTENTION: N est entier
|
---|
320 | // 1. pour que sin(N*x) et sin(x) soient nuls en meme temps
|
---|
321 | // (on peut faire le DL popur sin(N*x) et sin(x))
|
---|
322 | // 2. pour traiter correctement le DL en x = p*Pi+e avec e<<1 et p entier
|
---|
323 | // sin(N*x)/sin(x) = sin(N*p*Pi+N*e)/sin(p*Pi+e)
|
---|
324 | // = [sin(N*p*Pi)*cos(N*e)+cos(N*p*Pi)*sin(N*e)]
|
---|
325 | // / [sin(p*Pi)*cos(e)+cos(p*Pi)*sin(e)]
|
---|
326 | // comme sin(N*p*Pi)=0
|
---|
327 | // = [cos(N*p*Pi)*sin(N*e)] / [cos(p*Pi)*sin(e)]
|
---|
328 | // = [sin(N*e)/sin(e)] * [cos(N*p*Pi)/cos(p*Pi)]
|
---|
329 | // = [DL autour de x=0] * (+1 ou -1)
|
---|
330 | // Le seul cas ou on a "-1" est quand "p=impair" (cos(p*Pi)=-1) et "N=pair"
|
---|
331 | // Approx: dernier terme x^4*N^4/120 ~ 1e-13 -> x^2 ~ 3.5e-6/N^2
|
---|
332 | {
|
---|
333 | if(N==0) return 0;
|
---|
334 | double sx = sin(x), N2 = N*N;
|
---|
335 | if(app || sx*sx<3.5e-6/N2) {
|
---|
336 | double x2 = asin(sx); x2 *= x2;
|
---|
337 | double s = 1.;
|
---|
338 | if(N%2==0 && cos(x)<0.) s = -1.; // cas x ~ (2p+1)*Pi et N pair
|
---|
339 | return s*N*(1.-(N-1.)*(N+1.)/6.*x2*(1.-(3.*N2-7.)/60.*x2));
|
---|
340 | }
|
---|
341 | return sin((double)N*x)/sx;
|
---|
342 | }
|
---|
343 |
|
---|
344 | double SinNXsX_Sqr(double x,unsigned long N,bool app)
|
---|
345 | // Calcul de [sin(N*x)/sin(x)]^2 avec N entier positif
|
---|
346 | // ATTENTION: cf remarque pour N entier dans SinNXsX
|
---|
347 | // maximum de la fonction: N^2
|
---|
348 | // Approx: dernier terme x^4*2*N^4/45 ~ 1e-13 -> x^2 ~ 1.5e-6/N^2
|
---|
349 | {
|
---|
350 | if(N==0) return 0;
|
---|
351 | double sx = sin(x), N2 = N*N;
|
---|
352 | if(app || sx*sx<1.5e-6/N2) {
|
---|
353 | double x2 = asin(sx); x2 *= x2;
|
---|
354 | //return N2*(1.-(N*N-1.)/3.*x2);
|
---|
355 | return N2*(1.-(N-1.)*(N+1.)/3.*x2*(1.-(2.*N2-3.)/15.*x2));
|
---|
356 | }
|
---|
357 | sx = sin((double)N*x)/sx;
|
---|
358 | return sx*sx;
|
---|
359 | }
|
---|
360 |
|
---|
361 | //-------------------------------------------------------------------
|
---|
362 |
|
---|
363 | static unsigned short IntegrateFunc_GlOrder = 0;
|
---|
364 | static vector<double> IntegrateFunc_x;
|
---|
365 | static vector<double> IntegrateFunc_w;
|
---|
366 |
|
---|
367 | ///////////////////////////////////////////////////////////
|
---|
368 | //************** Integration of Functions ***************//
|
---|
369 | ///////////////////////////////////////////////////////////
|
---|
370 |
|
---|
371 |
|
---|
372 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
373 | double IntegrateFunc(GenericFunc& func,double xmin,double xmax
|
---|
374 | ,double perc,double dxinc,double dxmax,unsigned short glorder)
|
---|
375 | // --- Integration adaptative ---
|
---|
376 | // Integrate[func[x], {x,xmin,xmax}]
|
---|
377 | // ..xmin,xmax are the integration limits
|
---|
378 | // ..dxinc is the searching increment x = xmin+i*dxinc
|
---|
379 | // if <0 npt = int(|dxinc|) (si<2 alors npt=100)
|
---|
380 | // et dxinc = (xmax-xmin)/npt
|
---|
381 | // ..dxmax is the maximum possible increment (if dxmax<=0 no test)
|
---|
382 | // ---
|
---|
383 | // Partition de [xmin,xmax] en intervalles [x(i),x(i+1)]:
|
---|
384 | // on parcourt [xmin,xmax] par pas de "dxinc" : x(i) = xmin + i*dxinc
|
---|
385 | // on cree un intervalle [x(i),x(i+1)]
|
---|
386 | // - si |f[x(i+1)] - f[x(i)]| > perc*|f[[x(i)]|
|
---|
387 | // - si |x(i+1)-x(i)| >= dxmax (si dxmax>0.)
|
---|
388 | // Dans un intervalle [x(i),x(i+1)] la fonction est integree
|
---|
389 | // avec une methode de gauss-legendre d'ordre "glorder"
|
---|
390 | {
|
---|
391 | double signe = 1.;
|
---|
392 | if(xmin>xmax) {double tmp=xmax; xmax=xmin; xmin=tmp; signe=-1.;}
|
---|
393 |
|
---|
394 | if(glorder==0) glorder = 4;
|
---|
395 | if(perc<=0.) perc=0.1;
|
---|
396 | if(dxinc<=0.) {int n=int(-dxinc); if(n<2) n=100; dxinc=(xmax-xmin)/n;}
|
---|
397 | if(glorder != IntegrateFunc_GlOrder) {
|
---|
398 | IntegrateFunc_GlOrder = glorder;
|
---|
399 | Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
|
---|
400 | }
|
---|
401 |
|
---|
402 | // Recherche des intervalles [x(i),x(i+1)]
|
---|
403 | int_4 ninter = 0;
|
---|
404 | double sum = 0., xbas=xmin, fbas=func(xbas), fabsfbas=fabs(fbas);
|
---|
405 | for(double x=xmin+dxinc; x<xmax+dxinc/2.; x += dxinc) {
|
---|
406 | double f = func(x);
|
---|
407 | double dx = x-xbas;
|
---|
408 | bool doit = false;
|
---|
409 | if( x>xmax ) {doit = true; x=xmax;}
|
---|
410 | else if( dxmax>0. && dx>dxmax ) doit = true;
|
---|
411 | else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
|
---|
412 | if( ! doit ) continue;
|
---|
413 | double s = 0.;
|
---|
414 | for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++)
|
---|
415 | s += IntegrateFunc_w[i]*func(xbas+IntegrateFunc_x[i]*dx);
|
---|
416 | sum += s*dx;
|
---|
417 | xbas = x; fbas = f; fabsfbas=fabs(fbas); ninter++;
|
---|
418 | }
|
---|
419 | //cout<<"Ninter="<<ninter<<endl;
|
---|
420 |
|
---|
421 | return sum*signe;
|
---|
422 | }
|
---|
423 |
|
---|
424 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
425 | double IntegrateFuncLog(GenericFunc& func,double lxmin,double lxmax
|
---|
426 | ,double perc,double dlxinc,double dlxmax,unsigned short glorder)
|
---|
427 | // --- Integration adaptative ---
|
---|
428 | // Idem IntegrateFunc but integrate on logarithmic (base 10) intervals:
|
---|
429 | // Int[ f(x) dx ] = Int[ x*f(x) dlog10(x) ] * log(10)
|
---|
430 | // ..lxmin,lxmax are the log10() of the integration limits
|
---|
431 | // ..dlxinc is the searching logarithmic (base 10) increment lx = lxmin+i*dlxinc
|
---|
432 | // ..dlxmax is the maximum possible logarithmic (base 10) increment (if dlxmax<=0 no test)
|
---|
433 | // Remarque: to be use if "x*f(x) versus log10(x)" looks like a polynomial
|
---|
434 | // better than "f(x) versus x"
|
---|
435 | // ATTENTION: la fonction func que l'on passe en argument
|
---|
436 | // est "func(x)" et non pas "func(log10(x))"
|
---|
437 | {
|
---|
438 | double signe = 1.;
|
---|
439 | if(lxmin>lxmax) {double tmp=lxmax; lxmax=lxmin; lxmin=tmp; signe=-1.;}
|
---|
440 |
|
---|
441 | if(glorder==0) glorder = 4;
|
---|
442 | if(perc<=0.) perc=0.1;
|
---|
443 | if(dlxinc<=0.) {int n=int(-dlxinc); if(n<2) n=100; dlxinc=(lxmax-lxmin)/n;}
|
---|
444 | if(glorder != IntegrateFunc_GlOrder) {
|
---|
445 | IntegrateFunc_GlOrder = glorder;
|
---|
446 | Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
|
---|
447 | }
|
---|
448 |
|
---|
449 | // Recherche des intervalles [lx(i),lx(i+1)]
|
---|
450 | int_4 ninter = 0;
|
---|
451 | double sum = 0., lxbas=lxmin, fbas=func(pow(10.,lxbas)), fabsfbas=fabs(fbas);
|
---|
452 | for(double lx=lxmin+dlxinc; lx<lxmax+dlxinc/2.; lx += dlxinc) {
|
---|
453 | double f = func(pow(10.,lx));
|
---|
454 | double dlx = lx-lxbas;
|
---|
455 | bool doit = false;
|
---|
456 | if( lx>lxmax ) {doit = true; lx=lxmax;}
|
---|
457 | else if( dlxmax>0. && dlx>dlxmax ) doit = true;
|
---|
458 | else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
|
---|
459 | if( ! doit ) continue;
|
---|
460 | double s = 0.;
|
---|
461 | for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) {
|
---|
462 | double y = pow(10.,lxbas+IntegrateFunc_x[i]*dlx);
|
---|
463 | s += IntegrateFunc_w[i]*y*func(y);
|
---|
464 | }
|
---|
465 | sum += s*dlx;
|
---|
466 | lxbas = lx; fbas = f; fabsfbas=fabs(fbas); ninter++;
|
---|
467 | }
|
---|
468 | //cout<<"Ninter="<<ninter<<endl;
|
---|
469 |
|
---|
470 | return M_LN10*sum*signe;
|
---|
471 | }
|
---|
472 |
|
---|
473 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
474 | /*
|
---|
475 | Integration des fonctions a une dimension y=f(x) par la Methode de Gauss-Legendre.
|
---|
476 | --> Calcul des coefficients du developpement pour [x1,x2]
|
---|
477 | | INPUT:
|
---|
478 | | x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5)
|
---|
479 | | glorder = degre n du developpement de Gauss-Legendre
|
---|
480 | | OUTPUT:
|
---|
481 | | x[] = valeur des abscisses ou l'on calcule (dim=n)
|
---|
482 | | w[] = valeur des coefficients associes
|
---|
483 | | REMARQUES:
|
---|
484 | | - x et w seront dimensionnes a n.
|
---|
485 | | - l'integration est rigoureuse si sur l'intervalle d'integration
|
---|
486 | | la fonction f(x) peut etre approximee par un polynome
|
---|
487 | | de degre 2*m (monome le + haut x**(2*n-1) )
|
---|
488 | */
|
---|
489 | void Compute_GaussLeg(unsigned short glorder,vector<double>& x,vector<double>& w,double x1,double x2)
|
---|
490 | {
|
---|
491 | if(glorder==0) return;
|
---|
492 | int n = (int)glorder;
|
---|
493 | x.resize(n,0.); w.resize(n,0.);
|
---|
494 |
|
---|
495 | int m,j,i;
|
---|
496 | double z1,z,xm,xl,pp,p3,p2,p1;
|
---|
497 |
|
---|
498 | m=(n+1)/2;
|
---|
499 | xm=0.5*(x2+x1);
|
---|
500 | xl=0.5*(x2-x1);
|
---|
501 | for (i=1;i<=m;i++) {
|
---|
502 | z=cos(M_PI*(i-0.25)/(n+0.5));
|
---|
503 | do {
|
---|
504 | p1=1.0;
|
---|
505 | p2=0.0;
|
---|
506 | for (j=1;j<=n;j++) {
|
---|
507 | p3=p2;
|
---|
508 | p2=p1;
|
---|
509 | p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
|
---|
510 | }
|
---|
511 | pp=n*(z*p1-p2)/(z*z-1.0);
|
---|
512 | z1=z;
|
---|
513 | z=z1-p1/pp;
|
---|
514 | } while (fabs(z-z1) > 3.0e-11); // epsilon
|
---|
515 | x[i-1]=xm-xl*z;
|
---|
516 | x[n-i]=xm+xl*z;
|
---|
517 | w[i-1]=2.0*xl/((1.0-z*z)*pp*pp);
|
---|
518 | w[n-i]=w[i-1];
|
---|
519 | }
|
---|
520 | }
|
---|
521 |
|
---|
522 | } // Fin namespace SOPHYA
|
---|