fraction.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: fraction.cc,v 1.11 2006/12/31 00:49:39 rafi Exp $
00020 //
00021 
00030 #include <string>
00031 #include <iostream>
00032 #include <cstring>
00033 
00034 #ifdef DEBUG
00035 #include <cassert>
00036 #endif
00037 
00038 #include "casobject.h"
00039 #include "casexception.h"
00040 #include "fraction.h"
00041 #include "longint.h"
00042 
00050 // Private methods
00051 // ----------------------------------------------------------------------------
00052 
00053 // ----------------------------------------------------------------------------
00054 
00055 
00056 // Protected methods
00057 // ----------------------------------------------------------------------------
00058 
00059 // ----------------------------------------------------------------------------
00060 
00061 
00062 // Constructors & Destructor
00063 // ----------------------------------------------------------------------------
00068 Fraction::Fraction() {
00069 #ifdef SHOWCONSTRUCTOR
00070     std::cerr << "# Fraction::Fraction()" << std::endl;
00071 #endif
00072 
00073     LongInt tmp ( 1L );
00074     numerator = tmp.Clone();
00075     denominator = tmp.Clone();
00076 }
00077 
00085 Fraction::Fraction ( const CASObject* num, const CASObject* denom ) {
00086 #ifdef SHOWCONSTRUCTOR
00087     std::cerr << "# Fraction::Fraction(const CASObject* num, const CASObject* denom)" << std::endl;
00088 #endif
00089 
00090     checkptr ( num );
00091     checkptr ( denom );
00092 
00093     if ( denom->IsZero() ) {
00094         throw EDivByZero();
00095     }
00096 
00097     numerator = num->Clone();
00098     denominator = denom->Clone();
00099 }
00100 
00108 Fraction::Fraction ( const CASObject* denom ) {
00109 #ifdef SHOWCONSTRUCTOR
00110     std::cerr << "# Fraction::Fraction(const CASObject* denom)" << std::endl;
00111 #endif
00112 
00113     checkptr ( denom );
00114 
00115     if ( denom->IsZero() ) {
00116         throw EDivByZero();
00117     }
00118 
00119     LongInt t ( 1L );
00120     numerator = t.Clone();
00121     denominator = denominator->Clone();
00122 }
00123 
00129 Fraction::Fraction ( const Fraction &f ) {
00130 #ifdef SHOWCONSTRUCTOR
00131     std::cerr << "# Fraction::Fraction(const Fraction &f)" << std::endl;
00132 #endif
00133 
00134     numerator = f.numerator->Clone();
00135     denominator = f.denominator->Clone();
00136     meta = f.meta;
00137 }
00138 
00143 Fraction::~Fraction() {
00144 #ifdef SHOWCONSTRUCTOR
00145     std::cerr << "# Fraction::~Fraction()" << std::endl;
00146 #endif
00147 #ifdef DEBUG
00148     assert ( numerator != 0 );
00149     assert ( denominator != 0 );
00150 #endif
00151     delete numerator;
00152     delete denominator;
00153 }
00154 // ----------------------------------------------------------------------------
00155 
00156 
00157 // Public Methods
00158 // ----------------------------------------------------------------------------
00167 CASObject*
00168 Fraction::Clone() const {
00169     Fraction *ret_val = new Fraction;
00170 #ifdef DEBUG
00171     assert ( ret_val->numerator != 0 );
00172     assert ( ret_val->denominator != 0 );
00173 #endif
00174 
00175     CASObject::Garbage->Put ( ret_val->numerator );
00176     CASObject::Garbage->Put ( ret_val->denominator );
00177 
00178     ret_val->numerator = numerator->Clone();
00179     ret_val->denominator = denominator->Clone();
00180 
00181     ret_val->meta = meta;
00182 
00183     return ret_val;
00184 }
00185 
00195 void
00196 Fraction::Get ( std::string &s ) const {
00197     if ( IsOne() ) {
00198         s = "1";
00199         return;
00200     }
00201 
00202     if ( IsZero() ) {
00203         s = "0";
00204         return;
00205     }
00206 
00207     s = "(";
00208 
00209     std::string tmp;
00210     numerator->Get ( tmp );
00211     s += tmp;
00212 
00213     s += "/";
00214 
00215     denominator->Get ( tmp );
00216     s += tmp;
00217 
00218     s += ")";
00219 
00220 }
00221 
00235 void
00236 Fraction::Get ( char *s, unsigned long size ) const {
00237     checkptr ( s );
00238 
00239     if ( size < ( Length() + 1 ) ) {
00240         throw EBufTooSmall();
00241     }
00242 
00243     memset ( s, '\0', size );
00244 
00245 
00246     std::string tmp;
00247     Get ( tmp );
00248 
00249     strncpy ( s, tmp.c_str(), size );
00250 }
00251 
00257 void
00258 Fraction::Print() const {
00259     std::string tmp;
00260     Get ( tmp );
00261     std::cout << tmp;
00262 }
00263 
00273 unsigned long
00274 Fraction::Length() const {
00275     if ( IsZero() || IsOne() ) {
00276         return 1;
00277     }
00278 
00279     unsigned long len = 0;
00280     len += numerator->Length();
00281     len += denominator->Length();
00282     // Because the string representation puts the fraction in (X/X), we add 3,
00283     // one for '(', one for '/', and one for ')'
00284     len += 3;
00285     return len;
00286 }
00287 
00294 bool
00295 Fraction::IsZero() const {
00296     return numerator->IsZero();
00297 }
00298 
00305 bool
00306 Fraction::IsOne() const {
00307     return numerator->IsEqual ( denominator );
00308 }
00309 
00320 CASObject*
00321 Fraction::Absolute() const {
00322     Fraction res;
00323     res = *this;
00324     res.numerator->AbsoluteIP();
00325     res.denominator->AbsoluteIP();
00326 
00327     return res.Clone();
00328 }
00329 
00336 void
00337 Fraction::AbsoluteIP() {
00338     numerator->AbsoluteIP();
00339     denominator->AbsoluteIP();
00340 }
00341 
00354 CASObject*
00355 Fraction::Invert() const {
00356 #ifdef WARNINGS
00357 #warning "Not Implemented: Fraction::Invert() const"
00358 #endif
00359     throw ENotImplemented();
00360 }
00361 
00371 void
00372 Fraction::InvertIP() {
00373 #ifdef WARNINGS
00374 #warning "Not Implemented: Fraction::InvertIP()"
00375 #endif
00376     throw ENotImplemented();
00377 }
00378 
00396 CASObject*
00397 Fraction::Add ( const CASObject* addend ) const {
00398     checkptr ( addend );
00399 
00400     // Prepare the resulting fraction
00401     Fraction *result = new Fraction;
00402     CASObject::Garbage->Put ( result->numerator );
00403     CASObject::Garbage->Put ( result->denominator );
00404 
00405     if ( GetType() == addend->GetType() ) {
00406         const Fraction *fr_ptr = dynamic_cast<const Fraction*> ( addend );
00407 #ifdef DEBUG
00408         assert ( fr_ptr != 0 );
00409 #endif
00410 
00411         result->denominator = denominator->Multiply ( fr_ptr->denominator );
00412 
00413         CASObject* num1 = numerator->Multiply ( fr_ptr->denominator );
00414         CASObject* num2 = fr_ptr->numerator->Multiply ( denominator );
00415         result->numerator = num1->Add ( num2 );
00416 
00417         CASObject::Garbage->Put ( num1 );
00418         CASObject::Garbage->Put ( num2 );
00419 
00420         return result;
00421     }
00422 
00423     CASObject* num = denominator->Multiply ( addend );
00424     result->numerator = numerator->Add ( num );
00425     result->denominator = denominator->Clone();
00426 
00427     return result;
00428 
00429 }
00430 
00448 CASObject*
00449 Fraction::Subtract ( const CASObject* subtrahend ) const {
00450     checkptr ( subtrahend );
00451 
00452     // Prepare the resulting fraction
00453     Fraction *result = new Fraction;
00454 
00455     CASObject::Garbage->Put ( result->numerator );
00456     CASObject::Garbage->Put ( result->denominator );
00457 
00458     if ( GetType() == subtrahend->GetType() ) {
00459         const Fraction *fr_ptr = dynamic_cast<const Fraction*> ( subtrahend );
00460 #ifdef DEBUG
00461         assert ( fr_ptr != 0 );
00462 #endif
00463 
00464         result->denominator = denominator->Multiply ( fr_ptr->denominator );
00465 
00466         CASObject* num1 = numerator->Multiply ( fr_ptr->denominator );
00467         CASObject* num2 = fr_ptr->numerator->Multiply ( denominator );
00468         result->numerator = num1->Subtract ( num2 );
00469 
00470         CASObject::Garbage->Put ( num1 );
00471         CASObject::Garbage->Put ( num2 );
00472 
00473         return result;
00474     }
00475 
00476     CASObject* num = denominator->Multiply ( subtrahend );
00477     result->numerator = numerator->Subtract ( num );
00478     result->denominator = denominator->Clone();
00479 
00480     return result;
00481 }
00482 
00498 CASObject*
00499 Fraction::Multiply ( const CASObject* factor ) const {
00500     checkptr ( factor );
00501 
00502     // Prepare the resulting fraction
00503     Fraction *result = new Fraction;
00504 
00505     CASObject::Garbage->Put ( result->numerator );
00506     CASObject::Garbage->Put ( result->denominator );
00507 
00508     if ( GetType() == factor->GetType() ) {
00509         const Fraction *fr_ptr = dynamic_cast<const Fraction*> ( factor );
00510 #ifdef DEBUG
00511 
00512         assert ( fr_ptr != 0 );
00513 #endif
00514 
00515         result->denominator = denominator->Multiply ( fr_ptr->denominator );
00516         result->numerator = numerator->Multiply ( fr_ptr->numerator );
00517 
00518         return result;
00519     }
00520 
00521 
00522     result->numerator = numerator->Multiply ( factor );
00523     result->denominator = denominator->Clone();
00524 
00525     return result;
00526 }
00527 
00538 CASObject*
00539 Fraction::Divide ( const CASObject* divisor ) const {
00540     checkptr ( divisor );
00541 
00542     // Prepare the resulting fraction
00543     Fraction *result = new Fraction;
00544 
00545     CASObject::Garbage->Put ( result->numerator );
00546     CASObject::Garbage->Put ( result->denominator );
00547 
00548     if ( GetType() == divisor->GetType() ) {
00549         const Fraction *fr_ptr = dynamic_cast<const Fraction*> ( divisor );
00550 #ifdef DEBUG
00551 
00552         assert ( fr_ptr != 0 );
00553 #endif
00554 
00555         result->denominator = denominator->Multiply ( fr_ptr->numerator );
00556         result->numerator = numerator->Multiply ( fr_ptr->denominator );
00557 
00558         return result;
00559     }
00560 
00561 
00562     result->numerator = numerator->Clone();
00563     result->denominator = denominator->Multiply ( divisor );
00564 
00565     return result;
00566 
00567 }
00568 
00582 CASObject*
00583 Fraction::Power ( const CASObject* exp ) const {
00584     checkptr ( exp );
00585 
00586     Fraction *result = new Fraction;
00587 
00588     CASObject::Garbage->Put ( result->numerator );
00589     CASObject::Garbage->Put ( result->denominator );
00590 
00591     result->numerator = numerator->Power ( exp );
00592     result->denominator = denominator->Power ( exp );
00593 
00594     return result;
00595 
00596 }
00597 
00612 CASObject*
00613 Fraction::Modulo ( const CASObject* divisor ) const {
00614 #ifdef WARNINGS
00615 #warning "Not fully implemented: Fraction::Modulo(const CASObject*) const "
00616 #endif
00617     LongInt *result = new LongInt ( 0L );
00618     return result;
00619 }
00620 
00634 CASObject*
00635 Fraction::GCD ( const CASObject* o ) const {
00636 #ifdef WARNINGS
00637 #warning "Not fully implemented: Fraction::GCD(const CASObject*) const"
00638 #endif
00639     LongInt *result = new LongInt ( 1L );
00640     return result;
00641 }
00642 
00658 bool
00659 Fraction::IsEqual ( const CASObject* o ) const {
00660 #ifdef WARNINGS
00661 #warning "Not fully implemented: Fraction::IsEqual(const CASObject*) const"
00662 #endif
00663     checkptr ( o );
00664 
00665     if ( GetType() == o->GetType() ) {
00666         const Fraction *fr_ptr = dynamic_cast<const Fraction*> ( o );
00667 #ifdef DEBUG
00668 
00669         assert ( fr_ptr != 0 );
00670 #endif
00671 
00672         return ( *this ) == ( *fr_ptr );
00673     }
00674     else {
00675         return false;
00676     }
00677 }
00678 
00689 bool
00690 Fraction::IsLT ( const CASObject* o ) const {
00691     checkptr ( o );
00692 
00693     if ( GetType() < o->GetType() ) {
00694         return true;
00695     }
00696 
00697     if ( GetType() > o->GetType() ) {
00698         return false;
00699     }
00700 
00701     const Fraction *f = dynamic_cast<const Fraction*> ( o );
00702 #ifdef DEBUG
00703     assert ( o != 0 );
00704 #endif
00705 
00706     if ( denominator->IsLT ( f->denominator ) ) {
00707         return false;
00708     }
00709 
00710     if ( denominator->IsGT ( f->denominator ) ) {
00711         return true;
00712     }
00713 
00714     return numerator->IsLT ( f->numerator );
00715 }
00716 
00727 bool
00728 Fraction::IsGT ( const CASObject* o ) const {
00729     checkptr ( o );
00730     if ( IsEqual ( o ) ) {
00731         return false;
00732     }
00733 
00734     return !IsLT ( o );
00735 }
00736 
00752 bool
00753 Fraction::IsSimilar ( const CASObject *o ) const {
00754     checkptr ( o );
00755 
00756     if ( GetType() != o->GetType() ) {
00757         return false;
00758     }
00759 
00760     const Fraction *fr = dynamic_cast<const Fraction*> ( o );
00761 #ifdef DEBUG
00762     assert ( fr != 0 );
00763 #endif
00764 
00765     return ( fr->numerator->IsSimilar ( numerator ) &&
00766              fr->denominator->IsSimilar ( denominator ) );
00767 }
00768 
00777 CASObject*
00778 Fraction::SortWeight() const {
00779     CASObject* weightnumerator = numerator->SortWeight();
00780     CASObject* weightdenominator = denominator->SortWeight();
00781     CASObject* weight = weightnumerator->Divide ( weightdenominator );
00782     CASObject::Garbage->Put ( weightnumerator );
00783     CASObject::Garbage->Put ( weightdenominator );
00784 
00785     return weight;
00786 }
00787 
00793 void
00794 Fraction::Sort()  {
00795     if ( meta.IsSorted() ) {
00796         return;
00797     }
00798     checkptr ( numerator );
00799     checkptr ( denominator );
00800     numerator->Sort();
00801     denominator->Sort();
00802     meta.SetSorted();
00803 }
00804 
00818 CASObject*
00819 Fraction::Evaluate() const {
00820     if ( meta.IsEvaluated() ) {
00821         return Clone();
00822     }
00823     Fraction *ret_val = dynamic_cast<Fraction*> ( Clone() );
00824 #ifdef DEBUG
00825 
00826     assert ( ret_val != 0 );
00827 #endif
00828 
00829     CASObject* denom = ret_val->denominator;
00830     CASObject* num = ret_val->numerator;
00831 
00832     ret_val->denominator = ret_val->denominator->Evaluate();
00833     ret_val->numerator = ret_val->numerator->Evaluate();
00834 
00835     CASObject::Garbage->Put ( denom );
00836     CASObject::Garbage->Put ( num );
00837 
00838     ret_val->meta.SetEvaluated();
00839     ret_val->Sort();
00840 
00841     return ret_val;
00842 }
00843 
00851 inline bool Fraction::IsPureNumerical() const {
00852     return numerator->IsPureNumerical() && denominator->IsPureNumerical();
00853 }
00854 
00855 // ----------------------------------------------------------------------------
00856 
00857 // Operators
00858 // ----------------------------------------------------------------------------
00864 const Fraction&
00865 Fraction::operator= ( const Fraction &f ) {
00866 #ifdef SHOWCONSTRUCTOR
00867     std::cerr << "# Fraction::operator=(const Fraction &f)" << std::endl;
00868 #endif
00869 
00870     if ( this == &f ) {
00871         return *this;
00872     }
00873 
00874 #ifdef DEBUG
00875     assert ( numerator != 0 );
00876     assert ( denominator != 0 );
00877 #endif
00878 
00879     CASObject::Garbage->Put ( numerator );
00880     CASObject::Garbage->Put ( denominator );
00881 
00882     numerator = f.numerator->Clone();
00883     denominator = f.denominator->Clone();
00884     meta = f.meta;
00885 
00886     return *this;
00887 }
00888 
00899 const bool
00900 Fraction::operator== ( const Fraction &f ) const {
00901 #ifdef WARNINGS
00902 #warning "Not fully implemented: Fraction::operator==(const Fraction &f)"
00903 #endif
00904 #ifdef DEBUG
00905     assert ( numerator != 0 );
00906     assert ( denominator != 0 );
00907 #endif
00908 
00909     return numerator->IsEqual ( f.numerator ) && denominator->IsEqual ( f.denominator );
00910 }
00911 // ----------------------------------------------------------------------------
00912 

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