libmoldeo (Moldeo 1.0 Core)  1.0
libmoldeo es el conjunto de objetos y funciones, que permiten ejecutar las operaciones básicas de la plataforma Moldeo, y que compone su núcleo.
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Amigas 'defines' Grupos Páginas
moMathNumericalAnalysis.cpp
Ir a la documentación de este archivo.
1 /*******************************************************************************
2 
3  moMathNumericalAnalysis.h
4 
5  ****************************************************************************
6  * *
7  * This source is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This code is distributed in the hope that it will be useful, but *
13  * WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15  * General Public License for more details. *
16  * *
17  * A copy of the GNU General Public License is available on the World *
18  * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
19  * obtain it by writing to the Free Software Foundation, *
20  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  * *
22  ****************************************************************************
23 
24  Copyright(C) 2006 Fabricio Costa
25 
26  Authors:
27  Fabricio Costa
28  Andrés Colubri
29 
30  Portions taken from
31  Wild Magic Source Code
32  David Eberly
33  http://www.geometrictools.com
34  Copyright (c) 1998-2007
35 
36 *******************************************************************************/
37 
39 
40 // moIntegrate1 class -----------------------------------------------------------
41 /*
42 template <class Real>
43 Real moIntegrate1<Real>::RombergIntegral (int iOrder, Real fA, Real fB,
44  Function oF, void* pvUserData)
45 {
46  //assert(iOrder > 0);
47  Real** aafRom;
48 
49  aafRom = new Real*[2];
50  for (int i = 0; i < 2; i++) aafRom[i] = new Real[iOrder];
51 
52  Real fH = fB - fA;
53 
54  aafRom[0][0] = ((Real)0.5)*fH*(oF(fA,pvUserData)+oF(fB,pvUserData));
55  for (int i0=2, iP0=1; i0 <= iOrder; i0++, iP0 *= 2, fH *= (Real)0.5)
56  {
57  // approximations via the trapezoid rule
58  Real fSum = (Real)0.0;
59  int i1;
60  for (i1 = 1; i1 <= iP0; i1++)
61  {
62  fSum += oF(fA + fH*(i1-((Real)0.5)),pvUserData);
63  }
64 
65  // Richardson extrapolation
66  aafRom[1][0] = ((Real)0.5)*(aafRom[0][0] + fH*fSum);
67  for (int i2 = 1, iP2 = 4; i2 < i0; i2++, iP2 *= 4)
68  {
69  aafRom[1][i2] = (iP2*aafRom[1][i2-1] - aafRom[0][i2-1])/(iP2-1);
70  }
71 
72  for (i1 = 0; i1 < i0; i1++)
73  {
74  aafRom[0][i1] = aafRom[1][i1];
75  }
76  }
77 
78  Real fResult = aafRom[0][iOrder-1];
79 
80  for (int i = 0; i < 2; i++) delete[] aafRom[i];
81  delete[] aafRom;
82 
83  return fResult;
84 }
85 */
86 template <class Real>
87 Real moIntegrate1<Real>::GaussianQuadrature (Real fA, Real fB, Function oF,
88  void* pvUserData)
89 {
90  // Legendre polynomials
91  // P_0(x) = 1
92  // P_1(x) = x
93  // P_2(x) = (3x^2-1)/2
94  // P_3(x) = x(5x^2-3)/2
95  // P_4(x) = (35x^4-30x^2+3)/8
96  // P_5(x) = x(63x^4-70x^2+15)/8
97 
98  // generation of polynomials
99  // d/dx[ (1-x^2) dP_n(x)/dx ] + n(n+1) P_n(x) = 0
100  // P_n(x) = sum_{k=0}^{floor(n/2)} c_k x^{n-2k}
101  // c_k = (-1)^k (2n-2k)! / [ 2^n k! (n-k)! (n-2k)! ]
102  // P_n(x) = ((-1)^n/(2^n n!)) d^n/dx^n[ (1-x^2)^n ]
103  // (n+1)P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x)
104  // (1-x^2) dP_n(x)/dx = -n x P_n(x) + n P_{n-1}(x)
105 
106  // roots of the Legendre polynomial of specified degree
107  const int iDegree = 5;
108  const Real afRoot[iDegree] =
109  {
110  (Real)-0.9061798459,
111  (Real)-0.5384693101,
112  (Real) 0.0,
113  (Real)+0.5384693101,
114  (Real)+0.9061798459
115  };
116  const Real afCoeff[iDegree] =
117  {
118  (Real)0.2369268850,
119  (Real)0.4786286705,
120  (Real)0.5688888889,
121  (Real)0.4786286705,
122  (Real)0.2369268850
123  };
124 
125  // Need to transform domain [a,b] to [-1,1]. If a <= x <= b and
126  // -1 <= t <= 1, then x = ((b-a)*t+(b+a))/2.
127  Real fRadius = ((Real)0.5)*(fB - fA);
128  Real fCenter = ((Real)0.5)*(fB + fA);
129 
130  Real fResult = (Real)0.0;
131  for (int i = 0; i < iDegree; i++)
132  {
133  fResult += afCoeff[i]*oF(fRadius*afRoot[i]+fCenter,pvUserData);
134  }
135  fResult *= fRadius;
136 
137  return fResult;
138 }
139 
140 template <class Real>
141 Real moIntegrate1<Real>::TrapezoidRule (int iNumSamples, Real fA, Real fB,
142  Function oF, void* pvUserData)
143 {
144  //assert(iNumSamples >= 2);
145  Real fH = (fB - fA)/(Real)(iNumSamples - 1);
146  Real fResult = ((Real)0.5)*(oF(fA,pvUserData) + oF(fB,pvUserData));
147  for (int i = 1; i <= iNumSamples - 2; i++)
148  {
149  fResult += oF(fA+i*fH,pvUserData);
150  }
151  fResult *= fH;
152  return fResult;
153 }
154 
155 // moMinimize1 class -----------------------------------------------------------
156 
157 template <class Real>
158 moMinimize1<Real>::moMinimize1 (Function oFunction, int iMaxLevel,
159  int iMaxBracket, void* pvData)
160 {
161  //assert(oFunction);
162  m_oFunction = oFunction;
163  m_iMaxLevel = iMaxLevel;
164  m_iMaxBracket = iMaxBracket;
165  m_pvData = pvData;
166 }
167 
168 template <class Real>
170 {
171  return m_iMaxLevel;
172 }
173 
174 template <class Real>
176 {
177  return m_iMaxBracket;
178 }
179 
180 template <class Real>
182 {
183  return m_pvData;
184 }
185 
186 template <class Real>
187 void moMinimize1<Real>::GetMinimum (Real fT0, Real fT1, Real fTInitial,
188  Real& rfTMin, Real& rfFMin)
189 {
190  //assert(fT0 <= fTInitial && fTInitial <= fT1);
191 
192  m_fTMin = moMath<Real>::MAX_REAL;
193  m_fFMin = moMath<Real>::MAX_REAL;
194 
195  Real fF0 = m_oFunction(fT0,m_pvData);
196  Real fFInitial = m_oFunction(fTInitial,m_pvData);
197  Real fF1 = m_oFunction(fT1,m_pvData);
198 
199  GetMinimum(fT0,fF0,fTInitial,fFInitial,fT1,fF1,m_iMaxLevel);
200 
201  rfTMin = m_fTMin;
202  rfFMin = m_fFMin;
203 }
204 
205 template <class Real>
206 void moMinimize1<Real>::GetMinimum (Real fT0, Real fF0, Real fTm, Real fFm,
207  Real fT1, Real fF1, int iLevel)
208 {
209  if (fF0 < m_fFMin)
210  {
211  m_fTMin = fT0;
212  m_fFMin = fF0;
213  }
214 
215  if (fFm < m_fFMin)
216  {
217  m_fTMin = fTm;
218  m_fFMin = fFm;
219  }
220 
221  if (fF1 < m_fFMin)
222  {
223  m_fTMin = fT1;
224  m_fFMin = fF1;
225  }
226 
227  if (iLevel-- == 0)
228  {
229  return;
230  }
231 
232  if ((fT1 - fTm)*(fF0 - fFm) > (fTm - fT0)*(fFm - fF1))
233  {
234  // quadratic fit has positive second derivative at midpoint
235 
236  if (fF1 > fF0)
237  {
238  if (fFm >= fF0)
239  {
240  // increasing, repeat on [t0,tm]
241  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
242  }
243  else
244  {
245  // not monotonic, have a bracket
246  GetBracketedMinimum(fT0,fF0,fTm,fFm,fT1,fF1,iLevel);
247  }
248  }
249  else if (fF1 < fF0)
250  {
251  if (fFm >= fF1)
252  {
253  // decreasing, repeat on [tm,t1]
254  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
255  }
256  else
257  {
258  // not monotonic, have a bracket
259  GetBracketedMinimum(fT0,fF0,fTm,fFm,fT1,fF1,iLevel);
260  }
261  }
262  else
263  {
264  // constant, repeat on [t0,tm] and [tm,t1]
265  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
266  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
267  }
268  }
269  else
270  {
271  // quadratic fit has nonpositive second derivative at midpoint
272 
273  if (fF1 > fF0)
274  {
275  // repeat on [t0,tm]
276  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
277  }
278  else if ( fF1 < fF0 )
279  {
280  // repeat on [tm,t1]
281  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
282  }
283  else
284  {
285  // repeat on [t0,tm] and [tm,t1]
286  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
287  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
288  }
289  }
290 }
291 
292 template <class Real>
293 void moMinimize1<Real>::GetMinimum (Real fT0, Real fF0, Real fT1, Real fF1,
294  int iLevel)
295 {
296  if (fF0 < m_fFMin)
297  {
298  m_fTMin = fT0;
299  m_fFMin = fF0;
300  }
301 
302  if (fF1 < m_fFMin)
303  {
304  m_fTMin = fT1;
305  m_fFMin = fF1;
306  }
307 
308  if (iLevel-- == 0)
309  {
310  return;
311  }
312 
313  Real fTm = ((Real)0.5)*(fT0+fT1);
314  Real fFm = m_oFunction(fTm,m_pvData);
315 
316  if (fF0 - ((Real)2.0)*fFm + fF1 > (Real)0.0)
317  {
318  // quadratic fit has positive second derivative at midpoint
319 
320  if (fF1 > fF0)
321  {
322  if (fFm >= fF0)
323  {
324  // increasing, repeat on [t0,tm]
325  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
326  }
327  else
328  {
329  // not monotonic, have a bracket
330  GetBracketedMinimum(fT0,fF0,fTm,fFm,fT1,fF1,iLevel);
331  }
332  }
333  else if (fF1 < fF0)
334  {
335  if (fFm >= fF1)
336  {
337  // decreasing, repeat on [tm,t1]
338  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
339  }
340  else
341  {
342  // not monotonic, have a bracket
343  GetBracketedMinimum(fT0,fF0,fTm,fFm,fT1,fF1,iLevel);
344  }
345  }
346  else
347  {
348  // constant, repeat on [t0,tm] and [tm,t1]
349  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
350  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
351  }
352  }
353  else
354  {
355  // quadratic fit has nonpositive second derivative at midpoint
356 
357  if (fF1 > fF0)
358  {
359  // repeat on [t0,tm]
360  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
361  }
362  else if (fF1 < fF0)
363  {
364  // repeat on [tm,t1]
365  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
366  }
367  else
368  {
369  // repeat on [t0,tm] and [tm,t1]
370  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
371  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
372  }
373  }
374 }
375 
376 template <class Real>
377 void moMinimize1<Real>::GetBracketedMinimum (Real fT0, Real fF0, Real fTm,
378  Real fFm, Real fT1, Real fF1, int iLevel)
379 {
380  for (int i = 0; i < m_iMaxBracket; i++)
381  {
382  // update minimum value
383  if (fFm < m_fFMin)
384  {
385  m_fTMin = fTm;
386  m_fFMin = fFm;
387  }
388 
389  // test for convergence
390  const Real fEps = (Real)1e-08, fTol = (Real)1e-04;
391  if (moMath<Real>::FAbs(fT1-fT0) <= ((Real)2.0)*fTol*
392  moMath<Real>::FAbs(fTm) + fEps )
393  {
394  break;
395  }
396 
397  // compute vertex of interpolating parabola
398  Real fDT0 = fT0 - fTm, fDT1 = fT1 - fTm;
399  Real fDF0 = fF0 - fFm, fDF1 = fF1 - fFm;
400  Real fTmp0 = fDT0*fDF1, fTmp1 = fDT1*fDF0;
401  Real fDenom = fTmp1 - fTmp0;
402  if (moMath<Real>::FAbs(fDenom) < fEps)
403  {
404  return;
405  }
406 
407  Real fTv = fTm + ((Real)0.5)*(fDT1*fTmp1-fDT0*fTmp0)/fDenom;
408  //assert(fT0 <= fTv && fTv <= fT1);
409  Real fFv = m_oFunction(fTv,m_pvData);
410 
411  if (fTv < fTm)
412  {
413  if (fFv < fFm)
414  {
415  fT1 = fTm;
416  fF1 = fFm;
417  fTm = fTv;
418  fFm = fFv;
419  }
420  else
421  {
422  fT0 = fTv;
423  fF0 = fFv;
424  }
425  }
426  else if (fTv > fTm)
427  {
428  if (fFv < fFm)
429  {
430  fT0 = fTm;
431  fF0 = fFm;
432  fTm = fTv;
433  fFm = fFv;
434  }
435  else
436  {
437  fT1 = fTv;
438  fF1 = fFv;
439  }
440  }
441  else
442  {
443  // vertex of parabola is already at middle sample point
444  GetMinimum(fT0,fF0,fTm,fFm,iLevel);
445  GetMinimum(fTm,fFm,fT1,fF1,iLevel);
446  }
447  }
448 }
449 
void GetMinimum(Real fT0, Real fT1, Real fTInitial, Real &rfTMin, Real &rfFMin)
static Real TrapezoidRule(int iNumSamples, Real fA, Real fB, Function oF, void *pvUserData=0)
moMinimize1(Function oFunction, int iMaxLevel, int iMaxBracket, void *pvData=0)
moTypes MOint moText moParamIndex moParamReference int iRow int int i int i
Definition: all_f.js:18
static Real GaussianQuadrature(Real fA, Real fB, Function oF, void *pvUserData=0)
function e
Definition: jquery.js:71
Definition: moMath.h:64
static Real FAbs(Real fValue)
Definition: moMath.h:180