logarithm.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     logarithm.cpp
00004 
00005     This file is a part of the Arageli library.
00006 
00007     Copyright (C) Alexander Pshenichnikov, 2005--2006
00008     Copyright (C) Nikolay Santalov, 2005--2006
00009     
00010     University of Nizhni Novgorod, Russia
00011 
00012     23.12.2005
00013 
00014 *****************************************************************************/
00015 
00016 //#if 0 // WARNING! DISABLED WHILE PORTING!
00017 
00018 #include "config.hpp"
00019 
00020 #include <cstddef>
00021 #include <cmath>
00022 
00023 #include "big_int.hpp"
00024 #include "big_const.hpp"
00025 #include "powerest.hpp"
00026 
00027 #define SPARE 0xA   // WARNING! Macro!!!
00028 
00029 namespace Arageli
00030 {
00031 
00032 // Returns  [de*log2_10]
00033 big_int entier ( const big_int &de ) 
00034 {
00035     if ( !de.length() )
00036         return 0;
00037     
00038     std::size_t counter = 0;
00039     std::size_t factor = 1; 
00040     std::size_t spare_bits;
00041     std::size_t len = de.length ();
00042     big_int L;
00043     int fl = 1; 
00044     
00045     while ( fl )
00046     {
00047         L = log2_10_u ( len + SPARE * factor  ) * de;
00048         //if ( L >> len + SPARE * factor + 1 == ( L + de << 1 ) >> len + SPARE * factor + 1 );
00049         //  break;  
00050         spare_bits = SPARE * factor;
00051         while ( counter < spare_bits )
00052         {
00053             if ( ! L[ counter + len ] ) 
00054             {
00055                 fl = 0;
00056                 break;
00057             }
00058             counter++;
00059         }
00060         if ( counter == spare_bits ) 
00061         {
00062             factor++; 
00063             counter = 0;
00064         }
00065     }
00066     if ( de > 0 )
00067         return ( L >> ( len + SPARE * factor + 1 ) )  + 3 * de; 
00068     return ( L >> ( len + SPARE * factor + 1 ) )  + 3 * de - 1;
00069 }
00070 //Returns 2^{de*log2_10} with kbits precision
00071 big_int frac ( const big_int &de, std::size_t kbits) 
00072 {
00073     std::size_t n = ( kbits - 1 ) / 3 + 2;
00074     kbits += n + 4  ;
00075     big_int L;
00076     std::size_t len = de.length ( );
00077     //std::size_t spare_bits;
00078     
00079     do
00080     {
00081         L = log2_10_u ( len + kbits ) * de;
00082         L = - (( L >> ( len + kbits + 1 ) ) << ( len + kbits + 1)) + L;
00083         len += SPARE;
00084     
00085     }
00086     while   (  ( ( L + pow2<big_int> ( kbits + 1 ) ) >> ( len - SPARE + kbits + 1)   ) == 1 );  
00087     if ( L < 0 ) L = L + pow2<big_int> ( len + kbits + 1 - SPARE ) - 2;
00088     L = L >> len - SPARE + 4;
00089     
00090     //assumption that k>=56 
00091     kbits -= 3 ;
00092     std::size_t counter = 1;
00093     big_int s;
00094     big_int a = pow2<big_int> (  kbits  );
00095     len = (kbits  << 1) + 1;
00096     L = L * ln2_u ( kbits );
00097     //cout << L << endl;
00098     //cout << len << endl;
00099     s = s + a; 
00100     while ( counter < n )
00101     {
00102         a = ( ( a * L ) / counter ) >> len;//Teylor series  
00103         s = s + a;
00104         counter++;
00105     }
00106     return ( s >> n + 1 ) + 1;  
00107 }
00108 
00110 std::size_t lg10 ( const big_int &b )
00111 {
00112     std::size_t res = 0;
00113     big_int temp ( b );
00114 
00115     while ( ( temp = temp / 10 ) != 0 )
00116         res++;
00117 
00118     return res;
00119 }
00121 std::size_t lg10 ( std::size_t b )
00122 {
00123     std::size_t res = 0;
00124     std::size_t temp ( b );
00125 
00126     while ( ( temp /= 10 ) != 0 )
00127         res++;
00128 
00129     return res;
00130 }
00131 
00133 big_int power_of_ten ( std::size_t pow )
00134 {
00135     big_int res ( 1 );
00136 
00137     while ( pow-- )
00138      res = res * 10;
00139     return res;
00140 }
00141 
00142 //Returns [be / log2_10] = [be *lg(2)]
00143 big_int entier_1 ( const big_int &be )
00144 {
00145     if ( be == 0 ) return 0;
00146     
00147     int s = 0;
00148     std::size_t kbits ( be.length () + SPARE );
00149     big_int L ( be );
00150     if ( L < 0 ) 
00151     {
00152         L = -L;
00153         s = - 1;
00154     }
00155     big_int three ( 3 );
00156     do
00157     {
00158             L = ( L << ( kbits * 2 + 2) ) / (( three << kbits )+ log2_10_o ( kbits - 1 )) ; 
00159             kbits += SPARE;
00160     } while ( ( ( L + 2 ) >>  kbits + 1 )  != ( L >>  kbits + 1 ) );
00161     
00162     if ( s  ) return - ( L >>  kbits - SPARE + 2 ) - 1; 
00163     return L >> kbits - SPARE + 2; 
00164 }
00165 
00167 big_int frac_1 ( const big_int &de, std::size_t kbits)
00168 {
00169     if ( de == 0 ) return pow2<big_int> ( kbits ) ;
00170 
00171     std::size_t prec = kbits + 8; 
00172     std::size_t l = de.length() + prec + 1;
00173     big_int L;
00174     
00175     do 
00176     {
00177         L = de * lg_2_u( l );      // L ~ de * lg2 with prec + 1 precision de * lg2  = L / 2 ^ (l + 1) 
00178         L = L - ( (L >> l + 1) << l + 1); //{ de * lg2 } ~ L / 2 ^ ( l + 1 ) 
00179         if ( L < 0 ) L = L + pow2<big_int> ( l + 1 ) - 2 ; //{ -x } = 1 - { x }
00180         l += SPARE;
00181     } while ( (L +  pow2<big_int> ( de.length() + 1 ) ).length() > l);  
00182     L = L >> ( l - SPARE - prec );
00183     /* now L = { de * lg ( 2 ) } * 2 ^ ( prec + 1 ) with prec precision */
00184 
00185     //( ln1_25_u  ( prec ) + 3 * ln2_u ( prec ) )  ln10 with prec - 2 precision  ( ln10 = L / 2 ^ prec )  
00186     L = L * ( ln1_25_u ( prec ) + 3 * ln2_u ( prec ) ); // L = { de * lg ( 2 )} * ln10 with prec - 3 precision { de * lg ( 2 )} * ln10 = L / 2 ^ ( 2 * prec + 2 )
00187 
00188     /*
00189         exp ( underflow )
00190     */
00191     
00192     std::size_t n = ( kbits + 1 ) / 3 + 2;
00193     n = (n < 20 ) ? 20 : n;
00194     std::size_t pos = log ( (long double)n ) / log ( 2.0l ) + 2;//log2( n ) + 2 
00195     std::size_t counter = 1;
00196     big_int s;
00197     big_int a = pow2<big_int> ( kbits +  pos ); 
00198     std::size_t len = 2 * prec + 2;
00199     
00200     s = s + a; 
00201     while ( counter < n )
00202     {
00203         a = ( (a * L) / counter) >> len ;//Teylor series  
00204         s = s + a;
00205         counter++;
00206     }
00207     // now s ~= 10 ^ {de/log2_10} * 2 ^ kbits . It means that value  10 ^ {de/log2_10} * 2 ^ kbits is between   s and s + 2
00208     return  ( s >> pos ) + 1; //see do_dec_convert;
00209 }
00210 
00211 /*
00212 *this function convert decimal presentation : dm * 10 ^ de 
00213 *to binary presentation:  bm * 2 ^ dm  
00214 *it calculates bm and be using dm and de.  
00215 *non-integer number bm is rounded to integer in range [ 2^p, 2^{ p + 1 } ) 
00216 */
00217 void do_bin_convert ( const big_int &dm, const big_int &de, std::size_t p, big_int &bm, big_int &be )
00218 {
00219     if ( dm == 0 )
00220     {
00221         bm = be = 0;
00222         return;
00223     }
00224     //cout << "de = " << entier ( de ) << endl;
00225     be = entier ( de ) + log2 ( dm ) - p;
00226     //cout << be << endl; 
00227     //cout << " de = " << de << "   p = " << p; 
00228     bm = frac ( de, p );
00229     //cout << "frac() = " << bm << endl;
00230     bm = bm * dm / pow2<big_int> ( log2(dm));
00231     //cout << bm << endl;
00232     //cout << p << endl;
00233     if ( bm.length () - p ) 
00234     {
00235         be = be + 1;
00236         bm = bm >> 1;
00237     }
00238 }
00239 
00240 /*
00241 *this function convert binary presentation : bm * digit ^ be 
00242 *to decimal presentation:  dm * 10 ^ de  
00243 *it calculates dm and de using bm and be. 
00244 *non-integer number dm is rounded to integer in range [ 10^p, 10^{ p + 1 } ) 
00245 */
00246 std::size_t do_dec_convert ( big_int &dm, big_int &de, std::size_t p, const big_int & bm, const big_int & be )
00247 {
00248     //cout << "be = " << be << "bm = "<< bm << endl;
00249     //cout << entier_1 ( be  ) << endl;
00250     //cout << lg10 ( bm ) << endl;
00251     de = entier_1 ( be  ) + lg10 ( bm ) - p;
00252     //cout << "de =" << de << endl; 
00253     //cout << "be = " << be << "\tp = " << p <<endl; 
00254     std::size_t bp = std::size_t (( double )( p + 1 ) * ( log ( 10.0l ) / log ( 2.0l ) ) + 4.0);
00255     dm = frac_1 ( be, bp );
00256     //cout << p << endl;
00257     //cout << "dm = " << dm << "  bp = "<< bp << endl; 
00258     //cout << "dm =" << dm << endl;  
00259     
00260     //dm =  (( bm * dm ) >> bp) * power_of_ten ( p + 1 ) / power_of_ten ( lg10 (bm) ) ; 
00261     dm =  ( bm * dm * power_of_ten ( p + 1 ) >> bp )/ power_of_ten ( lg10 (bm) ) ; 
00262     //cout << " dm = " << dm << endl;
00263     dm = ( dm + 5 * dm.sign () ) / 10;
00264     
00265     //cout << "dm = "<< dm <<"   lg (dm) =" << lg10 ( dm ) << "   p = "<< p << endl;
00266     if ( ! (lg10 ( dm ) - p - 1)  ) 
00267     {
00268         de = de + 1;
00269         dm = (dm + 5 * dm.sign ()) / 10;
00270     
00271     }
00272     if ( ! ( lg10 ( dm ) - p + 1 )  ) 
00273     {
00274         de = de - 1;
00275         dm = dm * 10;
00276     }
00277     //cout << "dm = "<< dm <<"   lg (dm) =" << lg10 ( dm ) << "   p = "<< p << endl;
00278     return lg10 ( de );
00279 }
00280 
00281 }
00282 
00283 //#endif

Generated on Thu Aug 31 17:38:07 2006 for Arageli by  doxygen 1.4.7