sum.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: sum.cc,v 1.18 2006/12/31 00:49:39 rafi Exp $
00020 //
00021 
00031 #include <iostream>
00032 #include <iterator>
00033 #include <vector>
00034 
00035 #ifdef DEBUG
00036 #include <cassert>
00037 #endif
00038 
00039 #include "casfuncobj.h"
00040 #include "casexception.h"
00041 #include "castemplates.h"
00042 #include "sum.h"
00043 #include "product.h"
00044 #include "fraction.h"
00045 #include "longint.h"
00046 
00054 // Private methods
00055 // ----------------------------------------------------------------------------
00074 CASObject*
00075 Sum::CollectEqualOperands() const {
00076     Sum *working_obj = dynamic_cast<Sum*> ( Clone() );
00077 
00078     bool exprmodified;
00079     do {
00080         exprmodified = false;
00081         resolve_parentheses<Sum> ( working_obj );
00082         working_obj->Sort();
00083 #ifdef DEBUG
00084         assert ( working_obj != 0 );
00085 #endif
00086         std::vector<CASObject*>::const_iterator op_it = working_obj->operands.begin();
00087         std::vector<CASObject*>::const_iterator op_begin = op_it;
00088         std::vector<CASObject*>::const_iterator op_it_next = op_it;
00089         // Get the iterator for the next object
00090         op_it_next++;
00091         std::vector<CASObject*>::const_iterator op_end = working_obj->operands.end();
00092 
00093         // Holds the equal objects
00094         std::vector<CASObject*> equal_objs;
00095 
00096         // Temporary vector, which is later appended to the existing one
00097         std::vector<CASObject*> new_operands;
00098         while ( op_it != op_end && op_it_next != op_end ) {
00099             while ( op_it != op_end &&
00100                     op_it_next != op_end &&
00101                     ( *op_it )->IsEqual ( *op_it_next ) ) {
00102                 equal_objs.push_back ( *op_it );
00103                 equal_objs.push_back ( *op_it_next );
00104 
00105                 op_it++;
00106                 op_it_next++;
00107             }
00108 
00109             // Now replace the found objects, if any
00110             if ( equal_objs.size() > 0 ) {
00111                 exprmodified = true;
00112 
00113                 // The above method for searching same operands yields duplicate results
00114                 // thus we have to unique'ing the equal_obj vector.
00115                 // CASGarbageSort_Cmp() is used because it sorts by memory address
00116                 std::sort ( equal_objs.begin(), equal_objs.end(), CASGarbageSort_Cmp() );
00117 
00118                 std::vector<CASObject*>::iterator ip =
00119                     std::unique ( equal_objs.begin(), equal_objs.end() );
00120 
00121                 equal_objs.erase ( ip, equal_objs.end() );
00122 
00123                 LongInt coefficient ( equal_objs.size() );
00124                 coefficient.meta.SetCoefficient();
00125                 CASObject *product = coefficient.Multiply ( ( equal_objs.front() ) );
00126 
00127                 new_operands.push_back ( product );
00128 
00129                 // Now, destroy the equal operands, and zero 'em out
00130                 std::vector<CASObject*>::const_iterator eqo_it = equal_objs.begin();
00131                 while ( eqo_it != equal_objs.end() ) {
00132                     // find the operand in the operand vector, so we can set it to
00133                     // zero
00134                     CASObjectFindByAddr needle ( *eqo_it );
00135                     std::vector<CASObject*>::iterator pos =
00136                         std::find_if ( working_obj->operands.begin(),
00137                                        working_obj->operands.end(),
00138                                        needle );
00139 #ifdef DEBUG
00140                     assert ( pos != op_end );
00141                     assert ( *pos != 0 );
00142 #endif
00143                     *pos = 0;
00144                     CASObject::Garbage->Put ( *eqo_it );
00145                     eqo_it++;
00146                 }
00147                 // Finally, clear the list for the next iteration
00148                 equal_objs.clear();
00149             } else {
00150                 exprmodified = false;
00151             }
00152 
00153             op_it++;
00154             op_it_next++;
00155         }
00156 
00157         if ( new_operands.size() > 0 ) {
00158             // Remove the elements zero'ed out above and shrink
00159             // the vector.
00160             std::vector<CASObject*>::iterator last =
00161                 std::remove ( working_obj->operands.begin(),
00162                                   working_obj->operands.end(),
00163                                   ( ( CASObject* ) 0 ) );
00164             working_obj->operands.erase ( last, working_obj->operands.end() );
00165 
00166             std::copy ( new_operands.begin(),
00167                         new_operands.end(),
00168                         std::back_inserter ( working_obj->operands ) );
00169             working_obj->meta.UnsetSorted();
00170             working_obj->Sort();
00171         }
00172     } while ( exprmodified );
00173 
00174     return working_obj;
00175 }
00176 
00195 CASObject* Sum::CollectSingleValues() const {
00196     std::vector<const CASObject*> this_singleval;
00197     std::vector<const CASObject*> this_nonsingleval;
00198     GetSingleValues ( this_singleval );
00199     GetNonSingleValues ( this_nonsingleval );
00200 
00201     std::vector<CASObject*> working_singleval;
00202     std::vector<CASObject*> working_nonsingleval;
00203 
00204     // Necessary because Get(Non)SingleValues() return vectors holding the
00205     // pointers to the operands of this object.
00206     std::transform ( this_singleval.begin(),
00207                      this_singleval.end(),
00208                      std::back_inserter ( working_singleval ),
00209                      CASCloneObject() );
00210 
00211     std::transform ( this_nonsingleval.begin(),
00212                      this_nonsingleval.end(),
00213                      std::back_inserter ( working_nonsingleval ),
00214                      CASCloneObject() );
00215 
00216     // Try to assign the single values to other objects, e.g. collect them.
00217     std::vector<CASObject *>::iterator singleval_it = working_singleval.begin();
00218     while ( singleval_it != working_singleval.end() ) {
00219         std::vector<CASObject*>::iterator nonsingleval_it =
00220             working_nonsingleval.begin();
00221         while ( nonsingleval_it != working_nonsingleval.end() ) {
00222             CASTerm *term = dynamic_cast<CASTerm*> ( ( *nonsingleval_it ) );
00223             if ( term != 0 ) {
00224                 if ( term->IsSimilar ( ( *singleval_it ) ) ) {
00225                     CASObject *result = term->Add ( ( *singleval_it ) );
00226                     CASObject::Garbage->Put ( term );
00227                     ( *nonsingleval_it ) = result;
00228                     CASObject::Garbage->Put ( ( *singleval_it ) );
00229                     // Clear this out
00230                     ( *singleval_it ) = 0;
00231                     break;
00232                 }
00233             }
00234             nonsingleval_it++;
00235         }
00236         singleval_it++;
00237     }
00238 
00239     // From here on compose the Sum
00240     Sum *Collected_Sum = new Sum;
00241 #ifdef DEBUG
00242     assert ( Collected_Sum->exponent != 0 );
00243 #endif
00244     CASObject::Garbage->Put ( Collected_Sum->exponent );
00245     Collected_Sum->exponent = exponent->Clone();
00246 
00247     std::vector<CASObject*>::iterator last =
00248         std::remove ( working_singleval.begin(),
00249                           working_singleval.end(),
00250                           ( CASObject* ) 0 );
00251 
00252     working_singleval.erase ( last, working_singleval.end() );
00253 
00254     std::copy ( working_singleval.begin(),
00255                 working_singleval.end(),
00256                 std::back_inserter ( Collected_Sum->operands ) );
00257 
00258     std::copy ( working_nonsingleval.begin(),
00259                 working_nonsingleval.end(),
00260                 std::back_inserter ( Collected_Sum->operands ) );
00261 
00262     Collected_Sum->meta.UnsetSorted();
00263     Collected_Sum->Sort();
00264 
00265     return Collected_Sum;
00266 }
00267 
00286 CASObject* Sum::CollectNonSingleValues() const {
00287     std::vector<const CASObject*> this_singleval;
00288     std::vector<const CASObject*> this_nonsingleval;
00289 
00290     // We get both, becaus we need to concatenate them later on, but we barely
00291     // touch the single values
00292     GetSingleValues ( this_singleval );
00293     GetNonSingleValues ( this_nonsingleval );
00294 
00295     std::vector<CASObject*> working_singleval;
00296     std::vector<CASObject*> working_nonsingleval;
00297 
00298     // Necessary because Get(Non)SingleValues() return vectors holding the
00299     // pointers to the operands of this object.
00300     std::transform ( this_singleval.begin(),
00301                      this_singleval.end(),
00302                      std::back_inserter ( working_singleval ),
00303                      CASCloneObject() );
00304 
00305     std::transform ( this_nonsingleval.begin(),
00306                      this_nonsingleval.end(),
00307                      std::back_inserter ( working_nonsingleval ),
00308                      CASCloneObject() );
00309 
00310     std::vector<CASObject*>::iterator it = working_nonsingleval.begin();
00311     std::vector<CASObject*>::iterator secondary_it;
00312     while ( it != working_nonsingleval.end() ) {
00313         secondary_it = it;
00314         secondary_it++;
00315 
00316         CASTerm *term_a = dynamic_cast<CASTerm*> ( *it );
00317         while ( secondary_it != working_nonsingleval.end() &&  term_a != 0 ) {
00318             CASTerm *term_b = dynamic_cast<CASTerm*> ( *secondary_it );
00319             if ( term_b == 0 ) {
00320                 break;
00321             }
00322 
00323             if ( term_a->IsSimilar ( term_b ) ) {
00324                 CASObject *result = term_a->Add ( term_b );
00325                 CASObject::Garbage->Put ( *it );
00326                 *it = 0;
00327                 CASObject::Garbage->Put ( *secondary_it );
00328                 *secondary_it = result;
00329                 break;
00330             }
00331             secondary_it++;
00332         }
00333 
00334         it++;
00335     }
00336 
00337     // From here on compose the Sum
00338     Sum *Collected_Sum = new Sum;
00339 #ifdef DEBUG
00340     assert ( Collected_Sum->exponent != 0 );
00341 #endif
00342     CASObject::Garbage->Put ( Collected_Sum->exponent );
00343     Collected_Sum->exponent = exponent->Clone();
00344 
00345     std::vector<CASObject*>::iterator last =
00346         std::remove ( working_nonsingleval.begin(),
00347                           working_nonsingleval.end(),
00348                           ( CASObject* ) 0 );
00349 
00350     working_nonsingleval.erase ( last, working_nonsingleval.end() );
00351 
00352     std::copy ( working_singleval.begin(),
00353                 working_singleval.end(),
00354                 std::back_inserter ( Collected_Sum->operands ) );
00355 
00356     std::copy ( working_nonsingleval.begin(),
00357                 working_nonsingleval.end(),
00358                 std::back_inserter ( Collected_Sum->operands ) );
00359     Collected_Sum->meta.UnsetSorted();
00360     Collected_Sum->Sort();
00361 
00362     return Collected_Sum;
00363 }
00364 
00372 Sum*
00373 Sum::WithExponentOne() const {
00374     Sum *res = dynamic_cast<Sum*> ( Clone() );
00375 #ifdef DEBUG
00376     assert ( res != 0 );
00377     assert ( res->exponent != 0 );
00378 #endif
00379     CASObject::Garbage->Put ( res->exponent );
00380     LongInt one ( 1 );
00381     res->exponent = one.Clone();
00382     return res;
00383 }
00384 
00385 // ----------------------------------------------------------------------------
00386 
00387 
00388 // Protected methods
00389 // ----------------------------------------------------------------------------
00390 // ----------------------------------------------------------------------------
00391 
00392 
00393 // Constructors & Destructor
00394 // ----------------------------------------------------------------------------
00399 Sum::Sum() : CASTerm() {
00400 #ifdef SHOWCONSTRUCTOR
00401     std::cout << "# Sum::Sum()" << std::endl;
00402 #endif
00403     LongInt one ( 1L );
00404     exponent = one.Clone();
00405 }
00406 
00412 Sum::Sum ( const Sum &s ) {
00413 #ifdef SHOWCONSTRUCTOR
00414     std::cout << "# Sum::Sum(const Sum &f)" << std::endl;
00415 #endif
00416     std::transform ( s.operands.begin(),
00417                      s.operands.end(),
00418                      std::back_inserter ( operands ),
00419                      CASCloneObject() );
00420 
00421     meta = s.meta;
00422     exponent = s.exponent->Clone();
00423 }
00424 
00429 Sum::~Sum() {
00430 #ifdef SHOWCONSTRUCTOR
00431     std::cout << "# Sum::~Sum()" << std::endl;
00432 #endif
00433 #ifdef DEBUG
00434     assert ( exponent != 0 );
00435 #endif
00436     delete exponent;
00437 }
00438 
00439 // ----------------------------------------------------------------------------
00440 
00441 
00442 // Public Methods
00443 // ----------------------------------------------------------------------------
00451 CASObject*
00452 Sum::Clone() const {
00453     Sum *tmp = new Sum;
00454     *tmp = *this;
00455     return tmp;
00456 }
00457 
00466 void
00467 Sum::Get ( std::string &s ) const {
00468     s.erase();
00469     std::string tmp;
00470 
00471 #ifdef DEBUG
00472     s = "{";
00473 #endif
00474 
00475     if ( !exponent->IsOne() ) {
00476 #ifdef DEBUG
00477         s += "(";
00478 #else
00479         s = "(";
00480 #endif
00481     }
00482 
00483     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00484 #ifdef DEBUG
00485         assert ( operands[i] != 0 );
00486 #endif
00487         if ( i > 0 ) {
00488             s += "+";
00489         }
00490         operands[i]->Get ( tmp );
00491         s += tmp;
00492     }
00493 
00494     if ( !exponent->IsOne() ) {
00495         exponent->Get ( tmp );
00496         if ( !exponent->meta.IsSingleValue() ) {
00497             s += ")^(" + tmp + ")";
00498         } else {
00499             s += ")^" + tmp;
00500         }
00501     }
00502 
00503 #ifdef DEBUG
00504     s += "}";
00505 #endif
00506 }
00507 
00522 void
00523 Sum::Get ( char *s, unsigned long size ) const {
00524     checkptr ( s );
00525 
00526     if ( size < ( Length() + 1 ) ) {
00527         throw EBufTooSmall();
00528     }
00529 
00530     memset ( s, '\0', size );
00531 
00532     std::string tmp;
00533     Get ( tmp );
00534 
00535     strncpy ( s, tmp.c_str(), size );
00536 }
00537 
00543 void
00544 Sum::Print() const {
00545     std::string tmp;
00546     Get ( tmp );
00547     std::cout << tmp;
00548 }
00549 
00556 unsigned long
00557 Sum::Length() const {
00558     unsigned long len = 0;
00559 
00560     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00561 #ifdef DEBUG
00562         assert ( operands[i] != 0 );
00563 #endif
00564         len += operands[i]->Length();
00565     }
00566 
00567     // Add the size of the operators '+'
00568     len += operands.size() - 1;
00569 
00570     return len;
00571 }
00572 
00579 bool
00580 Sum::IsZero() const {
00581     if ( operands.size() == 0 )
00582         return true;
00583 
00584     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00585 #ifdef DEBUG
00586         assert ( operands[i] != 0 );
00587 #endif
00588         if ( !operands[i]->IsZero() ) {
00589             return false;
00590         }
00591     }
00592 
00593     return true;
00594 }
00595 
00605 bool
00606 Sum::IsOne() const {
00607 #ifdef WARNINGS
00608 #warning "Not fully Implemented: bool Sum::IsOne() const"
00609 #endif
00610     return false;
00611 }
00612 
00622 bool
00623 Sum::IsSimilar ( const CASObject *o ) const {
00624     checkptr ( o );
00625 
00626     if ( IsEqual ( o ) ) {
00627         return true;
00628     }
00629 
00630     return HaveSameOperands ( o );
00631 }
00632 
00643 CASObject*
00644 Sum::Absolute() const {
00645     Sum *tmp = new Sum;
00646     *tmp = *this;
00647 
00648     std::for_each ( tmp->operands.begin(),
00649                     tmp->operands.end(),
00650                     CASAbsoluteObjectIP() );
00651 
00652     return tmp;
00653 }
00654 
00661 void
00662 Sum::AbsoluteIP() {
00663     std::for_each ( operands.begin(), operands.end(), CASAbsoluteObjectIP() );
00664     meta.UnsetAll();
00665 }
00666 
00676 CASObject*
00677 Sum::Invert() const {
00678     Sum *tmp = new Sum;
00679     *tmp = *this;
00680 
00681     std::for_each ( tmp->operands.begin(),
00682                     tmp->operands.end(),
00683                     CASInvertObjectIP() );
00684 
00685     return tmp;
00686 }
00687 
00694 void
00695 Sum::InvertIP() {
00696     std::for_each ( operands.begin(), operands.end(), CASInvertObjectIP() );
00697     meta.UnsetAll();
00698 }
00699 
00721 CASObject*
00722 Sum::Add ( const CASObject* addend ) const {
00723     checkptr ( addend );
00724 
00725     if ( addend->GetType() == GetType() ) {
00726         // We have to add two sums, so, if they are equal, we form a
00727         // product with the coefficient '2', else we simply put them
00728         // together in a new sum.
00729         const Sum *addend_sum = dynamic_cast<const Sum*> ( addend );
00730 #ifdef DEBUG
00731         assert ( addend_sum != 0 );
00732 #endif
00733         if ( IsEqual ( addend_sum ) ) {
00734             Product *result = new Product;
00735             LongInt two ( 2L );
00736             result->Append ( &two );
00737             result->Append ( this );
00738             result->Sort();
00739             return result;
00740         }
00741 
00742         // Default return result
00743         Sum *result = new Sum;
00744         result->Append ( addend_sum );
00745         result->Append ( this );
00746         result->Sort();
00747         return result;
00748 
00749     } else {
00750         // Since we are here, we do not deal with a sum as
00751         // addend. Therefore, we first have to make sure the exponent
00752         // is one ('1'). If the exponent is not one, we simply put
00753         // them together in a new sum.  If the exponent is one, we
00754         // seek for an operand of the same type as the addend, and, if
00755         // one exists, we add them and replace the original item in
00756         // this->operands with the result.
00757         Sum *new_sum = new Sum;
00758         *new_sum = *this;
00759         if ( exponent->IsOne() ) {
00760             // Is there already an item of that type?
00761             std::vector<CASObject*>::iterator si = find_if ( new_sum->operands.begin(),
00762                                                    new_sum->operands.end(),
00763                                                    CASTypeFinder_EQ ( addend ) );
00764 
00765             if ( si != new_sum->operands.end() ) {
00766                 // Compute the sum
00767                 CASObject *result = ( *si )->Add ( addend );
00768                 // Free the memory occupied by the existing item
00769                 CASObject::Garbage->Put ( *si );
00770                 // Remove the item from the vector
00771                 new_sum->operands.erase ( si );
00772                 // Add the result
00773                 new_sum->operands.push_back ( result );
00774                 new_sum->Sort();
00775                 return new_sum;
00776             }
00777         }
00778         new_sum->Append ( addend );
00779         new_sum->Sort();
00780         return new_sum;
00781     }
00782 
00783     return 0L;
00784 }
00785 
00805 CASObject*
00806 Sum::Subtract ( const CASObject* subtrahend ) const {
00807     checkptr ( subtrahend );
00808 
00809     Sum *NewSum = new Sum;
00810     *NewSum = *this;
00811 
00812     if ( subtrahend->GetType() == GetType() ) {
00813         const Sum *subtrahend_sum = dynamic_cast<const Sum*> ( subtrahend );
00814 #ifdef DEBUG
00815         assert ( subtrahend_sum != 0 );
00816 #endif
00817         std::transform ( subtrahend_sum->operands.begin(),
00818                          subtrahend_sum->operands.end(),
00819                          std::back_inserter ( NewSum->operands ),
00820                          CASInvertObject() );
00821     } else {
00822         // Is there already an item of that type?
00823         std::vector<CASObject*>::iterator si =
00824             find_if ( NewSum->operands.begin(),
00825                       NewSum->operands.end(),
00826                       CASTypeFinder_EQ ( subtrahend ) );
00827 
00828         if ( si != NewSum->operands.end() ) {
00829             // Compute the difference
00830             CASObject *result = ( *si )->Subtract ( subtrahend );
00831             // Free the memory occupied by the existing item
00832             CASObject::Garbage->Put ( *si );
00833             // Remove the item from the vector
00834             NewSum->operands.erase ( si );
00835             // Add the result
00836             NewSum->operands.push_back ( result );
00837         } else {
00838             NewSum->operands.push_back ( subtrahend->Invert() );
00839         }
00840     }
00841 
00842     NewSum->Sort();
00843     return NewSum;
00844 }
00845 
00859 CASObject*
00860 Sum::Multiply ( const CASObject* factor ) const {
00861     checkptr ( factor );
00862 
00863     if ( GetType() == factor->GetType() ) {
00864         const Sum *sum = dynamic_cast<const Sum*> ( factor );
00865 #ifdef DEBUG
00866         assert ( sum != 0 );
00867 #endif
00868         if ( HaveSameOperands ( sum ) ) {
00869             Sum *result = new Sum;
00870             *result = *this;
00871             CASObject::Garbage->Put ( result->exponent );
00872             result->exponent = exponent->Add ( sum->exponent );
00873             result->Sort();
00874             return result;
00875         }
00876     }
00877 
00878     Product *result = new Product;
00879     result->Append ( this );
00880     result->Append ( factor );
00881     result->Sort();
00882     return result;
00883 }
00884 
00896 CASObject*
00897 Sum::Divide ( const CASObject* divisor ) const {
00898     checkptr ( divisor );
00899 
00900     return  new Fraction ( this, divisor );
00901 }
00902 
00917 CASObject*
00918 Sum::Modulo ( const CASObject* divisor ) const {
00919 #ifdef WARNINGS
00920 #warning "Not fully implemented: Sum::Modulo(const CASObject* divisor) const"
00921 #endif
00922     checkptr ( divisor );
00923 
00924     return new LongInt ( 0L );
00925 }
00926 
00942 CASObject*
00943 Sum::GCD ( const CASObject* o ) const{
00944 #ifdef WARNINGS
00945 #warning "Not fully implemented: Sum::GCD(const CASObject* o) const"
00946 #endif
00947     checkptr ( o );
00948 
00949     return new LongInt ( 1L );
00950 }
00951 
00970 CASObject*
00971 Sum::Evaluate() const {
00972     if ( meta.IsEvaluated() ) {
00973         return Clone();
00974     }
00975 #ifdef DEBUG2
00976     std::cout << ">>> Begin evaluation of ";
00977     Print();
00978     std::cout << std::endl;
00979 #endif
00980     Sum* tmp = dynamic_cast<Sum*> ( Clone() );
00981 #ifdef DEBUG
00982     assert ( tmp != 0 );
00983 #endif
00984     tmp->UnsetAllEvaluated();
00985     resolve_parentheses<Sum> ( tmp );
00986     evaluate_operands<Sum> ( tmp );
00987 
00988     CASObject* result = tmp->Collect();
00989     CASObject::Garbage->Put ( tmp );
00990 
00991     result->meta.SetEvaluated();
00992     CASTerm *term = dynamic_cast<CASTerm*> ( result );
00993     if ( term != 0 ) {
00994         term->RemoveNoOpElements();
00995         if ( term->IsZero() ) {
00996             CASObject::Garbage->Put ( result );
00997             LongInt r ( 0L );
00998             return r.Clone();
00999         }
01000         term->SetAllEvaluated();
01001     }
01002 
01003     if ( result->IsOne() ) {
01004         CASObject::Garbage->Put ( result );
01005         LongInt r ( 1L );
01006         return r.Clone();
01007     }
01008 
01009     if ( result->IsZero() ) {
01010         CASObject::Garbage->Put ( result );
01011         LongInt r ( 0L );
01012         return r.Clone();
01013     }
01014 
01015 #ifdef DEBUG2
01016     std::cout << ">>> End evaluation of ";
01017     Print();
01018     std::cout << std::endl;
01019 #endif
01020 
01021     return result;
01022 }
01023 
01036 CASObject *
01037 Sum::Collect() const {
01038     Sum *sum = dynamic_cast<Sum*> ( Clone() );
01039     CASObject* tmp = sum->CollectEqualOperands();
01040 #ifdef DEBUG
01041     checkptr ( tmp );
01042 #endif
01043     CASObject::Garbage->Put ( sum );
01044 
01045     sum = dynamic_cast<Sum*> ( tmp );
01046     // By collecting, it has become another type
01047     if ( sum == 0 ) {
01048         return tmp;
01049     }
01050 
01051 #ifdef DEBUG2
01052     std::cout << "Going to collect Single Values in " << std::endl;
01053     sum->Print();
01054     std::cout << std::endl;
01055 #endif
01056     tmp = sum->CollectSingleValues();
01057     CASObject::Garbage->Put ( sum );
01058 
01059     sum = dynamic_cast<Sum*> ( tmp );
01060     // By collecting, it has become another type
01061     if ( sum == 0 ) {
01062         return tmp;
01063     }
01064 
01065     CASObject *result = sum->CollectNonSingleValues();
01066     CASObject::Garbage->Put ( tmp );
01067 
01068     return result;
01069 }
01070 
01097 CASObject*
01098 Sum::Expand() const {
01099     if ( !meta.IsEvaluated() ) {
01100         throw EEvaluateFirst();
01101     }
01102 
01103     CASObject *clone = Clone();
01104 
01105     Sum* wrking = dynamic_cast<Sum*> ( clone );
01106 #ifdef DEBUG
01107     assert ( wrking != 0 );
01108 #endif
01109 
01110     if ( wrking->exponent->GetType() == CT_LONGINT &&
01111             !wrking->exponent->IsOne() ) {
01112         LongInt const *li_exp = dynamic_cast<LongInt*> ( wrking->exponent );
01113         Sum *wo_exponent = wrking->WithExponentOne();
01114         // We assume that it is evaluated, because *this object is.
01115         wo_exponent->meta.SetEvaluated();
01116 
01117         resolve_parentheses<Sum> ( wo_exponent );
01118         Product* prod = new Product;
01119 #ifdef DEBUG
01120         assert ( prod->NumOperands() == 0 );
01121 #endif
01122         for ( LongInt i ( 0L );i < ( *li_exp );i++ ) {
01123             prod->Append ( wo_exponent );
01124         }
01125 
01126         CASObject::Garbage->Put ( wo_exponent );
01127         CASObject::Garbage->Put ( wrking );
01128 
01129         resolve_parentheses<Product> ( prod );
01130 
01131         // Same as obove, assuming it is evaluated...
01132         // btw. leave it here, because Product::Append()
01133         // and resolve_parentheses() change that flag.
01134         prod->meta.SetEvaluated();
01135 
01136         CASObject* res = prod->Expand();
01137 
01138         CASObject::Garbage->Put ( prod );
01139         return res;
01140     } else {
01141         return clone;
01142     }
01143 }
01144 
01152 void
01153 Sum::RemoveNoOpElements() {
01154     std::vector<CASObject*>::iterator it = operands.begin();
01155     while ( it != operands.end() ) {
01156         if ( ( *it )->IsZero() ) {
01157             CASObject::Garbage->Put ( *it );
01158             it = operands.erase ( it );
01159         } else {
01160             CASTerm *term = dynamic_cast<CASTerm*> ( *it );
01161             if ( term != 0 ) {
01162                 term->RemoveNoOpElements();
01163             }
01164             it++;
01165         }
01166         // Iterator already incremented... no need for it++
01167     }
01168 }
01169 
01170 // ----------------------------------------------------------------------------
01171 
01172 // Operators
01173 // ----------------------------------------------------------------------------
01181 const Sum&
01182 Sum::operator= ( const Sum &s ) {
01183 #ifdef SHOWCONSTRUCTOR
01184     std::cout << "# Sum::operator=(const Sum &s)" << std::endl;
01185 #endif
01186     if ( &s == this ) {
01187         return *this;
01188     }
01189 
01190     CASObject::Garbage->Put ( operands );
01191 
01192     operands.clear();
01193 
01194     std::transform ( s.operands.begin(),
01195                      s.operands.end(),
01196                      std::back_inserter ( operands ),
01197                      CASCloneObject() );
01198 
01199     meta = s.meta;
01200     CASObject::Garbage->Put ( exponent );
01201     exponent = s.exponent->Clone();
01202 
01203     return *this;
01204 }
01205 
01206 // ----------------------------------------------------------------------------
01207 

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