source: Sophya/trunk/Poubelle/DPC:FitsIOServer/NTools/integ.cc

Last change on this file was 658, checked in by ansari, 26 years ago

no message

File size: 8.9 KB
Line 
1#include "integ.h"
2#include "generalfit.h"
3
4// A faire :
5// 1 dans GLInteg, optimiser recalcul en utilisant des poids
6// calcules sur [0,1] et chgt de variable
7// 2 dans GLInteg, distinction nStep = subdivisions de l'intervalle,
8// et on applique GL d'ordre "ordre" sur chaque subdivision, en
9// utilisant le (1)
10
11//++
12// Class Integrator
13// Lib Outils++
14// include integ.h
15//
16// Classe abstraite d'intégration numérique 1D.
17// On fournit une fonction double f(double) au constructeur, ou
18// une GeneralFunction avec des paramètres définis.
19// L'objet Integrator est convertible en valeur double qui est la valeur
20// de l'intégrale. Diverses méthodes permettent de choisir des options
21// de calcul, et ces méthodes retournent une référence sur l'objet, pour
22// permettre une notation chaînée.
23//--
24//++
25// Links Implementations
26// TrpzInteg
27// GLInteg
28//--
29
30//++
31// Titre Constructeurs
32//--
33
34//++
35Integrator::Integrator()
36//
37// Constructeur par défaut. L'objet n'est pas utilisable en l'état.
38//--
39
40: mFunc(NULL), mGFF(NULL), mGFFParm(NULL),
41 mNStep(50), mDX(-1), mReqPrec(-1),
42 mXMin(0), mXMax(1)
43{}
44
45//++
46Integrator::Integrator(FUNC f, double xmin, double xmax)
47//
48// Constructeur à partir de la fonction double->double, et des
49// bornes d'intégration.
50//--
51: mFunc(f), mGFF(NULL), mGFFParm(NULL),
52 mNStep(50), mDX(-1), mReqPrec(-1),
53 mXMin(xmin), mXMax(xmax)
54{}
55
56//++
57Integrator::Integrator(FUNC f)
58//
59// Constructeur sans spécifier les bornes. Elles sont positionnées
60// à [0,1], et on pourra les modifier plus tard.
61//--
62: mFunc(f), mGFF(NULL), mGFFParm(NULL),
63 mNStep(50), mDX(-1), mReqPrec(-1),
64 mXMin(0), mXMax(1)
65{}
66
67//++
68Integrator::Integrator(GeneralFunction* gff, double* par, double xmin, double xmax)
69//
70// Constructeur à partir d'une GeneralFunction. La fonction doit être une
71// fonction de une variable, et on fournit les valeurs des paramètres ainsi
72// que les bornes d'intégration.
73//--
74: mFunc(NULL), mGFF(gff), mGFFParm(par),
75 mNStep(50), mDX(-1), mReqPrec(-1),
76 mXMin(xmin), mXMax(xmax)
77{
78 DBASSERT(gff->NVar() == 1);
79}
80
81//++
82Integrator::Integrator(GeneralFunction* gff, double* par)
83//
84// Constructeur à partir d'une GeneralFunction. La fonction doit être une
85// fonction de une variable, et on fournit les valeurs des paramètres.
86// On ne spécifie pas les bornes. Elles sont positionnées
87// à [0,1], et on pourra les modifier plus tard.
88//--
89: mFunc(NULL), mGFF(gff), mGFFParm(par),
90 mNStep(50), mDX(-1), mReqPrec(-1),
91 mXMin(0), mXMax(1)
92{
93 DBASSERT(gff->NVar() == 1);
94}
95
96Integrator::~Integrator()
97{}
98
99//++
100// Titre Méthodes
101//--
102
103//++
104Integrator&
105Integrator::NStep(int n)
106//
107// Spécifie le nombre de pas pour l'intégration numérique.
108// La signification peut dépendre de la méthode d'intégration.
109//--
110{
111 mNStep = n;
112 mDX = mReqPrec = -1;
113 StepsChanged();
114 return *this;
115}
116
117//++
118Integrator&
119Integrator::DX(double d)
120//
121// Spécifie le pas d'intégration.
122// La signification peut dépendre de la méthode d'intégration.
123//--
124{
125 mDX = d;
126 mNStep = mReqPrec = -1;
127 StepsChanged();
128 return *this;
129}
130
131//++
132Integrator&
133Integrator::ReqPrec(double p)
134//
135// Spécifie la précision souhaitée.
136// La signification peut dépendre de la méthode d'intégration.
137// Non disponible dans toutes les méthodes d'intégration.
138//--
139{
140 DBASSERT( !"Pas encore implemente !");
141 mReqPrec = p;
142 mDX = mNStep = -1;
143 StepsChanged();
144 return *this;
145}
146
147//++
148Integrator&
149Integrator::Limits(double xmin, double xmax)
150//
151// Spécifie les bornes de l'intégrale.
152//--
153{
154 mXMin = xmin;
155 mXMax = xmax;
156 LimitsChanged();
157 return *this;
158}
159
160//++
161Integrator&
162Integrator::Func(FUNC f)
163//
164// Spécifie la fonction à intégrer, sous forme double f(double).
165//--
166{
167 mFunc = f;
168 mGFFParm = NULL;
169 mFunc = NULL;
170 FuncChanged();
171 return *this;
172}
173
174//++
175Integrator&
176Integrator::Func(GeneralFunction* gff, double* par)
177//
178// Spécifie la fonction à intégrer, sous forme de GeneralFunction
179// à une variable, et les paramètres sont fournis.
180//--
181{
182 mGFF = gff;
183 mGFFParm = par;
184 mFunc = NULL;
185 DBASSERT(gff->NVar() == 1);
186 FuncChanged();
187 return *this;
188}
189
190double
191Integrator::FVal(double x) const
192{
193 DBASSERT( mFunc || (mGFF && mGFFParm) );
194 return mFunc ? (*mFunc)(x) : mGFF->Value(&x, mGFFParm);
195}
196
197double
198Integrator::ValueBetween(double xmin, double xmax)
199{
200 Limits(xmin,xmax);
201 return Value();
202}
203
204//++
205// Class TrpzInteg
206// Lib Outils++
207// include integ.h
208//
209// Classe d'intégration par la méthode des trapèzes.
210// Voir Integrator pour les méthodes. Le nombre de pas
211// est le nombre de trapèze, le pas d'intégration est
212// la largeur des trapèzez. Impossible de demander une
213// précision.
214//
215//--
216//++
217// Links Parents
218// Integrator
219//--
220
221//++
222// Titre Constructeurs
223// Voir Integrator pour les détails.
224//--
225
226//++
227TrpzInteg::TrpzInteg()
228//
229//--
230{}
231
232//++
233TrpzInteg::TrpzInteg(FUNC f, double xmin, double xmax)
234//
235//--
236: Integrator(f, xmin, xmax)
237{}
238
239//++
240TrpzInteg::TrpzInteg(FUNC f)
241//
242//--
243: Integrator(f)
244{}
245
246//++
247TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
248//
249//--
250: Integrator(gff, par, xmin, xmax)
251{}
252
253//++
254TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par)
255//
256//--
257: Integrator(gff, par)
258{}
259
260TrpzInteg::~TrpzInteg()
261{}
262
263double
264TrpzInteg::Value()
265{
266 double dx = mDX;
267 double nstep = mNStep;
268
269 if (dx > 0)
270 nstep = (mXMax - mXMin)/dx;
271
272 if (nstep <= 0)
273 nstep = 10;
274
275 dx = (mXMax - mXMin) / nstep;
276
277 double s = (FVal(mXMin) + FVal(mXMax))/2;
278 double x = dx + mXMin;
279 for (int i=1; i<nstep; i++, x += dx)
280 s += FVal(x);
281
282 return s * dx;
283}
284
285
286
287//++
288// Class GLInteg
289// Lib Outils++
290// include integ.h
291//
292// Classe d'intégration par la méthode de Gauss-Legendre.
293// Voir Integrator pour les méthodes.
294// Pour le moment, nstep est l'ordre de la méthode.
295// Il est prévu un jour de spécifier l'ordre, et que NStep
296// découpe en intervalles sur chacun desquels on applique GL.
297// Le principe de la méthode est de calculer les valeurs de la
298// fonction aux zéros des polynomes de Legendre. Avec les poids
299// qui vont bien, GL d'ordre n est exacte pour des polynomes de
300// degré <= 2n+1.
301// Impossible de demander une précision donnée.
302//
303//--
304//++
305// Links Parents
306// Integrator
307//--
308
309//++
310// Titre Constructeurs
311// Voir Integrator pour les détails.
312//--
313
314
315
316
317//++
318GLInteg::GLInteg()
319//
320//--
321: mXPos(NULL), mWeights(NULL)
322{}
323
324
325//++
326GLInteg::GLInteg(FUNC f, double xmin, double xmax)
327//
328//--
329: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
330{
331 NStep(1);
332}
333
334//++
335GLInteg::GLInteg(FUNC f)
336//
337//--
338: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
339{
340 NStep(1);
341}
342
343//++
344GLInteg::GLInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
345//
346//--
347: Integrator(gff, par, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
348{
349 NStep(1);
350}
351
352//++
353GLInteg::GLInteg(GeneralFunction* gff, double* par)
354//
355//--
356: Integrator(gff, par), mXPos(NULL), mWeights(NULL), mOrder(8)
357{
358 NStep(1);
359}
360
361GLInteg::~GLInteg()
362{
363 delete[] mXPos;
364 delete[] mWeights;
365 mXPos = mWeights = NULL;
366}
367
368void
369GLInteg::InvalWeights()
370{
371 delete[] mXPos;
372 delete[] mWeights;
373 mXPos = mWeights = NULL;
374}
375
376
377void
378GLInteg::LimitsChanged()
379{
380 ComputeBounds();
381}
382
383void
384GLInteg::StepsChanged()
385{
386 ComputeBounds();
387}
388
389GLInteg&
390GLInteg::AddBound(double x)
391{
392 if (x<=mXMin || x>=mXMax) THROW(rangeCheckErr);
393 // On introduira les classes d'exections apres reflexion et de maniere systematique (Rz+cmv)
394 // if (x<=mXMin || x>=mXMax) throw range_error("GLInteg::AddBound bound outside interval");
395 mBounds.insert(x);
396 return *this;
397}
398
399
400GLInteg&
401GLInteg::SetOrder(int order)
402{
403 mOrder = order;
404 InvalWeights();
405 return *this;
406}
407
408
409
410double
411GLInteg::Value()
412{
413 if (!mXPos) ComputeWeights();
414 double s = 0;
415 set<double>::iterator i=mBounds.begin();
416 set<double>::iterator j=i; j++;
417 while (j != mBounds.end()) {
418 double s1 = 0;
419 double x1 = *i;
420 double x2 = *j;
421 for (int k=0; k<mOrder; k++)
422 s1 += mWeights[k] * FVal(x1 + (x2-x1)*mXPos[k]);
423 s += s1*(x2-x1);
424 i++; j++;
425 }
426 return s;
427}
428
429void
430GLInteg::ComputeBounds()
431{
432 mBounds.erase(mBounds.begin(), mBounds.end());
433 for (int i=0; i<=mNStep; i++)
434 mBounds.insert(mXMin + (mXMax-mXMin)*i/mNStep);
435}
436
437void
438GLInteg::ComputeWeights()
439{
440 const double EPS_gauleg = 3.0e-11;
441
442 int m=(mOrder+1)/2;
443 const double xxMin = 0;
444 const double xxMax = 1;
445
446 mXPos = new double[mOrder];
447 mWeights = new double[mOrder];
448
449 double xm=0.5*(xxMax+xxMin);
450 double xl=0.5*(xxMax-xxMin);
451 for (int i=1;i<=m;i++) {
452 double z=cos(3.141592654*(i-0.25)/(mOrder+0.5));
453 double z1, pp;
454 do {
455 double p1=1.0;
456 double p2=0.0;
457 for (int j=1;j<=mOrder;j++) {
458 double p3=p2;
459 p2=p1;
460 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
461 }
462 pp=mOrder*(z*p1-p2)/(z*z-1.0);
463 z1=z;
464 z=z1-p1/pp;
465 } while (fabs(z-z1) > EPS_gauleg);
466 mXPos[i-1] = xm-xl*z;
467 mXPos[mOrder-i] = xm+xl*z;
468 mWeights[i-1] = 2.0*xl/((1.0-z*z)*pp*pp);
469 mWeights[mOrder-i] = mWeights[i-1];
470 }
471
472}
473
Note: See TracBrowser for help on using the repository browser.