STK++ 1.0
STK_Algo.h
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2007  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project:  stkpp::STatistiK
00027  * Purpose:  Method implementing Algorithms.
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  **/
00030 
00035 #ifndef STK_ALGO_H
00036 #define STK_ALGO_H
00037 
00038 #include <cmath>
00039 
00040 #include "../../STKernel/include/STK_Integer.h"
00041 #include "../../STKernel/include/STK_Real.h"
00042 #include "../../STKernel/include/STK_Misc.h"
00043 #include "STK_Const_Math.h"
00044 #include "STK_ISerie.h"
00045 
00046 namespace STK
00047 {
00076 template <class Serie>
00077 Real sumAlternateSerie(const ISerie<Serie>& f, Integer const& n = 0)
00078 {
00079   // Compute the rate of convergence
00080   Real rate = 3.0 + 2.0 * Const::_SQRT2_;
00081   // compute the number of iterations if needed
00082   Integer niter = n;
00083   if (niter==0)
00084   {
00085     niter = (Integer )( log(Arithmetic<Real>::epsilon())
00086                   / (Const::_LN2_-log(rate))
00087                   ) + 1;
00088   }
00089   // initialization
00090   rate   = pow(rate, niter);
00091   Real b = -2.0/(rate+1.0/rate), c = -1.0, sum = 0.0;
00092   // first iteration (k = 0)
00093   sum += (c = b-c) * f.first();
00094   b   *= (- 2.*niter*niter);
00095   // iterations
00096   for (Integer k = 1; k<niter; k++)
00097   {
00098     sum += (c = b-c) * f.next();
00099     Real aux = k+1.;
00100     b   *=   ((k + niter)/(k + aux)) * ((k - niter)/aux) * 2.;
00101   }
00102   return sum;
00103 }
00104 
00129 template <class Serie>
00130 Real sumSerie(const ISerie<Serie>& f, Integer const& iter_max = 10)
00131 {
00132   Real e0[7]; // original serie
00133   Real e1[6];
00134   Real e2[5];
00135   Real e3[4];
00136   Real e4[3];
00137   Real e5[2];
00138   Real delta, sum; // e6
00139 
00140   e0[0] = f.first();        //f[0];
00141   e0[1] = e0[0] + f.next();
00142   e0[2] = e0[1] + f.next();
00143   e0[3] = e0[2] + f.next();
00144   e0[4] = e0[3] + f.next();
00145   e0[5] = e0[4] + f.next();
00146   e0[6] = e0[5] + f.next();
00147   
00148   // first epsilon e_{-1}[n] = 0
00149   e1[0] = 1/(e0[1] - e0[0]);
00150   e1[1] = 1/(e0[2] - e0[1]);
00151   e1[2] = 1/(e0[3] - e0[2]);
00152   e1[3] = 1/(e0[4] - e0[3]);
00153   e1[4] = 1/(e0[5] - e0[4]);
00154   e1[5] = 1/(e0[6] - e0[5]);
00155   
00156   // second epsilon
00157   e2[0] = e0[0] + 1/(e1[1] - e1[0]);
00158   e2[1] = e0[1] + 1/(e1[2] - e1[1]);
00159   e2[2] = e0[2] + 1/(e1[3] - e1[2]);
00160   e2[3] = e0[3] + 1/(e1[4] - e1[3]);
00161   e2[4] = e0[4] + 1/(e1[5] - e1[4]);
00162 
00163   // third epsilon
00164   e3[0] = e1[0] + 1/(e2[1] - e2[0]);
00165   e3[1] = e1[1] + 1/(e2[2] - e2[1]);
00166   e3[2] = e1[2] + 1/(e2[3] - e2[2]);
00167   e3[3] = e1[3] + 1/(e2[4] - e2[3]);
00168 
00169   // fourth epsilon
00170   e4[0] = e2[0] + 1/(e3[1] - e3[0]);
00171   e4[1] = e2[1] + 1/(e3[2] - e3[1]);
00172   e4[2] = e2[2] + 1/(e3[3] - e3[2]);
00173 
00174   // fifth epsilon
00175   e5[0] = e3[0] + 1/(e4[1] - e4[0]);
00176   e5[1] = e3[1] + 1/(e4[2] - e4[1]);
00177 
00178   // sum e6[0]
00179   sum = e4[0] + (delta = 1/(e5[1] - e5[0]));
00180 
00181   // main loop
00182   for (int n=1; n<=iter_max; n++)
00183   { // roll s0
00184     e0[4] = e0[5];
00185     e0[5] = e0[6];
00186     e0[6] += f.next();
00187   
00188     // roll first epsilon
00189     e1[3] = e1[4];
00190     e1[4] = e1[5];
00191     if ( (delta = (e0[6] - e0[5])) == 0) break;
00192     e1[5] = 1./delta;
00193   
00194     // roll second epsilon
00195     e2[2] = e2[3];
00196     e2[3] = e2[4];
00197     if ( (delta = (e1[5] - e1[4])) == 0) break;
00198     e2[4] = e0[4] + 1./delta;
00199 
00200     // roll third epsilon
00201     e3[1] = e3[2];
00202     e3[2] = e3[3];
00203     if ( (delta = (e2[4] - e2[3])) == 0) break;
00204     e3[3] = e1[3] + 1./delta;
00205 
00206     // roll fourth epsilon
00207     e4[0] = e4[1];
00208     e4[1] = e4[2];
00209     if ( (delta = (e3[3] - e3[2])) == 0) break;
00210     e4[2] = e2[2] + 1./delta;
00211 
00212     // roll fifth epsilon
00213     e5[0] = e5[1];
00214     if ( (delta = (e4[2] - e4[1])) == 0) break;
00215     e5[1] = e3[1] + 1./delta;
00216 
00217     // roll sixth epsilon and compute sum
00218     if ( (delta = (e5[1] - e5[0])) == 0) break;
00219     if (!Arithmetic<Real>::isFinite(delta = 1./delta)) break;
00220     // sum
00221     Real sum1 = e4[0] + delta;
00222     if (sum1 == sum) break;
00223     sum = sum1;
00224   }
00225   
00226   return sum;
00227 }
00251 template <class Seriea, class Serieb>
00252 Real continuedFraction( const ISerie<Seriea>& a
00253                       , const ISerie<Serieb>& b
00254                       , Integer const& iter_max = 100
00255                       )
00256 {
00257   // initialize a_n
00258   Real an = a.first(); // a_1
00259   // note a_1 =0 => cf = 0
00260   if (an == 0.) return 0.;
00261   // initialize b_n
00262   Real bn = b.first(); // b_1
00263   // initialize numerator
00264   Real Nold = 0, Ncur = an; // = a_1
00265   // initialize denominator
00266   Real Dold = 1, Dcur = bn; // = b_1
00267   // result
00268   Real cf = 0.;
00269   // iterations
00270   for (Integer n=1; n<=iter_max; n++)
00271   {
00272     // compute a_n
00273     an = a.next();
00274     // check trivial case
00275     // (a_n =0) and (D_n = 0) => cf = +\infty
00276     if (an == 0.) return Ncur/Dcur;
00277     // update b_n
00278     bn = b.next();
00279     // compute numerator and denominator
00280     Real Nnew = bn * Ncur + an * Nold;
00281     Real Dnew = bn * Dcur + an * Dold;
00282     // update old numerator and denominator
00283     Nold = Ncur;
00284     Dold = Dcur;
00285     // update current numerator and denominator
00286     Ncur = Nnew;
00287     Dcur = Dnew;
00288     // normalize if necessary with 2^32
00289     if (abs(Dcur) > 4294967296.0)
00290     {
00291       Ncur /= Dcur;
00292       Nold /= Dcur;
00293       Dold /= Dcur;
00294       Dcur = 1.;
00295     }
00296     // normalize if necessary with 2^32
00297     if (abs(Ncur) > 4294967296.0)
00298     {
00299       Ncur /= 4294967296.0;
00300       Nold /= 4294967296.0;
00301       Dold /= 4294967296.0;
00302       Dcur /= 4294967296.0;
00303     }
00304     // if D_n not to small check cv
00305     if (abs(Dcur) != 0)
00306     {
00307       Real cfnew = Ncur/Dcur;
00308       // check cv
00309       if (abs(cf - cfnew) < abs(cfnew)*Arithmetic<Real>::epsilon())
00310         return cfnew;
00311       else
00312         cf = cfnew;
00313     }
00314   }
00315   // avoid warning at compilation
00316   return cf;
00317 }
00318 
00319 } // namespace STK
00320 
00321 #endif /*STK_ALGO_H*/