longint.cc

Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2006 by Rafael Ostertag
00003 //
00004 //  This program is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (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 General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 //
00018 //
00019 // $Id: longint.cc,v 1.9 2006/12/31 00:49:39 rafi Exp $
00020 //
00021 
00031 #include <iostream>
00032 #include <limits>
00033 #include <list>
00034 #include <cstdio>
00035 #include <cstring>
00036 #include <cstdlib>
00037 #include <cmath>
00038 
00039 #ifdef DEBUG
00040 #include <cassert>
00041 #endif
00042 
00043 #include "casobject.h"
00044 #include "casexception.h"
00045 #include "sum.h"
00046 #include "product.h"
00047 #include "fraction.h"
00048 #include "longint.h"
00049 
00056 // Private Methods
00057 // ----------------------------------------------------------------------------
00058 
00067 unsigned long
00068 LongInt::frontpartlength() const {
00069     std::list<unsigned int>::const_reference i = lst.front();
00070 
00071     // Here we figure out how much space is needed for the last part of the
00072     // number.
00073     for ( int e = 1; e < part_len; e++ ) {
00074         if ( i < pow ( ( ( double ) 10 ), e ) ) {
00075             return e;
00076         }
00077     }
00078 
00079     return part_len;
00080 }
00081 
00092 void
00093 LongInt::str2longint ( const char *str_num ) {
00094 
00095     lst.clear();
00096 
00097     // Points to last printable character
00098     // of the buffer.
00099     const char *str_end = str_num + ( strlen ( str_num ) - 1 );
00100 
00101     // This holds the part of the number, beginning from the back
00102     char part[part_len+1];
00103     // Terminate the string
00104     part[part_len] = '\0';
00105 
00106     // Initialize the rest to the character zero
00107     memset ( part, '0', part_len );
00108 
00109     SetPositive();
00110 
00111     bool part_need_flush = false;
00112     int c = part_len - 1;
00113     for ( ;str_num <= str_end;str_end-- ) {
00114         if ( ( *str_end == '-' ) || ( *str_end == '+' ) ) {
00115             if ( *str_end == '-' ) {
00116                 SetNegative();
00117             }
00118         }
00119         else {
00120             part[c] = *str_end;
00121             part_need_flush = true;
00122         }
00123         c--;
00124 
00125         // The condition ``buf==buf_end is checked to make sure ``unit is
00126         // stored even if the length of ``buf is not a multiple
00127         // of ``part_len.
00128         if ( c < 0 || ( str_num == str_end && part_need_flush ) ) {
00129             unsigned int tmp = strtol ( part, NULL, 10 );
00130             lst.push_front ( tmp );
00131             part_need_flush = false;
00132             c = part_len - 1;
00133             // Reinitialize (erase) the part
00134             memset ( part, '0', part_len );
00135         }
00136     }
00137 
00138     stripzeros();
00139     if ( IsZero() ) {
00140         SetPositive();
00141     }
00142 }
00143 
00151 void
00152 LongInt::num2longint ( const signed long num ) {
00153     if ( num == 0 ) {
00154         setzero();
00155     }
00156     else {
00157         // Get size of the number
00158         // stored in ``l
00159         int size = snprintf ( NULL, 0, "%ld", num ) + 1;
00160         char *buf = new char[size];
00161         snprintf ( buf, size, "%li", num );
00162 
00163         str2longint ( buf );
00164 
00165         delete[] buf;
00166     }
00167 }
00168 
00184 void
00185 LongInt::longint2str ( char *s, unsigned long size ) const {
00186     if ( s == 0 ) {
00187         throw EInvArg();
00188     }
00189 
00190     if ( size < ( Length() + 1 ) ) {
00191         throw EBufTooSmall();
00192     }
00193 
00194     memset ( s, 0x0, size );
00195 
00196     // Make the format string
00197     char fmt[fmt_len];
00198     snprintf ( fmt, fmt_len, "%%0%du", part_len );
00199 
00200     char *mem_pos = s;
00201     if ( IsNegative() ) {
00202         strncpy ( s, "-", 2 );
00203         mem_pos++;
00204     }
00205 
00206     std::list<unsigned int>::const_iterator i = lst.begin();
00207     while ( i != lst.end() ) {
00208         // The first time, we don't want to have padding to part_len
00209         if ( i == lst.begin() ) {
00210             unsigned long frontlen = frontpartlength();
00211             snprintf ( mem_pos, frontlen + 1, "%u" , *i );
00212             // Advance pointer to next insertion point
00213             mem_pos += frontlen;
00214         }
00215         else {
00216             snprintf ( mem_pos, part_len + 1, fmt, *i );
00217             // Advance pointer to next insertion point
00218             mem_pos += part_len;
00219         }
00220 
00221         // Next item
00222         i++;
00223     }
00224 
00225 }
00226 
00232 void
00233 LongInt::setzero() {
00234     lst.clear();
00235     lst.push_front ( 0 );
00236     SetPositive();
00237 }
00238 
00244 void
00245 LongInt::stripzeros() {
00246     // Make sure we do not add a zero item to
00247     // the front, except the result is zero
00248     if ( lst.size() < 2 ) {
00249         return;
00250     }
00251 
00252     while ( ( *lst.begin() ) == 0 ) {
00253         lst.pop_front();
00254         if ( lst.size() < 2 ) {
00255             break;
00256         }
00257     }
00258 }
00259 // ----------------------------------------------------------------------------
00260 
00261 
00262 // Constructors & Destructors
00263 // ----------------------------------------------------------------------------
00264 
00272 LongInt::LongInt ( signed long l ) : CASNumeric(), div_remainder ( 0 ) {
00273 #ifdef SHOWCONSTRUCTOR
00274     std::cerr << "# LongInt::LongInt(signed long l)" << std::endl;
00275 #endif
00276     num2longint ( l );
00277     SetRadix ( ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
00278     meta.SetAll();
00279 }
00280 
00288 LongInt::LongInt ( const char *s ) : CASNumeric(), div_remainder ( 0 ) {
00289 #ifdef SHOWCONSTRUCTOR
00290     std::cerr << "# LongInt::LongInt(const char *s)" << std::endl;
00291 #endif
00292     str2longint ( s );
00293     SetRadix ( ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
00294     meta.SetAll();
00295 }
00296 
00304 LongInt::LongInt ( const std::string &s ) : CASNumeric(), div_remainder ( 0 ) {
00305 #ifdef SHOWCONSTRUCTOR
00306     std::cerr << "# LongInt::LongInt(const std::string &s)" << std::endl;
00307 #endif
00308     str2longint ( s.c_str() );
00309     SetRadix ( ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
00310     meta.SetAll();
00311 }
00312 
00318 LongInt::LongInt ( const LongInt &r ) {
00319 #ifdef SHOWCONSTRUCTOR
00320     std::cerr << "# Copy Constructor LongInt::LongInt()" << std::endl;
00321 #endif
00322 
00323     SetSign ( r.GetSign() );
00324     SetDivDepth ( r.GetDivDepth() );
00325     SetRadix ( r.GetRadix() );
00326     lst = r.lst;
00327 
00328     if ( r.div_remainder != 0 ) {
00329         div_remainder = new LongInt ( 0L );
00330         div_remainder->lst = r.div_remainder->lst;
00331         div_remainder->SetSign ( r.div_remainder->GetSign() );
00332     } else {
00333         div_remainder = 0;
00334     }
00335     meta = r.meta;
00336 }
00337 
00341 LongInt::~LongInt() {
00342 #ifdef SHOWCONSTRUCTOR
00343     std::cerr << "# LongInt::~LongInt()" << std::endl;
00344 #endif
00345     if ( div_remainder != 0 ) {
00346         delete div_remainder;
00347     }
00348 }
00349 
00358 CASObject*
00359 LongInt::Clone() const {
00360     LongInt *res = new LongInt;
00361     *res = *this;
00362 
00363     return res;
00364 }
00365 
00366 // ----------------------------------------------------------------------------
00367 
00368 // Public Methods
00369 // ----------------------------------------------------------------------------
00384 void LongInt::Get ( char **s ) const throw ( EInvArg,
00385         EUninitializedPtr ) { if ( s == 0 ) { throw EInvArg(); }
00386 
00387     if ( *s != 0 ) {
00388         throw EUninitializedPtr();
00389     }
00390 
00391     // Reserve memory for holding the string
00392     unsigned long size = Length() + 1;
00393     *s = new char[size];
00394 
00395     longint2str ( *s, size );
00396 }
00397 
00408 void
00409 LongInt::Get ( char *s, unsigned long size ) const {
00410     longint2str ( s, size );
00411 }
00412 
00421 void
00422 LongInt::Get ( std::string &s ) const {
00423     char *tmp = 0;
00424 
00425     Get ( &tmp );
00426     s = tmp;
00427 
00428     delete []tmp;
00429 }
00430 
00438 unsigned long
00439 LongInt::Length() const {
00440     long max_strlen = lst.size() * part_len;
00441 
00442     // Do we have to return the length of a negative number, which implies
00443     // max_strlen+1 because of the space of the minus signed
00444     max_strlen += IsNegative() ? 1 : 0;
00445 
00446     // We might get a size to big if the front part has not size of part_len.
00447     // Therefore, we have to find out, how much is not used of the front part.
00448     return max_strlen - ( part_len - frontpartlength() );
00449 }
00450 
00456 void
00457 LongInt::Print() const {
00458     char *str = 0;
00459     Get ( &str );
00460 
00461     std::cout << str;
00462 
00463     delete[] str;
00464 }
00465 
00474 CASObject*
00475 LongInt::Invert() const {
00476     LongInt tmp = *this;
00477 
00478     tmp.InvertIP();
00479     return tmp.Clone();
00480 }
00481 
00490 CASObject*
00491 LongInt::Absolute() const {
00492     LongInt tmp = *this;
00493 
00494     tmp.SetPositive();
00495     return tmp.Clone();
00496 }
00497 
00503 bool
00504 LongInt::IsZero() const{
00505     return ( lst.size() == 1 && lst.back() == 0 );
00506 }
00507 
00513 bool
00514 LongInt::IsOne() const{
00515     return ( lst.size() == 1 && lst.back() == 1 );
00516 }
00517 
00530 CASObject*
00531 LongInt::GCD ( const CASObject* i ) const {
00532     if ( GetType() != i->GetType() ) {
00533         LongInt tmp ( 1L );
00534         return tmp.Clone();
00535     }
00536     const LongInt *li = dynamic_cast<const LongInt*> ( i );
00537 #ifdef DEBUG
00538     assert ( li != 0 );
00539 #endif
00540     LongInt c = *this > *li ? *this : *li;
00541     LongInt d = *this > *li ? *li : *this;
00542     LongInt r;
00543 
00544     while ( !d.IsZero() ) {
00545         r = c % d;
00546         c = d;
00547         d = r;
00548     }
00549 
00550     LongInt *ret_val = new LongInt ( c );
00551 
00552     return ret_val;
00553 }
00554 
00568 LongInt
00569 LongInt::Pow ( const LongInt &exp ) const {
00570     LongInt tmp ( 1L );
00571 
00572     for ( LongInt i ( 0L ); i < exp; i++ ) {
00573         tmp = tmp * ( *this );
00574     }
00575 
00576     return tmp;
00577 }
00578 
00588 inline LongInt
00589 LongInt::Pow ( unsigned long exp ) const {
00590     LongInt tmp ( exp );
00591     return Pow ( tmp );
00592 }
00593 
00609 LongInt
00610 LongInt::FractionalPart ( const LongInt &r ) const {
00611 #ifdef WARNINGS
00612 #warning "LongInt::FractionalPart(): Not fully implemented"
00613 #endif
00614     // Divide the numbers
00615     LongInt d_res = *this / r;
00616 
00617     // Get the remainder
00618     LongInt d_remainder = * ( d_res.div_remainder );
00619 
00620     // Division has no fractional part
00621     if ( d_remainder.IsZero() ) {
00622         return LongInt ( 0L );
00623     }
00624 
00625     LongInt u = d_remainder;
00626     u.AbsoluteIP();
00627     LongInt v = r;
00628     v.AbsoluteIP();
00629 
00630     // This will hold the part we divide by v
00631     LongInt part_dividend;
00632     part_dividend.lst.clear();
00633 
00634     LongInt result;
00635     result.lst.clear();
00636 
00637     std::list<unsigned int>::const_iterator dividend = u.lst.begin();
00638 
00639     for ( unsigned long i = 0; i < GetDivDepth(); i++ ) {
00640 
00641         if ( dividend != u.lst.end() ) {
00642             part_dividend.lst.push_back ( *dividend );
00643             part_dividend.stripzeros();
00644             if ( i == 0 ) {
00645                 part_dividend.lst.push_back ( 0 );
00646             }
00647         } else {
00648             part_dividend.lst.push_back ( 0 );
00649         }
00650 
00651         // Sum is used to hold the sum of
00652         // sum = sum + v, which is used
00653         // find v|part_dividend
00654         LongInt sum ( 0L );
00655 
00656         unsigned int t = 0;
00657 
00658         while ( sum < part_dividend ) {
00659             sum += v;
00660             t++;
00661         }
00662 
00663         // Check if we have counted one too much
00664         if ( sum > part_dividend ) {
00665             t--;
00666         }
00667 
00668 #ifdef DEBUG
00669         assert ( t < ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
00670 #endif
00671 
00672         // t is now our factor appended to the
00673         // result
00674         result.lst.push_back ( t );
00675 
00676         part_dividend -= ( v * t );
00677 
00678         if ( part_dividend.IsZero() ) {
00679             break;
00680         }
00681 
00682         if ( dividend != u.lst.end() ) {
00683             dividend++;
00684         }
00685     }
00686 
00687     return result;
00688 
00689 }
00690 
00704 LongInt
00705 LongInt::FractionalPart ( signed long r ) const {
00706     return FractionalPart ( LongInt ( r ) );
00707 }
00708 
00722 CASObject*
00723 LongInt::Add ( const CASObject* addend ) const {
00724     checkptr ( addend );
00725 
00726     if ( GetType() == addend->GetType() ) {
00727         const LongInt *li_ptr = dynamic_cast<const LongInt*> ( addend );
00728 #ifdef DEBUG
00729         assert ( li_ptr != 0 );
00730 #endif
00731         LongInt res;
00732 
00733         res = ( *this ) + ( *li_ptr );
00734         return res.Clone();
00735     }
00736 
00737     Sum tmp;
00738     CASObject* result;
00739 
00740     tmp.Append ( this );
00741     result = tmp.Add ( addend );
00742 
00743     return result;
00744 }
00745 
00760 CASObject*
00761 LongInt::Subtract ( const CASObject* sub ) const {
00762     checkptr ( sub );
00763 
00764     if ( GetType() == sub->GetType() ) {
00765         const LongInt *li_ptr = dynamic_cast<const LongInt*> ( sub );
00766 #ifdef DEBUG
00767         assert ( li_ptr != 0 );
00768 #endif
00769         LongInt res;
00770 
00771         res = ( *this ) - ( *li_ptr );
00772         return res.Clone();
00773     }
00774 
00775     Sum tmp;
00776     CASObject *result;
00777 
00778     tmp.Append ( this );
00779     result = tmp.Subtract ( sub );
00780 
00781 
00782     return result;
00783 
00784 }
00785 
00801 CASObject*
00802 LongInt::Multiply ( const CASObject* fact ) const {
00803     checkptr ( fact );
00804 
00805     if ( GetType() < fact->GetType() ) {
00806         return fact->Multiply ( this );
00807     }
00808 
00809     if ( GetType() == fact->GetType() ) {
00810         const LongInt *li_ptr = dynamic_cast<const LongInt*> ( fact );
00811 #ifdef DEBUG
00812         assert ( li_ptr != 0 );
00813 #endif
00814         LongInt res;
00815 
00816         res = ( *this ) * ( *li_ptr );
00817         return res.Clone();
00818     }
00819 
00820     Product *res = new Product;
00821 
00822     // "this" is a coefficient
00823     CASObject *tmp = this->Clone();
00824     tmp->meta.SetCoefficient();
00825     res->Append ( tmp );
00826     res->Append ( fact );
00827     CASObject::Garbage->Put ( tmp );
00828 
00829     return res;
00830 }
00831 
00843 CASObject*
00844 LongInt::Divide ( const CASObject* divisor ) const {
00845     checkptr ( divisor );
00846 
00847     return new Fraction ( this, divisor );
00848 }
00849 
00863 CASObject*
00864 LongInt::Power ( const CASObject* exp ) const {
00865     checkptr ( exp );
00866 
00867     if ( GetType() == exp->GetType() ) {
00868         const LongInt *num_exp = dynamic_cast<const LongInt*> ( exp );
00869 #ifdef DEBUG
00870         assert ( num_exp != 0 );
00871 #endif
00872         LongInt res;
00873         res = Pow ( *num_exp );
00874         return res.Clone();
00875     }
00876 
00877 #ifdef WARNINGS
00878 #warning __FILE__ " " __LINE__ "Cannot exponentiate numeric value with anything other than numeric value"
00879 #endif
00880     std::cout << "Cannot exponentiate ";
00881     Print();
00882     std::cout << " by ";
00883     exp->Print();
00884     std::cout << std::endl;
00885 
00886     throw ENotImplemented();
00887 }
00888 
00900 CASObject*
00901 LongInt::Modulo ( const CASObject* divisor ) const {
00902     checkptr ( divisor );
00903 
00904     if ( GetType() == divisor->GetType() ) {
00905         const LongInt *li_ptr = dynamic_cast<const LongInt*> ( divisor );
00906 #ifdef DEBUG
00907         assert ( li_ptr != 0 );
00908 #endif
00909         LongInt *result = new LongInt;
00910 
00911         *result = ( *this ) % ( *li_ptr );
00912         return result;
00913     }
00914 
00915     return new LongInt ( 0L );
00916 }
00917 
00926 bool
00927 LongInt::IsEqual ( const CASObject* o ) const {
00928     checkptr ( o );
00929 
00930     if ( GetType() != o->GetType() ) {
00931         return false;
00932     }
00933 
00934     const LongInt *li_ptr = dynamic_cast<const LongInt*> ( o );
00935 #ifdef DEBUG
00936     assert ( li_ptr != 0 );
00937 #endif
00938     return ( *this ) == ( *li_ptr );
00939 
00940 }
00941 
00951 bool
00952 LongInt::IsLT ( const CASObject* o ) const {
00953     checkptr ( o );
00954 
00955     if ( GetType() < o->GetType() ) {
00956         return true;
00957     }
00958 
00959     if ( GetType() > o->GetType() ) {
00960         return false;
00961     }
00962 
00963     const LongInt *li = dynamic_cast<const LongInt *> ( o );
00964 
00965 #ifdef DEBUG
00966     assert ( li != 0 );
00967 #endif
00968 
00969     return ( *this ) < ( *li );
00970 }
00971 
00981 bool
00982 LongInt::IsGT ( const CASObject* o ) const {
00983     checkptr ( o );
00984 
00985     if ( IsEqual ( o ) ) {
00986         return false;
00987     }
00988 
00989     return !IsLT ( o );
00990 }
00991 
01003 bool
01004 LongInt::IsSimilar ( const CASObject* o ) const {
01005     checkptr ( o );
01006 
01007     if ( GetType() == o->GetType() ) {
01008         return true;
01009     }
01010 
01011     return false;
01012 }
01013 
01023 CASObject*
01024 LongInt::Evaluate() const {
01025     CASObject *ret_val = Clone();
01026 
01027     ret_val->Sort();
01028     ret_val->meta.SetEvaluated();
01029 
01030     return ret_val;
01031 }
01032 
01033 // ----------------------------------------------------------------------------
01034 
01035 // Operators
01036 // ----------------------------------------------------------------------------
01037 
01045 LongInt&
01046 LongInt::operator= ( const LongInt &r ) {
01047 #ifdef SHOWCONSTRUCTOR
01048     std::cerr << "# LongInt::operator=()" << std::endl;
01049 #endif
01050     if ( this == &r ) {
01051         return *this;
01052     }
01053     SetSign ( r.GetSign() );
01054     SetDivDepth ( r.GetDivDepth() );
01055     SetRadix ( r.GetRadix() );
01056     lst.clear();
01057     lst = r.lst;
01058 
01059     if ( r.div_remainder != 0 ) {
01060         CASObject::Garbage->Put ( div_remainder );
01061         div_remainder = 0;
01062     }
01063 
01064 #ifdef DEBUG
01065     assert ( div_remainder == 0 );
01066 #endif
01067 
01068     if ( r.div_remainder != 0 ) {
01069         div_remainder = new LongInt ( 0L );
01070         div_remainder->lst = r.div_remainder->lst;
01071         div_remainder->SetSign ( r.div_remainder->GetSign() );;
01072     }
01073 
01074     meta = r.meta;
01075 
01076     return *this;
01077 }
01078 
01086 LongInt&
01087 LongInt::operator= ( const signed long &r ) {
01088     if ( r == 0 ) {
01089         setzero();
01090     }
01091     else {
01092         num2longint ( r );
01093     }
01094 
01095     SetRadix ( ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
01096 
01097     if ( div_remainder != 0 ) {
01098         CASObject::Garbage->Put ( div_remainder );
01099         div_remainder = 0;
01100     }
01101 
01102     meta.SetAll();
01103 
01104     return *this;
01105 }
01106 
01114 LongInt&
01115 LongInt::operator+= ( const LongInt &r ) {
01116     return ( *this = *this + r );
01117 }
01118 
01126 LongInt&
01127 LongInt::operator+= ( const signed long &r ) {
01128     return operator+= ( LongInt ( r ) );
01129 }
01130 
01138 LongInt&
01139 LongInt::operator-= ( const LongInt &r )  {
01140     return ( *this = *this - r );
01141 }
01142 
01150 LongInt&
01151 LongInt::operator-= ( const signed long &r ) {
01152     return operator-= ( LongInt ( r ) );
01153 }
01154 
01162 LongInt&
01163 LongInt::operator*= ( const LongInt &r ) {
01164     return ( *this = *this * r );
01165 }
01166 
01174 LongInt&
01175 LongInt::operator*= ( const signed long &r ) {
01176     return operator*= ( LongInt ( r ) );
01177 }
01178 
01186 LongInt&
01187 LongInt::operator/= ( const LongInt &r ) {
01188     return ( *this = *this / r );
01189 }
01190 
01198 LongInt&
01199 LongInt::operator/= ( const signed long &r ) {
01200     return operator/= ( LongInt ( r ) );
01201 }
01202 
01210 LongInt&
01211 LongInt::operator%= ( const LongInt &r ) {
01212     return ( *this = *this % r );
01213 }
01214 
01222 LongInt&
01223 LongInt::operator%= ( const signed long &r ) {
01224     return operator%= ( LongInt ( r ) );
01225 }
01226 
01234 const LongInt
01235 LongInt::operator+ ( const LongInt &r ) const {
01236     if ( r.IsZero() ) {
01237         return *this;
01238     }
01239 
01240     if ( IsNegative() && r.IsPositive() ) {
01241         LongInt tmp = *this;
01242         tmp.SetPositive();
01243         return r -tmp;
01244     }
01245 
01246     if ( IsPositive() && r.IsNegative() ) {
01247         LongInt tmp = r;
01248         tmp.SetPositive();
01249         return ( *this ) - tmp;
01250     }
01251     std::list<unsigned int> sum;
01252 
01253     unsigned long max_iter = r.lst.size() > lst.size() ? r.lst.size() : lst.size();
01254     std::list<unsigned int>::const_iterator i_addend1 = lst.end();
01255     i_addend1--;
01256     std::list<unsigned int>::const_iterator i_addend2 = r.lst.end();
01257     i_addend2--;
01258 
01259     unsigned int addend1 = *i_addend1;
01260     unsigned int addend2 = *i_addend2;
01261     unsigned int remainder = 0;
01262 
01263     for ( unsigned long i = 0; i < max_iter; i++ ) {
01264 
01265         unsigned int res = addend1 + addend2 + remainder;
01266         if ( res >= GetRadix() ) {
01267             res -= GetRadix();
01268             remainder = 1;
01269         }
01270         else {
01271             remainder = 0;
01272         }
01273 
01274         sum.push_front ( res );
01275 
01276         if ( i_addend1 != lst.begin() ) {
01277             i_addend1--;
01278             addend1 = *i_addend1;
01279         }
01280         else {
01281             addend1 = 0;
01282         }
01283 
01284         if ( i_addend2 != r.lst.begin() ) {
01285             i_addend2--;
01286             addend2 = *i_addend2;
01287         }
01288         else {
01289             addend2 = 0;
01290         }
01291 
01292     }
01293 
01294     // Flush remainder
01295     if ( remainder != 0 ) {
01296         sum.push_front ( remainder );
01297     }
01298 
01299     LongInt ret_val;
01300     ret_val.lst = sum;
01301     ret_val.SetSign ( GetSign() );
01302 
01303     ret_val.stripzeros();
01304     return ret_val;
01305 }
01306 
01314 const LongInt
01315 LongInt::operator+ ( const long &r ) const {
01316     return operator+ ( LongInt ( r ) );
01317 }
01318 
01326 const LongInt
01327 LongInt::operator* ( const LongInt &r ) const {
01328 
01329     if ( IsZero() || r.IsZero() ) {
01330         return LongInt ( 0L );
01331     }
01332 
01333     LongInt result ( 0L );
01334     LongInt tmp ( 0L );
01335     unsigned int prod;
01336     unsigned int modulo;
01337 
01338 
01339     std::list<unsigned int>::const_iterator fact2 = r.lst.end();
01340     fact2--;
01341 
01342     for ( unsigned long outer_l = 0; outer_l < r.lst.size(); outer_l++ ) {
01343 
01344         std::list<unsigned int>::const_iterator fact1 = lst.end();
01345         fact1--;
01346 
01347         unsigned int carry = 0;
01348         for ( unsigned long inner_l = 0; inner_l < lst.size(); inner_l++ ) {
01349             prod = ( ( *fact1 ) * ( *fact2 ) ) + carry;
01350             carry = ( unsigned int ) prod / GetRadix();
01351             modulo = prod % GetRadix();
01352             tmp = modulo;
01353             tmp = tmp << outer_l;
01354             tmp = tmp << inner_l;
01355             result = result + tmp;
01356             fact1--;
01357         }
01358 
01359         // flush carry
01360         if ( carry != 0 ) {
01361             tmp = carry;
01362             tmp = tmp << outer_l;
01363             tmp = tmp << lst.size();
01364 
01365             result = result + tmp;
01366         }
01367         fact2--;
01368     }
01369 
01370     // Compute sign
01371     result.SetSign ( ( r.IsNegative() ^ IsNegative() ? Negative : Positive ) );
01372 
01373     result.stripzeros();
01374 
01375     return result;
01376 }
01377 
01386 const LongInt
01387 LongInt::operator* ( const long &r ) const {
01388     return operator* ( LongInt ( r ) );
01389 }
01390 
01398 const LongInt
01399 LongInt::operator- ( const LongInt &r ) const {
01400     if ( r.IsZero() ) {
01401         return *this;
01402     }
01403 
01404     if ( IsNegative() && r.IsPositive() ) {
01405         LongInt lh = *this;
01406         lh.SetPositive();
01407         LongInt res = r + lh;
01408         res.SetNegative();
01409         return res;
01410     }
01411 
01412     if ( r.IsNegative() ) {
01413         LongInt tmp = r;
01414         tmp.SetPositive();
01415         return ( *this ) + tmp;
01416     }
01417 
01418     // Find out whether or not
01419     // the result is still positive.
01420     // If it will become negative, a
01421     // slightly other algorithm is used.
01422     bool stays_pos;
01423     if ( *this < r ) {
01424         stays_pos = false;
01425     } else {
01426         stays_pos = true;
01427     }
01428 
01429     std::list<unsigned int> sum;
01430 
01431     unsigned long max_iter = r.lst.size() > lst.size() ? r.lst.size() : lst.size();
01432     std::list<unsigned int>::const_iterator i_minuend =
01433         ( stays_pos ? lst.end() : r.lst.end() );
01434     i_minuend--;
01435     std::list<unsigned int>::const_iterator i_subtrahend =
01436         ( stays_pos ? r.lst.end() : lst.end() );
01437     i_subtrahend--;
01438 
01439     unsigned int minuend = *i_minuend;
01440     unsigned int subtrahend = *i_subtrahend;
01441     int remainder = 0;
01442 
01443     for ( unsigned long i = 0; i < max_iter; i++ ) {
01444 
01445         int res = minuend - ( subtrahend + remainder );
01446         if ( res < 0 ) {
01447             remainder = 1;
01448             res = GetRadix() + res;
01449 
01450         }
01451         else {
01452             remainder = 0;
01453         }
01454 
01455         sum.push_front ( ( unsigned int ) res );
01456 
01457         if ( i_minuend != ( stays_pos ? lst.begin() : r.lst.begin() ) ) {
01458             i_minuend--;
01459             minuend = *i_minuend;
01460         }
01461         else {
01462             minuend = 0;
01463         }
01464 
01465         if ( i_subtrahend != ( stays_pos ? r.lst.begin() : lst.begin() ) ) {
01466             i_subtrahend--;
01467             subtrahend = *i_subtrahend;
01468         }
01469         else {
01470             subtrahend = 0;
01471         }
01472 
01473     }
01474 
01475     LongInt ret_val;
01476     ret_val.lst = sum;
01477     ret_val.SetPositive();
01478     ret_val.stripzeros();
01479     if ( !stays_pos && !ret_val.IsZero() ) {
01480         ret_val.SetNegative();
01481     }
01482     return ret_val;
01483 
01484 }
01485 
01494 const LongInt
01495 LongInt::operator- ( const long &r ) const {
01496     return operator- ( LongInt ( r ) );
01497 }
01498 
01506 const LongInt
01507 LongInt::operator/ ( const LongInt &r ) const {
01508     LongInt u = ( *this );
01509     u.AbsoluteIP();
01510     LongInt v = r;
01511     v.AbsoluteIP();
01512 
01513     // Result is a dummy on which we manipulate the internal
01514     // structures directly
01515     LongInt result ( 0L );
01516 
01517     if ( v.IsZero() ) {
01518         throw EDivByZero();
01519     }
01520 
01521     if ( u < v ) {
01522         result.div_remainder = new LongInt;
01523         result.div_remainder->lst = lst;
01524         result.div_remainder->SetSign ( GetSign() );
01525         return result;
01526     }
01527 
01528     if ( u == v ) {
01529         result = 1;
01530         result.div_remainder = new LongInt;
01531         return result;
01532     }
01533 
01534     if ( v == 1 ) {
01535         // Return *this, because it still has the sign properly set!
01536         result = *this;
01537         result.div_remainder = new LongInt;
01538         return result;
01539     }
01540 
01541     // Clear the internal list of the result
01542     result.lst.clear();
01543 
01544     // This will hold the part we divide by v
01545     LongInt part_dividend;
01546     part_dividend.lst.clear();
01547 
01548     std::list<unsigned int>::const_iterator dividend = u.lst.begin();
01549 
01550     while ( dividend != u.lst.end() ) {
01551 
01552         part_dividend.lst.push_back ( *dividend );
01553         part_dividend.stripzeros();
01554 
01555         // Sum is used to hold the sum of sum = sum + v, which is used
01556         // find v|part_dividend
01557         LongInt sum ( 0L );
01558 
01559         unsigned int t = 0;
01560 
01561         while ( sum < part_dividend ) {
01562             sum += v;
01563             t++;
01564         }
01565 
01566         // Check if we have counted one too much
01567         if ( sum > part_dividend ) {
01568             t--;
01569         }
01570 
01571 #ifdef DEBUG
01572         assert ( t < ( unsigned long ) pow ( ( ( double ) 10 ), part_len ) );
01573 #endif
01574 
01575         result.lst.push_back ( t );
01576 
01577         part_dividend -= ( v * t );
01578         dividend++;
01579     }
01580 
01581     // Compute Sign
01582     result.SetSign ( ( r.IsNegative() ^ IsNegative() ? Negative : Positive ) );
01583     result.stripzeros();
01584 
01585 #ifdef DEBUG
01586     assert ( result.div_remainder == 0 );
01587 #endif
01588 
01589     result.div_remainder = new LongInt ( 0L );
01590     result.div_remainder->lst = part_dividend.lst;
01591     result.div_remainder->SetSign ( part_dividend.GetSign() );
01592 
01593     return result;
01594 
01595 }
01596 
01605 const LongInt
01606 LongInt::operator/ ( const long &r ) const {
01607     return operator/ ( LongInt ( r ) );
01608 }
01609 
01622 const LongInt
01623 LongInt::operator% ( const LongInt &r ) const {
01624 #ifdef WARNINGS
01625 #warning "LongInt::operator%(): Not fully implemented"
01626 #endif
01627     LongInt result = *this / r;
01628     LongInt modulo = * ( result.div_remainder );
01629 
01630     if ( r < 0L && *this > 0L ) {
01631         modulo += r;
01632         return modulo;
01633     }
01634 
01635     if ( r > 0L && *this < 0L ) {
01636         modulo -= r;
01637         modulo.InvertIP();
01638         return modulo;
01639     }
01640 
01641     if ( r < 0L && *this < 0L ) {
01642         modulo.InvertIP();
01643         return modulo;
01644     }
01645 
01646     return modulo;
01647 }
01648 
01657 const LongInt
01658 LongInt::operator% ( const long &r ) const {
01659     return operator% ( LongInt ( r ) );
01660 }
01661 
01670 const bool
01671 LongInt::operator== ( const LongInt &r ) const {
01672     if ( Length() != r.Length() ) {
01673         return false;
01674     }
01675 
01676     if ( IsNegative() != r.IsNegative() ) {
01677         return false;
01678     }
01679 
01680     if ( lst.size() != r.lst.size() ) {
01681         return false;
01682     }
01683 
01684     std::list<unsigned int>::const_iterator it1 = lst.begin();
01685     std::list<unsigned int>::const_iterator it2 = r.lst.begin();
01686 
01687     while ( it1 != lst.end() ) {
01688         if ( *it1 != *it2 ) {
01689             return false;
01690         }
01691 
01692         it1++;
01693         it2++;
01694     }
01695 
01696     return true;
01697 }
01698 
01707 const bool
01708 LongInt::operator== ( const long &r ) const {
01709     return operator== ( LongInt ( r ) );
01710 }
01711 
01721 const bool
01722 LongInt::operator!= ( const LongInt &r ) const {
01723     return ! ( *this == r );
01724 }
01725 
01734 const bool
01735 LongInt::operator!= ( const long &r ) const {
01736     return ! ( *this == LongInt ( r ) );
01737 }
01738 
01748 const bool
01749 LongInt::operator< ( const LongInt &r ) const {
01750     if ( *this == r ) {
01751         return false;
01752     }
01753 
01754     if ( IsNegative() && r.IsPositive() ) {
01755         return true;
01756     }
01757 
01758     if ( IsPositive() && r.IsNegative() ) {
01759         return false;
01760     }
01761 
01762     if ( lst.size() < r.lst.size() ) {
01763         return ( IsNegative() ? false : true );
01764     }
01765 
01766     if ( lst.size() > r.lst.size() ) {
01767         return ( IsNegative() ? true : false );
01768     }
01769 
01770     std::list<unsigned int>::const_iterator it1 = lst.begin();
01771     std::list<unsigned int>::const_iterator it2 = r.lst.begin();
01772 
01773     while ( it1 != lst.end() ) {
01774         if ( *it1 != *it2 ) {
01775             if ( *it1 < *it2 ) {
01776                 return ( IsNegative() ? false : true );
01777             }
01778             else {
01779                 return ( IsNegative() ? true : false );
01780             }
01781         }
01782 
01783         it1++;
01784         it2++;
01785     }
01786     throw EInternal();
01787 }
01788 
01798 const bool
01799 LongInt::operator< ( const long &r ) const {
01800     return operator< ( LongInt ( r ) );
01801 }
01802 
01812 const bool
01813 LongInt::operator> ( const LongInt &r ) const {
01814     if ( *this == r ) {
01815         return false;
01816     }
01817 
01818     if ( IsNegative() && r.IsPositive() ) {
01819         return false;
01820     }
01821 
01822     if ( IsPositive() && r.IsNegative() ) {
01823         return true;
01824     }
01825 
01826     if ( lst.size() > r.lst.size() ) {
01827         return ( IsNegative() ? false : true );
01828     }
01829 
01830     if ( lst.size() < r.lst.size() ) {
01831         return ( IsNegative() ? true : false );
01832     }
01833 
01834     std::list<unsigned int>::const_iterator it1 = lst.begin();
01835     std::list<unsigned int>::const_iterator it2 = r.lst.begin();
01836 
01837     while ( it1 != lst.end() ) {
01838         if ( *it1 != *it2 ) {
01839             if ( *it1 > *it2 ) {
01840                 return ( IsNegative() ? false : true );
01841             }
01842             else {
01843                 return ( IsNegative() ? true : false );
01844             }
01845         }
01846 
01847         it1++;
01848         it2++;
01849     }
01850     throw EInternal();
01851 }
01852 
01862 const bool
01863 LongInt::operator> ( const long &r ) const {
01864     return operator> ( LongInt ( r ) );
01865 }
01866 
01876 const bool
01877 LongInt::operator>= ( const LongInt &r ) const {
01878     if ( *this == r ) {
01879         return true;
01880     }
01881 
01882     if ( *this > r ) {
01883         return true;
01884     }
01885 
01886     return false;
01887 }
01888 
01898 const bool
01899 LongInt::operator>= ( const long &r ) const {
01900     return operator>= ( LongInt ( r ) );
01901 }
01902 
01912 const bool
01913 LongInt::operator<= ( const LongInt &r ) const {
01914     if ( *this == r ) {
01915         return true;
01916     }
01917 
01918     if ( *this < r ) {
01919         return true;
01920     }
01921 
01922     return false;
01923 }
01924 
01934 const bool
01935 LongInt::operator<= ( const long &r ) const {
01936     return operator<= ( LongInt ( r ) );
01937 }
01938 
01947 const LongInt
01948 LongInt::operator<< ( const signed long &r ) const {
01949     if ( r < 0 ) {
01950         return *this;
01951     }
01952 
01953     LongInt tmp = *this;
01954     for ( signed long l = 0; l < r; l++ ) {
01955         tmp.lst.push_back ( 0 );
01956     }
01957 
01958     tmp.stripzeros();
01959     return tmp;
01960 }
01961 
01967 const LongInt
01968 LongInt::operator++() {
01969     return ( *this ) = operator+ ( 1 );
01970 }
01971 
01977 const LongInt
01978 LongInt::operator++ ( int ) {
01979     LongInt before = *this;
01980     ( *this ) = operator+ ( 1 );
01981 
01982     return before;
01983 }
01984 
01990 const LongInt
01991 LongInt::operator--()  {
01992     return ( *this ) = operator- ( 1 );
01993 }
01994 
02000 const LongInt
02001 LongInt::operator-- ( int ) {
02002     LongInt before = *this;
02003     ( *this ) = operator- ( 1 );
02004 
02005     return before;
02006 }
02007 
02008 // ----------------------------------------------------------------------------
02009 

Generated on Sun Dec 31 01:57:27 2006 for ECAS by  doxygen 1.4.7