big_float.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     big_float.cpp -- Big Float Numbers implementation.
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 *****************************************************************************/
00013 
00014 //#if 0 // WARNING! DISABLED WHILE PORTING!
00015 
00016 #include "config.hpp"
00017 
00018 #include <sstream>
00019 
00020 #include "powerest.hpp"
00021 #include "logarithm.hpp"
00022 #include "big_float.hpp"
00023 
00024 
00025 #pragma warning(disable : 4244) // here: conversion from long double to size_t,
00026                                 // possible loss of data
00027 
00028 
00029 namespace Arageli
00030 {
00031 
00032 
00033 //a-la bigarith 
00034 void big_float_warning ( const char *s )
00035 {
00036   std::cerr << "Big float warning: " << s << "\n";
00037 }
00038 
00039 void big_float_error ( const char *s )
00040 {
00041   std::cerr << "Big float error: " << s << "\n";
00042 }
00043 
00044 void big_float_fatal_error(const char *s)
00045 {
00046   std::cerr << "Big float fatal error: \n " << s << "\n";
00047   exit(1);
00048 }
00049 
00050 
00051 #define CHECK_PREC(p)  if ( p < PREC_MIN || p > PREC_MAX ) \
00052     {\
00053         std::cout << p;\
00054         big_float_warning ( "attempt to use illegal precision. PREC_MIN is used as default precision" );\
00055         p = PREC_MIN;\
00056     }\
00057     //else prec = p;
00058 #define CHECK_MODE(m) if ( m < EXACT || m > TO_INF ) \
00059  {\
00060      big_float_warning ( "attempt to set illegal rounding mode. TO_NEAREST is used as default rounding mode" );\
00061      m = TO_NEAREST;\
00062  }\
00063     
00064 //returns |n| mod m
00065 unsigned fracsion ( int n, unsigned m )
00066 { 
00067     if ( n < 0 ) 
00068     return (m-((-n)%m))%m; 
00069     else return (n%m);
00070 }
00071 
00072 int get_exponent_of_double(double d)
00073 {
00074  
00075  int *pd = (int*)&d;
00076  pd += sizeof ( double ) / sizeof ( int ) - 1;
00077  *pd <<= 1;
00078  *pd += 0x80000000;//? only for 32 bits 
00079  *pd >>= ( sizeof ( int ) * 0x8 - 0xB );
00080   return *pd + 1;
00081 }
00082 
00083 _Internal::digit * get_mantissa_of_double (double d) //array of digits representing mantissa of d
00084 {
00085     _Internal::digit *man;
00086     _Internal::digit *pint;
00087     man = new _Internal::digit [ 4 ];
00088     if (!man)
00089     {
00090         std::cerr << "Big arith fatal error: \n " << "the heap overflow" << "\n";
00091         exit ( 1 );
00092     }
00093     pint = ( _Internal::digit * ) &d;
00094     man [ 0 ] = ((*pint) << 16 ) >> 16;
00095     man [ 1 ] =  ( *pint ) >> 16;
00096     pint++;
00097     man [ 2 ] = ((*pint) << 16 ) >> 16;
00098     man [ 3 ] =  ((( *pint ) << 12 ) >> 28) + 16;
00099     
00100     return man;
00101 }
00102 
00103 // TODO: Delete this function! It's already implemented (and better).
00104 //swap  a  and b
00105 //inline void swap( big_int &a, big_int &b )
00106 //{
00107 //  a = a + b;
00108 //  b = a - b;
00109 //  a = a - b;
00110 //}
00111 
00112 // Unused now 
00113 //inline long get_number_of_digits ( big_int b )
00114 //{
00115 //  return (b.length() - 1 ) / _Internal::bits_per_digit + 1;
00116 //}
00117 
00118 
00119 // return sign of big_int 
00120 inline int get_sign ( big_int s )
00121 {
00122     if ( s > 0 ) return 1;
00123     else return -1;
00124 }
00125 
00126 //нормализация с различными режимами округления
00127 /*void normalize ( long prec,  int mode, big_int &s, big_int &e )
00128 {
00129     int is_digit = 0;
00130     big_int stemp ( s ); 
00131     
00132     if ( s == 0 ) 
00133     {
00134          e = 0;
00135         return;
00136     }//если s=0, то показатель тоже зануляем
00137     if ( mode == EXACT) return;//ничего не делаем
00138 
00139     while ( get_number_of_digits ( s ) < prec )
00140     {
00141         s = s << bits_per_digit;// *(max_digit+1);
00142         e = e - 1;
00143     }//Дописали нули в конец
00144     if ( get_number_of_digits ( s ) == prec ) return;
00145     while ( get_number_of_digits ( s ) > ( prec + 1 ) )
00146     {
00147         stemp = s >> bits_per_digit;
00148         if ( !( is_digit ) && (stemp << bits_per_digit) != s ) is_digit = 1;
00149         e = e + 1;
00150         s = stemp;
00151     }
00152     switch (mode)
00153     {   
00154         case TO_NEAREST:
00155                        s = ( s + BASE * get_sign ( s ) / 2 ) >> bits_per_digit;
00156                        e = e + 1;
00157                        if ( get_number_of_digits ( s ) > prec) 
00158                        {
00159                            s = s >> bits_per_digit;
00160                            e = e+1;
00161                        }
00162                        break;
00163                      
00164     case TO_ZERO :
00165                        s = s >> bits_per_digit;
00166                        e = e + 1;
00167                        break;
00168     case TO_P_INF  :
00169                        if ( s < 0 ) s = s >> bits_per_digit;
00170                        else 
00171                        {
00172                             if ( is_digit ) s = ( s >> bits_per_digit) + 1;
00173                             else 
00174                             {
00175                                    stemp = s >> bits_per_digit;
00176                                    if ( ( stemp << bits_per_digit ) != s)  s = stemp + 1;
00177                                    else  s = s >> bits_per_digit;
00178                             }
00179                         }
00180                        e = e + 1;
00181 
00182                        if ( get_number_of_digits ( s ) > prec ) 
00183                        {
00184                            s = s >> bits_per_digit;
00185                            e = e + 1; 
00186                        }
00187                        break;
00188       case TO_M_INF :
00189                        if ( s > 0 ) s = s >> bits_per_digit;
00190                        else 
00191                        {
00192                              if ( is_digit ) s = s >> ( bits_per_digit ) - 1;
00193                              else 
00194                              {
00195                                     stemp = s >> bits_per_digit;
00196                                     if ( ( stemp << bits_per_digit ) != s) s = stemp - 1;
00197                                     else s = s >> bits_per_digit;
00198                               }
00199                        }
00200                        e=e+1;
00201 
00202                       if ( get_number_of_digits ( s ) > prec ) 
00203                       {
00204                           s = s >> bits_per_digit; 
00205                           e = e + 1;
00206                       }
00207                       break;
00208     case TO_INF     :
00209                        //s=s/(max_digit+1);
00210                        if ( is_digit )  s = ( s >> bits_per_digit) + get_sign ( s ); 
00211                        else 
00212                        {
00213                              stemp = s >> bits_per_digit;
00214                              if ( (stemp << bits_per_digit ) != s) s = stemp + get_sign ( s );
00215                              else        s=s/(max_digit+1);
00216                        }
00217                        e = e + 1;
00218                        if ( get_number_of_digits ( s ) > prec )
00219                        {
00220                            s = s >> bits_per_digit;
00221                            e = e + 1; 
00222                        }
00223                        break;
00224                      
00225     default         : break;
00226 
00227     }//switch(mode)
00228     return;
00229 }*/
00230 
00232 void big_float::normalize_1 ( long prec, long mode )
00233 {
00234     if ( !s.sign() ) 
00235     {
00236         e = 0;
00237         return;
00238     }//significant s=0, then exponenta = 0 
00239     
00240     int s_len = s.length() - prec; 
00241         
00242     if ( mode == EXACT && s.length() <= PREC_MAX ||  (!s_len)  ) return;// do nothing - mantissa has apropriate length 
00243     if ( s_len < 0  ) 
00244     {
00245         s = s << -s_len;
00246         e = e + s_len;
00247         return;
00248     }//write zero at the end and return
00249     if ( mode == EXACT )
00250     {
00251         mode = TO_NEAREST; // s.lenght > PREC_MAX 
00252         big_float_error ( "can't perfom operarion with EXACT rounding mode" );
00253     }
00254     int is_digit = 0; // needs then rounds to +-infinity
00255     is_digit = ( (s >> s_len - 1) << s_len - 1 != s ); 
00256     s = s >> s_len - 1;
00257     e = e + s_len - 1; 
00258 
00259     switch (mode)
00260     {   
00261         case TO_NEAREST:
00262                        s = ( s + s.sign() ) >> 1;
00263                        e = e + 1;
00264                        if ( s.length() > prec ) 
00265                        {
00266                            s = s >> 1;
00267                            e = e + 1;
00268                        }
00269                        break;
00270                      
00271     case TO_ZERO :
00272                        s = s >> 1;
00273                        e = e + 1;
00274                        break;
00275     case TO_P_INF  :
00276                        if ( s.sign() < 0 ) s = s >> 1;
00277                        else 
00278                        {
00279                             if ( is_digit ) s = ( s >> 1) + 1;
00280                             else 
00281                                 s = s + 1 >> 1;
00282                        }
00283                        e = e + 1;
00284 
00285                        if ( s.length() > prec ) 
00286                        {
00287                            s = s >> 1;
00288                            e = e + 1; 
00289                        }
00290                        break;
00291       case TO_M_INF :
00292                        if ( s.sign() > 0  ) s = s >> 1;
00293                        else 
00294                        {
00295                             if ( is_digit ) s = ( s >> 1) - 1;
00296                             else 
00297                                 s = s - 1 >> 1;
00298                        }
00299                        e = e + 1;
00300 
00301                        if ( s.length() > prec ) 
00302                        {
00303                            s = s >> 1;
00304                            e = e + 1; 
00305                        }
00306                        break;
00307     case TO_INF     :
00308                        //s=s/(max_digit+1);
00309                        if ( is_digit )  s = ( s >> 1 ) + s.sign();
00310                        else 
00311                        {
00312                              if ( s [ 0 ] )
00313                                  s = ( s >> 1 ) + s.sign();
00314                              else    s = s >> 1;
00315                        }
00316                        e = e + 1;
00317                        
00318                        if ( s.length() > prec )
00319                        {
00320                            s = s >> 1;
00321                            e = e + 1; 
00322                        }
00323                        break;
00324                      
00325     default         : break;
00326 
00327     }//switch(mode)
00328     return;
00329 }
00330 //returns exponent
00331 big_int big_float::get_exponent( void ) const
00332 {
00333     return e;
00334 }
00335 
00336 //returns mantissa
00337 big_int big_float::get_significant( void ) const
00338 {
00339     return s;
00340 }
00341 
00342 //default constructor
00343 big_float::big_float(void)// : e(0),s(0)
00344 {
00345     //e = s = 0;
00346 }
00347 //copy constructor
00348 big_float::big_float ( const big_float &b )
00349 {
00350     e = b.e;
00351     s = b.s;
00352 }
00353 
00354 //constructor (from string to big_float) 
00355 big_float::big_float ( const char *str )
00356 {
00357     std::istringstream s ( str );
00358     s >> *this;
00359 }
00360 
00361 //constructor  ( from two big_int to big_float )
00362 big_float::big_float ( const big_int &s, const big_int &e )
00363 {
00364     this->e = e;
00365     this->s = s;
00366     normalize_1 ( ); //Realy needed? 
00367     //Yes, needed for present implementation. Not needed if each big_float number keeps it's own precision and rounding mode 
00368 }
00369 
00370 //constructor (from double to big_float) !WARNING! Only for 32 bits digit.
00371 big_float::big_float( double b )
00372 {
00373     if ( b == 0.0 ) 
00374     {
00375         big_float ();
00376         return;
00377     }
00378     _Internal::digit *man = get_mantissa_of_double ( b );
00379 
00380     if ( b > 0.0 )
00381     {
00382         s.free_mem_and_alloc_number( 1, man, 4 );
00383     }
00384     else 
00385     {
00386         s.free_mem_and_alloc_number( -1, man, 4 );
00387     }
00388     e = get_exponent_of_double ( b ) - 52;
00389     normalize_1 (  );
00390 }
00391 big_float::big_float( int i )
00392 {
00393     *this = big_float( i, 0 );
00394 }
00395 
00396 //destructor
00397 big_float::~big_float(){}
00398 
00399 /*
00400     operator=
00401 */
00402 big_float & big_float::operator = ( const big_float &b  )  
00403 {
00404     if ( this == &b  ) return *this;
00405     s = b.s;
00406     e = b.e;
00407     return *this;
00408 }
00409 
00410 big_float & big_float::operator = ( const double d  )  
00411 {
00412     if ( d == 0.0 ) 
00413     {
00414         s = 0;
00415         e = 0;
00416         return *this;
00417     }
00418     _Internal::digit *man = get_mantissa_of_double ( d );
00419 
00420     if ( d > 0.0 )
00421     {
00422         s.free_mem_and_alloc_number( 1, man, 4 );
00423     }
00424     else 
00425     {
00426         s.free_mem_and_alloc_number( -1, man, 4 );
00427     }
00428     e = get_exponent_of_double ( d ) - 52;
00429     
00430         normalize_1 (  );
00431     return *this;
00432 }
00433 
00434 big_float & big_float::operator = ( const int i )
00435 {
00436     return big_float::operator=( double(i) );
00437 }
00438 
00439 big_float & big_float::operator = ( const char *str )
00440 {
00441     return *this = big_float::big_float( str );
00442 }
00443 
00444 /*
00445 *  compare operations 
00446 */
00447 int cmp ( const big_float & a, const big_float & b ) 
00448 {
00449     big_float temp = a - b;
00450     return temp.get_significant().sign();
00451 }
00452 
00453 int operator == ( const big_float & a, const big_float & b )
00454 {
00455     return  cmp ( a, b ) == 0;
00456 }
00457 
00458 int operator != ( const big_float & a, const big_float & b )
00459 {
00460     return cmp ( a, b ) != 0;    
00461 }
00462 
00463 int operator > (const big_float & a, const big_float & b)
00464 {
00465     return cmp ( a, b ) == 1; 
00466 }
00467 
00468 int operator >= (const big_float & a, const big_float & b)
00469 {
00470     return cmp ( a, b ) != -1;
00471 }
00472 
00473 int operator < (const big_float & a, const big_float & b)
00474 {
00475     return cmp ( a, b ) == -1;
00476 }
00477 
00478 int operator <= (const big_float & a, const big_float & b)
00479 {
00480     return cmp ( a, b ) != 1;
00481 }
00482 
00483 
00484 //set default global bits precision 
00485 void big_float::set_global_precision ( long p )
00486 {
00487     CHECK_PREC(p)
00488     prec = p;
00489 }
00490 
00491 //set global rounding mode
00492 void big_float::set_round_mode ( int m )
00493 {
00494     CHECK_MODE(m)
00495     mode = m;
00496 }
00497 
00498 //unary plus
00499 big_float operator + ( const big_float &a )
00500 {
00501     return a;// normalizaton needed may be 
00502 }
00503 
00504 //unary minus
00505 big_float operator - ( const big_float &a )
00506 {
00507     big_float b;
00508     b.s = -a.s;
00509     b.e = a.e;
00510     return b;// normalizaton needed may be ???
00511 }
00512 
00513 //operator + 
00514 big_float operator + (const big_float & b, const big_float & c)
00515 {
00516     return add ( b, c, big_float::prec, big_float::mode);
00517 }
00518 
00519 //operator -
00520 big_float operator - (const big_float & b, const big_float & c)
00521 {
00522     return sub( b, c, big_float::prec, big_float::mode);
00523 }
00524 
00525 //operator *
00526 big_float operator * (const big_float & b, const big_float & c)
00527 {
00528     return mul( b, c, big_float::prec, big_float::mode);
00529 }
00530 
00531 //operator /
00532 big_float operator / (const big_float & b, const big_float & c)
00533 {
00534     return div ( b, c, big_float::prec, big_float::mode );
00535 }
00536 
00537 // adding ( with default precision and default rounding mode )
00538 big_float add(const big_float & b, const big_float & c )
00539 {
00540     return add ( b, c, big_float::prec, big_float::mode );
00541 }
00542 
00543 // subtraction ( with default precision and default rounding mode )
00544 big_float sub (const big_float & b, const big_float & c )
00545 {
00546     return sub( b, c, big_float::prec, big_float::mode );
00547 }
00548 
00549 //multiplying ( with default precision and default rounding mode )
00550 big_float mul( const big_float & b, const big_float & c )
00551 {
00552     return mul( b, c, big_float::prec, big_float::mode );
00553 }
00554 
00555 // division ( with default precision and default rounding mode )
00556 big_float div ( const big_float &b, const big_float & c )
00557 {
00558     return div (b, c, big_float::prec, big_float::mode );
00559 }
00560 
00561 //adding ( with default rounding mode )
00562 big_float add(const big_float & b, const big_float & c, long prec)
00563 {
00564     return add (b, c, prec, big_float::mode );
00565 }
00566 
00567 //subtraction ( with default rounding mode )
00568 big_float sub(const big_float & b, const big_float & c, long prec)
00569 {
00570     return sub(b,c,prec,big_float::mode);
00571 }
00572 
00573 //multiplying ( with default rounding mode )
00574 big_float mul(const big_float & b, const big_float & c, long prec)
00575 {
00576     return mul(b,c,prec,big_float::mode);
00577 }
00578 
00579 //division ( with default rounding mode )
00580 big_float div(const big_float & b, const big_float & c, long prec)
00581 {
00582     return div(b,c,prec,big_float::mode);
00583 }
00584 
00585 //adding
00586 big_float add ( const big_float & b, const big_float & c, long prec, int mode )
00587 {
00588 
00589   CHECK_PREC(prec)//
00590   CHECK_MODE(mode)//вообще говоря, накладно // Кхе... вставте в ARAGELI_ASSERT_0 // Так и сделаем
00591   big_int b_e(b.e), c_e(c.e), b_s(b.s), c_s(c.s);
00592 
00593   big_float temp;
00594   
00595   // some checks   
00596   if ( !c_s.length() ) // c == 0, so b + c == b  
00597   {
00598     temp = b;
00599     temp.normalize_1 ( prec, mode );
00600     return temp;
00601   }
00602   if ( !b_s.length() ) // b == 0, so b + c == c  
00603   {
00604     temp = c;
00605     temp.normalize_1 ( prec, mode );
00606     return temp;
00607   }
00608   
00609   // followed if ( ... )... needed for adding no normalized numbers make equal length
00610   long delta = b_s.length() - c_s.length();
00611   
00612   if ( delta > 0 )
00613   {
00614     c_s = c_s << delta;
00615     c_e = c_e - delta;
00616   }
00617   else 
00618   {
00619     b_s = b_s << -delta;
00620     b_e = b_e + delta;
00621   }
00622   
00623   if ( b_e < c_e )  
00624   { 
00625       swap ( b_e, c_e );
00626       swap ( b_s, c_s );
00627   }
00628      
00629   big_int ed = b_e - c_e;//либо три раза вычислять, либо один раз сохранить
00630   
00631   if ( ed > prec  && mode != EXACT/*+1 */) // может случиться так что b_e - c_e очень большое и mode == EXACT !!! 
00632     //  условие верное, только если mode == TO_NAREST
00633   {
00634         temp.s = b_s;//если mode=EXACT, тогда, вообще говоря, этой проверки не должно быть
00635         temp.e = b_e;
00636         if ( mode != TO_NEAREST )
00637         {
00638             temp.s = ( temp.s << 1 ) + c_s.sign();
00639             temp.e = temp.e - 1;
00640         }
00641   }
00642   else
00643   {
00644       if ( ed.length() > _Internal::bits_per_digit /* PREC_MAX - b_s.length()*/ ) //ed > PREC_MAX and mode == EXACT
00645             big_float_fatal_error( "can't perfom adding with EXACT rounding mode" ); 
00646       
00647       // WARNING! I have commented '/*.to_digit()*/' at the following
00648       // source line because I think it's needless. (Sergey Lyalin)
00649       b_s = b_s << ed/*.to_digit ()*/; //можем потерять значение, если mode == EXCACT и  b_e - c_e очень большое
00650        
00651        temp.s = c_s + b_s;
00652        temp.e = c_e;
00653   }
00654   temp.normalize_1 ( prec, mode );
00655   return temp;
00656 }
00657 
00658 //subtraction
00659 big_float sub(const big_float & b, const big_float & c, long prec, int mode)
00660 {
00661  big_float temp(c);
00662  temp.s = -temp.s;
00663  temp = add ( b, temp, prec, mode);
00664  return temp;
00665 }
00666 
00667 //myltiplying
00668 big_float mul( const big_float & b, const big_float & c, long prec, int mode )
00669 {
00670   CHECK_PREC(prec)
00671   CHECK_MODE(mode)
00672   big_float temp;
00673   temp.s = b.get_significant() * c.get_significant();
00674   temp.e = b.get_exponent() + c.get_exponent();
00675   temp.normalize_1 ( prec, mode );
00676   return temp;
00677 }
00678 
00679 //настоящее деление
00680 /*big_float div(const big_float & b, const big_float & c, long prec, int mode)
00681 {
00682   //Заданы 2 числа, надо получить b/c с точностью prec
00683   if (c.s==0) return big_float();//НАДО !!!!!!!!!!!!!!!бесконечность с нужным знаком
00684   big_float x,y,z;
00685     x.s=1;
00686         int q=get_number_of_digits(c.s);
00687         int i=0;
00688     x.e=-c.e-q; //x.e=x.e-q;
00689         normalize(prec,mode,x.s,x.e);
00690         y=x;
00691         normalize(prec,mode,y.s,y.e);
00692         z=y-x;
00693         normalize(prec,mode,z.s,z.e);
00694         //получим сначала 1/c
00695         std::cout<<(-c.e-q)<<"\n"<<x<<"\t\t"<<y<<"\n";
00696         long p=prec;
00697         while (/*(z.e>(-p-2-b.e-get_number_of_digits(b.s))&&(i<100))//)
00698     {
00699                 i++;
00700         y=x;
00701                 x=2*y-c*y*y;
00702                 z=x-y;
00703                 std::cout<<"x="<<x<<"\t\t"<<"y="<<y<<"\t\t";
00704                 std::cout<<"z.e="<<z.e<<std::endl;
00705                 //prec=prec*2;
00706                 //getch();
00707         }
00708         prec=p;
00709         if (get_sign(x.s)!=get_sign(c.s)) x=-x;
00710         z=b*x; normalize(prec,mode,z.s,z.e);
00711     return (z);
00712 } */
00713 //division
00714 big_float div ( const big_float & b, const big_float & c, long prec, int mode)
00715 {
00716   //std::cout << "1: " << b << "\t 2: " << c << "  prec" << prec << std::endl; 
00717   if ( c.s==0 ) return big_float();//НАДО !!!!!!!!!!!!!!!бесконечность с нужным знаком
00718   big_float x;
00719   big_int temp = pow2<big_int> ( prec << 1 );
00720   
00721   //std::cout << "temp = " << temp << std::endl;
00722   //for ( long i=0; i<prec; i++, temp=temp*(max_digit+1),temp=temp*(max_digit+1));
00723   //std::cout << "c.s = " << c.s << std::endl;
00724   x.s = temp / c.s;
00725   x.e = -c.e - prec - prec;
00726   //x.out( std::cout, 'd');
00727   x.normalize_1 (prec,mode );
00728   //std::cout << "  / : "<< x * b << std::endl;
00729   return mul( x, b, prec, mode );
00730 }
00731 big_float divnu ( const big_float & b, const big_float & c, long prec, int mode)
00732 {
00733     //Получим сначала 1/с, а потом умножим на b
00734     //для этого, чтобы скорость сходимости была хорошей с должно быть между 1/2 и 1
00735     short k = 0;
00736     big_float x;
00737     big_float temp = 1;
00738     temp.out ( std::cout, 'd');
00739     x.s = c.s;
00740     while ( x.s.length() % _Internal::bits_per_digit > 0 ) 
00741     {
00742         x.s = x.s << 1;
00743         k++;
00744     }
00745     x.e = -( int )x.s.length();// / bits_per_digit;
00746     for ( int i=0; i < prec + 1; i++ )
00747     {
00748         temp = mul (2,temp,prec,mode) - mul ( mul ( temp,temp,prec,mode ),x,prec,mode );
00749     }
00750     for (int i = 0; i < k; i++)
00751     {
00752         temp = temp * 2;
00753     }
00754     temp.e = temp.e + x.e - c.e;
00755     temp = mul ( b, temp, prec, mode );
00756     return temp;
00757 }
00758 
00759 big_float div_i ( const big_int & c )
00760 {
00761     std::size_t l  = c.length();
00762 
00763     std::size_t step = 1;
00764     big_float res;
00765         
00766     res.s = 1;
00767     
00768     for ( step = 1 ; step < 32; step <<= 1 )
00769     {
00770         res.s = res.s * ( pow2<big_int> ( l * step + 1  ) - c * res.s ); 
00771     }
00772     //res.e =- l * ( step );
00773     std::cout << 10000 * res.s / pow2<big_int> ( 500)<< std::endl;
00774     //std::cout << res.s << std::endl << res.e << std::endl;
00775     return res;
00776 }
00777 
00778 
00779 /*std::ostream & operator << (std::ostream & s, const big_float & x)//простая версия
00780 {
00781  big_int temp=1;
00782  big_int i=0;
00783 
00784  if ( x.get_exponent() >= 0 )//если число целое, то и выводим как целое
00785  {
00786   for( ; i < x.get_exponent () ; i = i + 1, temp = temp >>  bits_per_digit);
00787   s << ( x.get_significant( ) * temp ) << std::endl;
00788  }
00789  else//деление столбиком
00790  {
00791   big_int num,denum=1;
00792   num=x.get_significant()*get_sign(x.s);
00793   for(i=0;i<-x.get_exponent();i=i+1,denum=denum*(max_digit+1));
00794   temp=num/denum;
00795   if(x.get_significant()<0) std::cout<<'-';
00796   s<<temp<<',';
00797   num=(num-temp*denum)*10;
00798   for(i=0;i<PREC;i=i+1)
00799   {
00800    temp=num/denum;
00801    s << temp;
00802    num=(num-temp*denum)*10;
00803 
00804   }
00805  }
00806  return s;
00807 }*/
00808 
00809 /*
00810 * stream operators 
00811 */
00812 
00813 void reduce_final_zeros ( std::basic_string<char> &str )
00814 {
00815     std::size_t last_zero = str.length() - 1;  
00816     
00817     while ( str[ last_zero ] == '0' )
00818         last_zero--;
00819     str.erase(last_zero + 1);
00820     if ( str[last_zero] == '.' )
00821         str.erase(last_zero--);
00822     if ( str[last_zero] == '.' )
00823         str.erase(last_zero);
00824 }
00825 
00826 std::istream & operator >> ( std::istream &is , big_float &fnum )
00827 {
00828     char simbol;
00829     big_int dm, de, bm,be;
00830     long add = 0;
00831     
00832     std::stringstream bufferm; //integer part of mantissa
00833     std::stringstream buffere; //exponenta
00834         
00835     do 
00836     {
00837         is.get( simbol );
00838     } while ( isspace ( simbol ) && !is.fail() );
00839     
00840     if ( simbol == '-' || simbol == '+' ) // signum may be 
00841     {
00842         bufferm << simbol;
00843         is.get ( simbol );
00844     }
00845 
00846     if ( isdigit ( simbol ) ) // mantissa
00847     {
00848         bufferm << simbol;
00849         is.get ( simbol );
00850         while ( isdigit ( simbol ) && !is.fail() )
00851         {
00852             bufferm << simbol;
00853             is.get ( simbol );
00854         }
00855     }
00856     
00857     if ( simbol == '.' )//decimal point
00858     {
00859         simbol = is.get ();
00860         while ( isdigit (simbol) && !is.fail() )
00861         {
00862             bufferm << simbol;
00863             simbol = is.get();
00864             add++;
00865         }
00866     }
00867     
00868     if ( simbol == 'e' || simbol == 'E')//exponenta
00869     {
00870         is.get ( simbol );
00871         if ( simbol == '-' || simbol == '+') // signum may be 
00872         {
00873             buffere << simbol;
00874             is.get ( simbol );
00875         }
00876         while ( isdigit (simbol)  && !is.fail() )
00877         {
00878             buffere << simbol;
00879             is.get ( simbol );
00880         }
00881     }
00882     
00883     if ( bufferm.str().empty() || bufferm.str() == "+" || bufferm.str() == "-")
00884     {
00885         fnum = big_float ();//zero 
00886     }
00887     else 
00888     {
00889         bufferm >> dm;
00890         if ( !bufferm.str().empty() && buffere.str() != "+" && buffere.str() != "-" )
00891             buffere >> de;
00892         de = de - add;
00893         do_bin_convert (dm, de, big_float :: prec /*- 1 bits_per_digit - 1*/, bm, be);
00894         //if ( be.get_sign() != -1 )
00895         //{
00896         //  bm = bm << (be - (be / bits_per_digit) * bits_per_digit); 
00897         //  be =  be  / bits_per_digit;
00898         //}
00899         //else 
00900         //{
00901         //  bm = bm << bits_per_digit + be - (be / bits_per_digit) * bits_per_digit; 
00902         //  be = be / bits_per_digit - 1;
00903         //}
00904             //std::cout << "bm = " << bm.length() << "    be = "  << be.length() << std::endl; 
00905         fnum = big_float ( bm, be );
00906         //std::cout << fnum.get_significant()<< std::endl;
00907         //std::cout << fnum.get_exponent()<< std::endl;
00908     }
00909     
00910     is.putback ( simbol );
00911     return is;
00912 }
00913 
00914 std::ostream & operator << ( std::ostream &os , const big_float &fnum )
00915 {
00916     long flags = os.flags( );
00917 
00918     if ( flags & std::ios::scientific )
00919         fnum.out ( os, 'e' );
00920     else if ( flags & std::ios :: fixed )
00921         fnum.out ( os, 'f');
00922     else 
00923         fnum.out(os, 'a');
00924     return os;
00925 }
00926 
00928 void big_float :: in ( std::istream & ins, char c )
00929 {
00930     switch  ( c )
00931     {
00932         case 'f': 
00933             ins >> *this;
00934             break;      
00935         case 'd':
00936             ins >> s >> e;
00937             normalize_1 ();
00938             break;
00939         default:
00940             big_float_warning ( "unrecognized input format: " );
00941             std::cerr << c << '\n';
00942             ins >> *this;
00943     }
00944 }
00945 
00946 void big_float :: out ( std::ostream & os, char c  ) const 
00947 {
00948     using namespace _Internal;
00949     
00950     if ( !s.sign() ) // always show 0.0 if number is zero 
00951     {
00952         os << "0.0";
00953         return;
00954     }
00955     
00956     std::stringstream str;            // for temporary output 
00957     big_int dm, de;                   // mantissa and exponenta in decimal representation   
00958     int  position;                    // decimal point position 
00959     std::basic_string<char> temp_str; // for temporary output
00960 
00961     if ( os.precision() > D_PREC_MAX )
00962         os.precision( D_PREC_MAX ); 
00963     std::ios_base::fmtflags prev_flags = os.flags ();   // ostream flags
00964     
00965     //don't take a lot of trouble over signums
00966     if ( s.sign() == -1 ) 
00967         os << "-";
00968             
00969     else if ( prev_flags & std::ios::showpos )
00970         os << "+";
00971 
00972     str.setf( std::ios::dec | std::ios::showpos ); // always out signum see below  
00973     
00974     switch ( c )
00975     {
00976         case 'f': //floating point mode e.g 123.456 
00977                 position = s.length() + e.to_native_int<int>(); // Check this conversion good way to improve this function 
00978                 
00979                 //approximately evaluate floating point position in decimal representation  
00980                 if ( position >= 0 )
00981                     position = 1 + ( int )((position + 1) * log (2.0l) / log ( 10.0l )); 
00982                 else 
00983                     position = (int)( (long double) position * log (2.0l) / log ( 10.0l ) );
00984                 
00985                 if ( position + os.precision() > 0 ) //there is significant digits (probably) 
00986                 {
00987                     // convert to decimal and out in string stream  
00988                     do_dec_convert(dm, de, os.precision() + position, s, e);
00989                     str << dm;
00990                     temp_str = str.str();// save dm in non-const string variable for manipulation 
00991                     temp_str.erase(0,1); // erase signum ( it have been printed already )  
00992 
00993                     if ( position > 0 )
00994                     {
00995                         //insert decimal point in right position 
00996                         temp_str.insert( position = temp_str.length() + de.to_native_int<int>(), "." );
00997                     }
00998                     else //there is leading zeros 
00999                     {
01000                         os << "0.";
01001                         if ( position ) //one zero is produced already 
01002                         {
01003                             os.width( -position );
01004                             os.fill ( '0' );
01005                             os << "0"; 
01006                         }
01007                         if (temp_str.length() <= os.precision() + position ) 
01008                             position--, os << "0"; 
01009                     }
01010 
01011                     //erase excess digits and final zeros //without rounding!!  
01012                     temp_str.erase( position + os.precision() ); 
01013                     reduce_final_zeros ( temp_str );
01014                     os << temp_str;
01015                 }
01016                 else // no significant digits on this precision (only zeros) 
01017                     os << "0.0";
01018                             
01019                 break;
01020 
01021         case 'e':// exponential mode  e.g 1.23e456
01022                 
01023                 do_dec_convert ( dm, de, os.precision(), s, e );
01024                 str << dm;
01025                 temp_str = str.str();
01026                 temp_str.erase(0,1); // erase signum ( it have been printed already )
01027                 temp_str.insert(1,".");
01028                 reduce_final_zeros ( temp_str ); 
01029 
01030                 //out 
01031                 if ( prev_flags & std::ios::uppercase )
01032                     os << temp_str << 'E' << de + os.precision();
01033                 else 
01034                     os << temp_str << 'e' << de + os.precision();   
01035 
01036                 break; 
01037 
01038         case 'a': // auto format ( if neither scientific notation and not fixed notation are used )
01039                 do_dec_convert ( dm, de, os.precision(), s, e );
01040                 str << dm;
01041                 temp_str = str.str();
01042                 temp_str.erase(0,1);// erase signum ( it have been printed already )
01043 
01044                 if ( de.sign() < 0 && de.to_native_int<int>() > -4 - os.precision () ) // show number in fixed format 
01045                 {
01046                     position = temp_str.length()+ de.to_native_int<int>(); //determine floating point position  
01047                     if ( position <= 0 ) //there is leading zeros
01048                     {
01049                         os << "0.";
01050                         if ( position ) //one zero is produced already 
01051                         {
01052                             os.width( -position );
01053                             os.fill ( '0' );
01054                             os << "0"; 
01055                         }
01056                     }
01057                     else if ( position != os.precision() ) 
01058                         //insert decimal point in right position 
01059                         temp_str.insert ( position, "." );
01060                     else 
01061                         temp_str.insert ( position, ".." ); //will be erased in followed
01062 
01063                     //erase excess digits and //without rounding!!  
01064                     temp_str.erase( temp_str.length()-1 );
01065                     reduce_final_zeros ( temp_str );
01066                     os << temp_str;
01067                 }
01068                 else // use scientific format
01069                 {
01070                     temp_str.insert( 1,"." );
01071                     //erase excess digits //without rounding!!  
01072                     temp_str.erase( temp_str.length() - 1 ); 
01073                     reduce_final_zeros ( temp_str );
01074 
01075                     //out 
01076                     if ( prev_flags & std::ios::uppercase )
01077                         os << temp_str << 'E' << de + os.precision();
01078                     else 
01079                         os << temp_str << 'e' << de + os.precision(); 
01080                 }
01081                 
01082             break;
01083 
01084         case 'b'://binary ( zero and one ). out significant and exponent separately 
01085             if ( s.sign() == -1 )
01086                 os << '-';
01087             else if ( prev_flags & std::ios::showpos )
01088                 os << '+';
01089             for ( int counter = s.length () - 1; counter >= 0 ; counter-- )
01090                 os << s [ counter ]; 
01091 
01092             os << '\t';
01093 
01094             if ( e.sign() == -1 )
01095                 os << '-';
01096             else if ( prev_flags & std::ios::showpos )
01097                 os << '+';
01098 
01099             for ( int counter = e.length () - 1; counter >= 0 ; counter-- )
01100                 os << e [ counter ]; 
01101             break;
01102 
01103         case 'd': // out significant and exponent separately, in decimal mode   
01104             os.setf( std::ios :: dec, std::ios::hex );
01105             os << s << '\t' << e;
01106             break;
01107 
01108         case 'h': // out significant and exponent separately, in hex mode 
01109             os.setf( std::ios::hex, std::ios::dec );
01110             os << s << '\t' << e;
01111             break;
01112 
01113         case 'o': // out significant and exponent separately, in oct mode 
01114             os.setf( std::ios :: oct, std::ios::dec | std::ios::hex );
01115             os << s << '\t' << e;
01116             break;
01117 
01118         default:
01119             std::cerr << "Warning!: unrecognized output format:" << c << std::endl;
01120             os.setf( std::ios::dec);
01121             os << s << '\t' << e;
01122     }
01123     //restore flags 
01124     os.setf( prev_flags, os.flags() );
01125 
01126 }
01127 //returns a floating-point value representing the smallest integer that is greater than or equal to a
01128 big_float ceil  (const big_float & a)
01129 {
01130     big_float res ( a );
01131     big_int e = a.e;
01132     big_int temp;
01133 
01134     if ( e >=  0 )
01135         return res;
01136     if ( e <= -big_int(a.s.length()) ) 
01137     {
01138         if ( a.s > 0 )
01139             return 1.0;
01140         else return 0.0;
01141     }
01142     temp = ( res.s >> e) << e;
01143     if ( res.s != temp && res.s > 0 ) 
01144         res.s = temp + pow2<big_int>( e/*.to_digit ()*/ );  
01145     else res.s = temp;
01146     return res;
01147 }
01148 
01149 // returns a floating-point value representing the largest integer that is less than or equal to a
01150 big_float floor (const big_float & a)
01151 {
01152     big_float res ( a );
01153     big_int e = a.e;
01154     big_int temp;
01155 
01156     if ( e >=  0 )
01157         return res;
01158     if ( e <= -big_int(a.s.length()) ) 
01159     {
01160         if ( a.s > 0 )
01161             return 1.0;
01162         else return 0.0;
01163     }
01164     temp = ( res.s >> e) << e;
01165     if ( res.s != temp && res.s < 0 ) 
01166         res.s = temp - pow2<big_int>( e );  
01167     else res.s = temp;
01168     return res;
01169 
01170 }
01171 
01172 // Returns the fractal part of the number
01173 big_float frac  (const big_float & a)
01174 {
01175     if ( a.e >= 0 )
01176         return 0.0;
01177     
01178     big_float res ( a );
01179     if ( res.e <= - big_int(res.s.length()) )
01180         return res;
01181     
01182     res.s = res.s - ((res.s >> res.e) << res.e);
01183     return res;
01184 }
01185 
01186 // returns an big-integer value representing the smallest integer that is greater than or equal to a
01187 big_int iceil (const big_float & a)
01188 {
01189     std::size_t l = a.s.length();
01190     if ( !l ) return l;
01191     
01192     big_int temp ( a.s );
01193     if ( a.e > 0 )
01194     {
01195         if ( a.e + a.s.length() > SHRT_MAX/*??*/  )
01196             big_float_fatal_error ( "Can't convert from big_float to big_int ( exponent too large )..." );
01197         return a.s <<a.e;   
01198     }
01199     if ( a.e <= -big_int(a.s.length()) )
01200         return ( a.s > 0 ) ? 1 : 0;
01201     temp = temp >> a.e;
01202     if ( temp << a.e != a.s && temp > 0)
01203         return temp + 1;  
01204     return temp;
01205 }
01206 
01207 // returns a big-integer  value representing the largest integer that is less than or equal to a
01208 big_int ifloor(const big_float & a)
01209 {
01210     std::size_t l = a.s.length();
01211     if ( !l ) return l;
01212     
01213     big_int temp ( a.s );
01214     if ( a.e > 0 )
01215     {
01216         if ( a.e + a.s.length() > SHRT_MAX/*??*/  )
01217             big_float_fatal_error ( "Can't convert from big_float to big_int ( exponent too large )..." );
01218         return a.s <<a.e;   
01219     }
01220     if ( a.e <= -big_int(a.s.length()) )
01221             return ( a.s > 0 ) ? 0 : -1;
01222     temp = temp >> a.e;
01223     if ( temp << a.e != a.s && temp > 0)
01224         return temp;  
01225     return temp - 1;
01226 }
01227 //sqrt 
01228 big_float fsqrt( const big_float & b )
01229 {
01230     return fsqrt( b, big_float :: prec, big_float :: mode);
01231 }
01232 
01233 //user must call fsqrt( const big_float & b ) function instead two forward
01234 //functions ( because EXACT mode not supported yet )  
01235 big_float fsqrt(const big_float & bf, long prec)
01236 {
01237     return fsqrt( bf, prec, big_float :: mode);
01238 }
01239 
01240 big_float fsqrt(const big_float & bf, long prec, int mode)
01241 {
01242     big_float res ( bf );
01243     int l;
01244 
01245     if ( res.e [ 0 ] )
01246     {   
01247         res.s = res.s << 1;
01248         res.e = res.e - 1;
01249     }
01250     
01251     l = (res.s.length() - 2 * prec - 1);
01252     l = (l / 2) * 2;
01253 
01254     if ( l > 0 )
01255     {   
01256         res.s = res.s >> l;
01257         res.e = res.e + l;
01258     }
01259     else 
01260     {
01261         res.s = res.s << (-l) + 2;
01262         res.e = res.e + l - 2;
01263     }
01264     res.s = sqrt ( res.s );
01265     res.e = res.e >> 1;
01266     res.normalize_1 ( prec, mode );//error may be if mode == TO_INF
01267     
01268     return res;
01269 }
01270 //Newton fsqrt
01271 big_float nfsqrt ( const big_float & bf, long prec, int mode )
01272 {
01273     big_float res;
01274     //std::cout << bf << std::endl;
01275     res.e = ((( bf.get_exponent() ) + bf.get_significant().length() - 1) >> 1) + 1;
01276     res.s = 1;
01277     //res.normalize_1();
01278     std::cout << "x0 "<<res << std::endl; 
01279     //res.out ( std::cout, 'd' ) ;
01280     //std::cout << std::endl;
01281     std::size_t n = log ( (long double)prec + 1 ) / log ( 2.0l ) + 1;
01282     
01283     for ( std::size_t counter = 1; counter <= 2 * n; counter ++ )
01284     {
01285         std::cout << div( bf, res, counter * 2, EXACT ) << std::endl;
01286         res = add ( res,  div( bf, res, counter * 2, EXACT ), counter * 2, TO_NEAREST );  
01287         std::cout << res << std::endl;
01288         res.e = res.e - 1;
01289         std::cout << counter << " iter \t";
01290         std::cout << res << std::endl;
01291         //res.out( std::cout, 'd' );
01292         //std::cout << std::endl;
01293     }
01294     res.normalize_1 ( prec, mode );//error may be if mode == TO_INF
01295     
01296     return res;
01297 }
01298 //Random numbers 
01299 big_float frandom  ( long prec )
01300 {
01301     CHECK_PREC(prec)//
01302     return big_float ( big_int::random_with_length_or_less( prec ), -prec );
01303 }
01304 //Random numbers 
01305 big_float frandom  ( )
01306 {
01307     return big_float ( big_int::random_with_length_or_less( big_float::prec ), -big_float::prec );
01308 }
01309 
01310 big_float frandom1 ( long bits, const big_int & exp)
01311 {
01312     CHECK_PREC(bits)//
01313     return big_float (  big_int::random_with_length_or_less( bits ) + pow2<big_int>( bits - 1 ) , exp );
01314 }
01315 
01316 /*not used now*/
01317 int big_float::is_NaN( )
01318 {
01319   return 0;
01320 }     
01321 int big_float::is_Zero( )
01322 {
01323  return ( s==0 );
01324 }
01325 
01326 int big_float::is_pZero( )
01327 {
01328  return ( ( s ==0 ) && (get_sign( s ) == 1) );
01329 }
01330 
01331 int big_float::is_mZero()
01332 {
01333  return ((s==0)&&(get_sign(s)==-1));
01334 }
01335 
01336 int big_float::is_Special()
01337 {
01338   return ((is_NaN())||(is_Inf())||(is_Zero()));
01339 }     
01340    
01341 
01342 int big_float::is_Inf()
01343 {
01344   return 0;
01345 }
01346 
01347 long big_float::prec; //bits precision 
01348 long big_float::mode; //rounding mode
01349 
01350 
01351 }
01352 
01353 //#endif

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