|
STK++ 1.0
|
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*/