product.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: product.cc,v 1.18 2006/12/31 00:49:39 rafi Exp $
00020 //
00021 
00031 #include <iostream>
00032 #include <algorithm>
00033 
00034 #ifdef DEBUG
00035 #include <cassert>
00036 #endif
00037 
00038 #include "casfuncobj.h"
00039 #include "casexception.h"
00040 #include "product.h"
00041 #include "sum.h"
00042 #include "longint.h"
00043 #include "fraction.h"
00044 #include "casconvert.h"
00045 
00053 // Private methods
00054 // ----------------------------------------------------------------------------
00055 
00066 void
00067 Product::GetOperandsWithoutCoefficient ( std::vector<const CASObject*>& lst ) const {
00068     std::transform ( operands.begin(),
00069                      operands.end(),
00070                      std::back_inserter ( lst ),
00071                      CASExtractNonCoefficients() );
00072 
00073     std::vector<const CASObject*>::iterator last =
00074         std::remove ( lst.begin(), lst.end(), ( ( CASObject* ) 0 ) );
00075     lst.erase ( last, lst.end() );
00076 
00077     // Here sort according value and type as expected by the cas methods
00078     std::sort ( lst.begin(), lst.end(), CASSortObject() );
00079 }
00080 
00081 const CASObject* Product::GetCoefficient() const {
00082     CASGetCoefficient coe;
00083     coe = std::for_each ( operands.begin(), operands.end(), coe );
00084     return coe.Result();
00085 }
00086 
00102 CASObject*
00103 Product::CollectEqualOperands() const {
00104     Product *working_obj = dynamic_cast<Product*> ( Clone() );
00105 #ifdef DEBUG2
00106     std::cout << "Product::CollectEqualOperands()" << std::endl;
00107     Print();
00108     std::cout << std::endl;
00109 #endif
00110     bool exprmodified;
00111     do {
00112         exprmodified = false;
00113         resolve_parentheses<Product> ( working_obj );
00114         working_obj->Sort();
00115 #ifdef DEBUG
00116         assert ( working_obj != 0 );
00117 #endif
00118 
00119         std::vector<CASObject*>::const_iterator op_it = working_obj->operands.begin();
00120         std::vector<CASObject*>::const_iterator op_begin = op_it;
00121         std::vector<CASObject*>::const_iterator op_it_next = op_it;
00122         std::vector<CASObject*>::const_iterator op_end = working_obj->operands.end();
00123 
00124         // Get the iterator for the next object
00125         op_it_next++;
00126 
00127         // Holds the equal objects
00128         std::vector<CASObject*> equal_objs;
00129 
00130         // Temporary vector, which is later appended to the existing
00131         // one
00132         std::vector<CASObject*> new_operands;
00133         while ( op_it != op_end && op_it_next != op_end ) {
00134             while ( op_it != op_end &&
00135                     op_it_next != op_end &&
00136                     ( *op_it )->IsEqual ( *op_it_next ) ) {
00137                 equal_objs.push_back ( *op_it );
00138                 equal_objs.push_back ( *op_it_next );
00139 
00140                 op_it++;
00141                 op_it_next++;
00142             }
00143 
00144             // Now replace the found objects, if any
00145             if ( equal_objs.size() > 0 ) {
00146                 exprmodified = true;
00147 
00148                 // The above method for searching same operands yields
00149                 // duplicate results thus we have to unique'ing the
00150                 // equal_obj vector.  CASGarbageSort_Cmp() is used
00151                 // because it sorts by memory address
00152                 std::sort ( equal_objs.begin(), equal_objs.end(), CASGarbageSort_Cmp() );
00153 
00154                 std::vector<CASObject*>::iterator ip =
00155                     std::unique ( equal_objs.begin(), equal_objs.end() );
00156 
00157                 equal_objs.erase ( ip, equal_objs.end() );
00158 
00159                 LongInt li_exponent ( equal_objs.size() );
00160                 CASObject *res =
00161                     ( equal_objs.front() )->Power ( &li_exponent );
00162 
00163                 new_operands.push_back ( res );
00164 
00165                 // Now, destroy the equal operands, and zero 'em out
00166                 std::vector<CASObject*>::const_iterator eqo_it = equal_objs.begin();
00167                 while ( eqo_it != equal_objs.end() ) {
00168                     // find the operand in the operand vector, so we
00169                     // can set it to zero
00170                     CASObjectFindByAddr needle ( *eqo_it );
00171                     std::vector<CASObject*>::iterator pos =
00172                         std::find_if ( working_obj->operands.begin(),
00173                                        working_obj->operands.end(),
00174                                        needle );
00175 #ifdef DEBUG
00176                     assert ( pos != op_end );
00177                     assert ( *pos != 0 );
00178 #endif
00179 
00180                     *pos = 0;
00181                     CASObject::Garbage->Put ( *eqo_it );
00182                     eqo_it++;
00183                 }
00184                 // Finally, clear the list for the next iteration
00185                 equal_objs.clear();
00186             } else {
00187                 exprmodified = false;
00188             }
00189 
00190             op_it++;
00191             op_it_next++;
00192         }
00193 
00194         if ( new_operands.size() > 0 ) {
00195             // Remove the elements zero'ed out above and shrink
00196             // the vector.
00197             std::vector<CASObject*>::iterator last =
00198                 std::remove ( working_obj->operands.begin(),
00199                                   working_obj->operands.end(),
00200                                   ( ( CASObject* ) 0 ) )
00201                     ;
00202             working_obj->operands.erase ( last, working_obj->operands.end() );
00203 
00204             std::copy ( new_operands.begin(),
00205                         new_operands.end(),
00206                         std::back_inserter ( working_obj->operands ) );
00207 
00208             new_operands.clear();
00209 
00210             working_obj->meta.UnsetSorted();
00211             working_obj->Sort();
00212         }
00213     } while ( exprmodified );
00214 
00215     return working_obj;
00216 }
00217 
00230 CASObject*
00231 Product::CollectOther() const {
00232 #ifdef DEBUG2
00233     std::cout << "Product::CollectOther()" << std::endl;
00234     Print();
00235     std::cout << std::endl;
00236 #endif
00237     std::vector<CASObject*> newoperands;
00238     std::transform ( operands.begin(),
00239                      operands.end(),
00240                      back_inserter ( newoperands ),
00241                      CASCloneObject() );
00242 
00243     std::vector<CASObject*>::iterator it = newoperands.begin();
00244     std::vector<CASObject*>::iterator secondary_it;
00245 
00246     while ( it != newoperands.end() ) {
00247         secondary_it = it;
00248         secondary_it++;
00249         while ( secondary_it != newoperands.end() ) {
00250             bool similar = ( *it )->IsSimilar ( ( *secondary_it ) );
00251             if ( similar ) {
00252                 CASObject *tmp = *secondary_it;
00253                 *secondary_it = ( *it )->Multiply ( ( *secondary_it ) );
00254                 CASObject::Garbage->Put ( tmp );
00255                 CASObject::Garbage->Put ( ( *it ) );
00256                 *it = 0;
00257                 break;
00258             }
00259 
00260             secondary_it++;
00261         }
00262 
00263         it++;
00264     }
00265 
00266     it = std::remove ( newoperands.begin(),
00267                            newoperands.end(),
00268                            ( CASObject* ) 0 );
00269     newoperands.erase ( it, newoperands.end() );
00270     Product* result = new Product();
00271 #ifdef DEBUG
00272     assert ( result->exponent != 0 );
00273 #endif
00274     CASObject::Garbage->Put ( result->exponent );
00275     result->exponent = exponent->Clone();
00276     result->operands = newoperands;
00277     result->Sort();
00278 
00279     return result;
00280 
00281 }
00282 
00295 void
00296 Product::ExplodeSumsIP() {
00297     std::vector<CASObject*>::iterator it = operands.begin();
00298     std::vector<CASObject*> exploded_sums;
00299 
00300     while ( it != operands.end() ) {
00301         if ( ( *it )->GetType() == CT_SUM &&
00302                 ( *it )->exponent->GetType() == CT_LONGINT &&
00303                 ! ( *it )->exponent->IsOne() ) {
00304             Sum *sum = dynamic_cast<Sum*> ( *it );
00305             LongInt *li_exp = dynamic_cast<LongInt*> ( sum->exponent );
00306 #ifdef DEBUG
00307             assert ( li_exp != 0 );
00308             assert ( sum != 0 );
00309 #endif
00310             Sum *sum_exp_one = dynamic_cast<Sum*> ( sum->Clone() );
00311 #ifdef DEBUG
00312             assert ( sum_exp_one != 0 );
00313 #endif
00314             CASObject::Garbage->Put ( sum_exp_one->exponent );
00315             LongInt li ( 1L );
00316             sum_exp_one->exponent = li.Clone();
00317             for ( li = 0; li < * ( li_exp ); li++ ) {
00318                 exploded_sums.push_back ( sum_exp_one->Clone() );
00319             }
00320             ( *it ) = 0;
00321 
00322             CASObject::Garbage->Put ( sum );
00323             CASObject::Garbage->Put ( sum_exp_one );
00324         }
00325         it++;
00326     }
00327     std::vector<CASObject*>::iterator remove_it =
00328         std::remove ( operands.begin(),
00329                           operands.end(),
00330                           ( ( CASObject* ) 0 ) );
00331     operands.erase ( remove_it, operands.end() );
00332     std::copy ( exploded_sums.begin(),
00333                 exploded_sums.end(),
00334                 std::back_inserter ( operands )
00335               );
00336     return;
00337 }
00338 
00357 void
00358 Product::GetSums ( const std::vector<const CASObject*> &in,
00359                    std::vector<const CASObject*> &out ) {
00360     for ( unsigned long i = 0; i < in.size(); i++ ) {
00361         if ( in[i]->GetType() == CT_SUM )
00362             out.push_back ( in[i] );
00363     }
00364 }
00365 
00384 void
00385 Product::GetNonSums ( const std::vector<const CASObject*> &in,
00386                       std::vector<const CASObject*> &out ) {
00387     for ( unsigned long i = 0; i < in.size(); i++ ) {
00388         if ( in[i]->GetType() != CT_SUM )
00389             out.push_back ( in[i] );
00390     }
00391 }
00392 // ----------------------------------------------------------------------------
00393 
00394 
00395 
00396 // Protected methods
00397 // ----------------------------------------------------------------------------
00398 
00399 // ----------------------------------------------------------------------------
00400 
00401 // Constructors & Destructor
00402 // ----------------------------------------------------------------------------
00407 Product::Product() : CASTerm() {
00408 #ifdef SHOWCONSTRUCTOR
00409     std::cout << "# Product::Product()" << std::endl;
00410 #endif
00411     LongInt one ( 1L );
00412     exponent = one.Clone();
00413 }
00414 
00419 Product::~Product() {
00420 #ifdef SHOWCONSTRUCTOR
00421     std::cout << "# Product::~Product()" << std::endl;
00422 #endif
00423 #ifdef DEBUG
00424     assert ( exponent != 0 );
00425 #endif
00426     delete exponent;
00427 }
00428 
00434 Product::Product ( const Product &p ) {
00435 #ifdef SHOWCONSTRUCTOR
00436     std::cout << "# Product::Product(const Product &f)" << std::endl;
00437 #endif
00438 
00439     std::transform ( p.operands.begin(),
00440                      p.operands.end(),
00441                      std::back_inserter ( operands ),
00442                      CASCloneObject() );
00443     meta = p.meta;
00444     exponent = p.exponent->Clone();
00445 }
00446 
00447 // ----------------------------------------------------------------------------
00448 
00449 
00450 // Public Methods
00451 // ----------------------------------------------------------------------------
00460 CASObject*
00461 Product::Clone() const {
00462     Product *ret_val = new Product;
00463 
00464     *ret_val = *this;
00465 
00466     return ret_val;
00467 }
00468 
00479 void
00480 Product::Get ( std::string &s ) const {
00481     s.erase();
00482     std::string tmp;
00483 
00484 #ifdef DEBUG
00485     s = "[";
00486 #endif
00487 
00488     if ( !exponent->IsOne() ) {
00489 #ifdef DEBUG
00490         s += "(";
00491 #else
00492         s = "(";
00493 #endif
00494     }
00495 
00496     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00497 #ifdef DEBUG
00498         assert ( operands[i] != 0 );
00499 #endif
00500         if ( i > 0 ) {
00501             s += "*";
00502         }
00503 
00504         if ( operands[i]->GetType() == CT_SUM ) {
00505             s += "(";
00506         }
00507 
00508         operands[i]->Get ( tmp );
00509 
00510         s += tmp;
00511 
00512         if ( operands[i]->GetType() == CT_SUM ) {
00513             s += ")";
00514         }
00515     }
00516 
00517     if ( !exponent->IsOne() ) {
00518         s += ")^";
00519         exponent->Get ( tmp );
00520         if ( !exponent->meta.IsSingleValue() ) {
00521             s += "(" + tmp + ")";
00522         } else {
00523             s += tmp;
00524         }
00525     }
00526 #ifdef DEBUG
00527     s += "]";
00528 #endif
00529 }
00530 
00545 void
00546 Product::Get ( char *s, unsigned long size ) const {
00547     checkptr ( s );
00548 
00549     if ( size < ( Length() + 1 ) ) {
00550         throw EBufTooSmall();
00551     }
00552 
00553     memset ( s, '\0', size );
00554 
00555     std::string tmp;
00556     Get ( tmp );
00557 
00558     strncpy ( s, tmp.c_str(), size );
00559 }
00560 
00566 void
00567 Product::Print() const {
00568     std::string tmp;
00569     Get ( tmp );
00570     std::cout << tmp;
00571 }
00572 
00579 unsigned long
00580 Product::Length() const {
00581     unsigned long len = 0;
00582 
00583     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00584 #ifdef DEBUG
00585         assert ( operands[i] != 0 );
00586 #endif
00587 
00588         len += operands[i]->Length();
00589     }
00590 
00591     // Add the size of the operators '*'
00592     len += operands.size() - 1;
00593 
00594     return len;
00595 }
00596 
00603 bool
00604 Product::IsZero() const {
00605     if ( operands.size() == 0 )
00606         return true;
00607 
00608     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00609 #ifdef DEBUG
00610         assert ( operands[i] != 0 );
00611 #endif
00612 
00613         if ( operands[i]->IsZero() ) {
00614             return true;
00615         }
00616     }
00617 
00618     return false;
00619 }
00620 
00627 bool
00628 Product::IsOne() const {
00629     for ( unsigned long i = 0; i < operands.size(); i++ ) {
00630 #ifdef DEBUG
00631         assert ( operands[i] != 0 );
00632 #endif
00633 
00634         if ( !operands[i]->IsOne() ) {
00635             return false;
00636         }
00637     }
00638 
00639     return true;
00640 
00641 }
00642 
00654 bool
00655 Product::IsSimilar ( const CASObject *o ) const {
00656     checkptr ( o );
00657 #ifdef DEBUG2
00658     std::cout << "Object to search for similarity: ";
00659     o->Print();
00660     std::cout << std::endl;
00661 #endif
00662 
00663     if ( !o->meta.IsSingleValue() && ( GetType() != o->GetType() ) ) {
00664         return false;
00665     }
00666     if ( IsEqual ( o ) ) {
00667         return true;
00668     }
00669 
00670     std::vector<const CASObject*> ops_without_coeff;
00671     GetOperandsWithoutCoefficient ( ops_without_coeff );
00672 #ifdef DEBUG
00673     assert ( ops_without_coeff.size() > 0 );
00674 #endif
00675 
00676     CASConvert convert ( ops_without_coeff );
00677 
00678     Product *tmp_prod;
00679     try {
00680         tmp_prod = convert.ToProduct();
00681     } catch ( EDoesNotApply &e ) {
00682 #ifdef DEBUG2
00683         std::cout << "Catched exception EDoesNotApply()";
00684 #endif
00685         return false;
00686     }
00687 
00688     CASConvert convert_o ( o );
00689     Product* converted_o;
00690     try {
00691         converted_o = convert_o.ToProduct();
00692     } catch ( EDoesNotApply &e ) {
00693 #ifdef DEBUG2
00694         std::cout << "Catched exception EDoesNotApply()";
00695 #endif
00696         CASObject::Garbage->Put ( tmp_prod );
00697         return false;
00698     }
00699 
00700     // Since it is a Product now, we extract only non-coefficients
00701     std::vector<const CASObject*> o_ops_without_coeff;
00702     converted_o->GetOperandsWithoutCoefficient ( o_ops_without_coeff );
00703 
00704     CASConvert non_coeff_conv ( o_ops_without_coeff );
00705     Product* final_o_conversion;
00706     try {
00707         final_o_conversion = non_coeff_conv.ToProduct();
00708     } catch ( EDoesNotApply &e ) {
00709 #ifdef DEBUG2
00710         std::cout << "Catched exception EDoesNotApply()";
00711 #endif
00712         CASObject::Garbage->Put ( tmp_prod );
00713         CASObject::Garbage->Put ( converted_o );
00714         return false;
00715     }
00716 
00717 
00718 
00719     bool ret_val = tmp_prod->IsEqual ( final_o_conversion );
00720     CASObject::Garbage->Put ( final_o_conversion );
00721     CASObject::Garbage->Put ( converted_o );
00722     CASObject::Garbage->Put ( tmp_prod );
00723 
00724     return ret_val;
00725 }
00726 
00737 CASObject*
00738 Product::Absolute() const {
00739     Product *tmp = new Product;
00740     *tmp = *this;
00741 
00742     std::for_each ( tmp->operands.begin(),
00743                     tmp->operands.end(),
00744                     CASAbsoluteObjectIP() );
00745 
00746     return tmp;
00747 }
00748 
00749 
00756 void
00757 Product::AbsoluteIP() {
00758     std::for_each ( operands.begin(), operands.end(), CASAbsoluteObjectIP() );
00759 }
00760 
00770 CASObject*
00771 Product::Invert() const {
00772     Product *tmp = new Product;
00773     *tmp = *this;
00774 
00775     std::for_each ( tmp->operands.begin(),
00776                     tmp->operands.end(),
00777                     CASInvertObjectIP() );
00778 
00779     return tmp;
00780 }
00781 
00788 void
00789 Product::InvertIP() {
00790     std::for_each ( operands.begin(), operands.end(), CASInvertObjectIP() );
00791 }
00792 
00820 CASObject*
00821 Product::Add ( const CASObject* addend ) const {
00822     checkptr ( addend );
00823 
00824     // Retrieve the operands without coefficients from this product.
00825     std::vector<const CASObject*> this_noncoe;
00826     GetOperandsWithoutCoefficient ( this_noncoe );
00827 #if defined(DEBUG)
00828     assert ( this_noncoe.size() > 0 );
00829 #endif
00830     const CASObject *this_coeff = GetCoefficient();
00831 
00832     if ( GetType() == addend->GetType() ) {
00833         const Product *arg_obj = dynamic_cast<const Product*> ( addend );
00834 #if defined(DEBUG)
00835         assert ( arg_obj != 0 );
00836 #endif
00837 
00838         // Retrieve the operands without coefficients from the product
00839         // supplied as argument
00840         std::vector<const CASObject*> arg_noncoe;
00841         arg_obj->GetOperandsWithoutCoefficient ( arg_noncoe );
00842 #if defined(DEBUG)
00843         assert ( arg_noncoe.size() > 0 );
00844 #endif
00845 
00846         bool equal = false;
00847         if ( this_noncoe.size() == arg_noncoe.size() ) {
00848             equal = std::equal ( this_noncoe.begin(),
00849                                  this_noncoe.end(),
00850                                  arg_noncoe.begin(),
00851                                  CASObjectEqual() );
00852         }
00853         // Check if the vectors holding the non-coefficient operands
00854         // are equal, if they are not, simply fall thru the end of the
00855         // method
00856         if ( equal ) {
00857             // Because both products are equal regarding
00858             // non-coefficients we have to compute the new
00859             // coefficient. The non-coefficients are appended to the
00860             // result at the bottom of this scope
00861             Product *result = new Product;
00862 
00863             const CASObject *arg_coeff = arg_obj->GetCoefficient();
00864 #if  defined(DEBUG)
00865             // In debug mode, make sure both objects are pure
00866             // numerical values
00867             if ( this_coeff != 0 ) {
00868                 assert ( this_coeff->IsPureNumerical() );
00869             }
00870             if ( arg_coeff != 0 ) {
00871                 assert ( arg_coeff->IsPureNumerical() );
00872             }
00873 #endif
00874 
00875             // Compute the new coefficient depending on the existing
00876             // coefficients
00877             if ( this_coeff != 0 && arg_coeff != 0 ) {
00878                 CASObject *new_coeff = this_coeff->Add ( arg_coeff );
00879                 result->Append ( new_coeff );
00880                 // The new coefficient is no longer needed, since
00881                 CASObject::Garbage->Put ( new_coeff );
00882             } else {
00883                 // Now we have to find out which coefficient exists,
00884                 // the one from this product, or the one in the
00885                 // product supplied as argument. Worst case, both do
00886                 // not have an coefficient...
00887                 if ( this_coeff == 0 && arg_coeff == 0 ) {
00888                     LongInt new_coeff ( 2L );
00889                     result->Append ( &new_coeff );
00890                 }
00891 
00892                 LongInt one ( 1L );
00893                 CASObject *new_coeff;
00894                 if ( this_coeff != 0 ) {
00895                     new_coeff = this_coeff->Add ( &one );
00896                     result->Append ( new_coeff );
00897                     CASObject::Garbage->Put ( new_coeff );
00898                 }
00899 
00900                 if ( arg_coeff != 0 ) {
00901                     new_coeff = arg_coeff->Add ( &one );
00902                     result->Append ( new_coeff );
00903                     CASObject::Garbage->Put ( new_coeff );
00904                 }
00905             }
00906 
00907 
00908             // Now append the non-coefficients to the result
00909             std::transform ( this_noncoe.begin(), this_noncoe.end(),
00910                              back_inserter ( result->operands ), CASCloneObject() );
00911             return result;
00912         }
00913     } else {
00914         // Here we see if we deal with a single argument
00915         if ( this_noncoe.size() == 1 ) {
00916             if ( addend->IsEqual ( this_noncoe[0] ) ) {
00917                 Product *result = new Product;
00918                 result->Append ( addend );
00919                 if ( this_coeff != 0 ) {
00920                     LongInt one ( 1L );
00921                     CASObject *new_coeff = this_coeff->Add ( &one );
00922                     new_coeff->meta.SetCoefficient();
00923                     result->Append ( new_coeff );
00924                     CASObject::Garbage->Put ( new_coeff );
00925                 } else {
00926                     LongInt two ( 2L );
00927                     two.meta.SetCoefficient();
00928                     result->Append ( &two );
00929                 }
00930                 return result;
00931             }
00932         }
00933         // Simply fall thru
00934     }
00935     Sum *result = new Sum;
00936     result->Append ( this );
00937     result->Append ( addend );
00938 
00939     return result;
00940 }
00941 
00958 CASObject*
00959 Product::Subtract ( const CASObject* subtrahend ) const {
00960     checkptr ( subtrahend );
00961 
00962     Sum *result = new Sum;
00963     result->Append ( this );
00964     CASObject* inv_subtrahend = subtrahend->Invert();
00965     result->Append ( inv_subtrahend );
00966 
00967     CASObject::Garbage->Put ( inv_subtrahend );
00968     return result;
00969 }
00970 
00988 CASObject*
00989 Product::Multiply ( const CASObject* factor ) const {
00990     checkptr ( factor );
00991 
00992     Product *NewProd = new Product;
00993     *NewProd = *this;
00994     NewProd->meta.UnsetSorted();
00995 
00996     if ( GetType() == factor->GetType() ) {
00997 
00998         const Product *pr_ptr = dynamic_cast<const Product *> ( factor );
00999 #ifdef DEBUG
01000         assert ( pr_ptr != 0 );
01001 #endif
01002 
01003         std::transform ( pr_ptr->operands.begin(),
01004                          pr_ptr->operands.end(),
01005                          back_inserter ( NewProd->operands ),
01006                          CASCloneObject() );
01007     } else {
01008         std::vector<CASObject*>::iterator pi = find_if ( NewProd->operands.begin(),
01009                                                NewProd->operands.end(),
01010                                                CASTypeFinder_EQ ( factor ) );
01011 
01012         if ( pi != NewProd->operands.end() ) {
01013             // Compute the product
01014             CASObject *result = ( *pi )->Multiply ( factor );
01015             // Free the memory occupied by the existing item
01016             CASObject::Garbage->Put ( *pi );
01017             // Remove the item from the vector
01018             NewProd->operands.erase ( pi );
01019             // Add the result
01020             if ( result->IsPureNumerical() ) {
01021                 result->meta.SetCoefficient();
01022                 NewProd->operands.push_back ( result );
01023             } else {
01024                 // See if it is of the type Product, so we can incorporate
01025                 // the operands directly into the ones of "result"
01026                 if ( GetType() == result->GetType() ) {
01027                     Product *result_prod = dynamic_cast<Product*> ( result );
01028 #ifdef DEBUG
01029                     assert ( result_prod != 0 );
01030 #endif
01031                     std::copy ( result_prod->operands.begin(),
01032                                 result_prod->operands.end(),
01033                                 back_inserter ( NewProd->operands ) );
01034                 } else {
01035                     NewProd->operands.push_back ( result );
01036                 }
01037             }
01038 
01039         } else {
01040             CASObject *tmp = factor->Clone();
01041             if ( tmp->IsPureNumerical() ) {
01042                 tmp->meta.SetCoefficient();
01043             }
01044             NewProd->operands.push_back ( tmp );
01045         }
01046     }
01047 
01048     return NewProd;
01049 }
01050 
01062 CASObject*
01063 Product::Divide ( const CASObject* divisor ) const {
01064     checkptr ( divisor );
01065 
01066     Fraction *result = new Fraction ( this, divisor );
01067 
01068     return result;
01069 }
01070 
01085 CASObject*
01086 Product::Modulo ( const CASObject* divisor ) const {
01087 #ifdef WARNINGS
01088 #warning "Not fully implemented: Product::Modulo(const CASObject*)"
01089 #endif
01090     checkptr ( divisor );
01091     return new LongInt ( 0L );
01092 }
01093 
01108 CASObject*
01109 Product::GCD ( const CASObject* o ) const {
01110 #ifdef WARNINGS
01111 #warning "Not fully implemented: Product::GCD(const CASObject*) const"
01112 #endif
01113 
01114     checkptr ( o );
01115     return new LongInt ( 1L );
01116 }
01117 
01136 CASObject*
01137 Product::Evaluate() const {
01138     if ( meta.IsEvaluated() ) {
01139         return Clone();
01140     }
01141 
01142 #ifdef DEBUG2
01143     std::cout << ">>> Begin evaluation of ";
01144     Print();
01145     std::cout << std::endl;
01146 #endif
01147 
01148     Product *tmp = dynamic_cast<Product*> ( Clone() );
01149 #ifdef DEBUG
01150     assert ( tmp != 0 );
01151 #endif
01152     tmp->UnsetAllEvaluated();
01153     resolve_parentheses<Product> ( tmp );
01154     evaluate_operands<Product> ( tmp );
01155 
01156     CASObject* result = tmp->Collect();
01157     CASObject::Garbage->Put ( tmp );
01158 
01159     result->meta.SetEvaluated();
01160     CASTerm *term = dynamic_cast<CASTerm*> ( result );
01161     if ( term != 0 ) {
01162         term->RemoveNoOpElements();
01163         if ( term->IsOne() ) {
01164             CASObject::Garbage->Put ( result );
01165             LongInt r ( 1L );
01166             return r.Clone();
01167         }
01168         term->SetAllEvaluated();
01169     }
01170 
01171     if ( result->IsOne() ) {
01172         CASObject::Garbage->Put ( result );
01173         LongInt r ( 1L );
01174         return r.Clone();
01175     }
01176 
01177     if ( result->IsZero() ) {
01178         CASObject::Garbage->Put ( result );
01179         LongInt r ( 0L );
01180         return r.Clone();
01181     }
01182 
01183 #ifdef DEBUG2
01184     std::cout << ">>> End evaluation of ";
01185     Print();
01186     std::cout << std::endl;
01187 #endif
01188 
01189     return result;
01190 }
01191 
01203 CASObject*
01204 Product::Collect() const {
01205     Product *product = dynamic_cast<Product*> ( Clone() );
01206 
01207     CASObject* tmp = product->CollectEqualOperands();
01208 #ifdef DEBUG
01209     checkptr ( tmp );
01210 #endif
01211     CASObject::Garbage->Put ( product );
01212 
01213     product = dynamic_cast<Product*> ( tmp );
01214     if ( product == 0 ) {
01215         return tmp;
01216     }
01217 
01218     tmp = product->CollectOther();
01219     CASObject::Garbage->Put ( product );
01220 
01221     return tmp;
01222 
01223 }
01224 
01255 CASObject*
01256 Product::Expand() const {
01257     if ( !meta.IsEvaluated() ) {
01258         throw EEvaluateFirst();
01259     }
01260     CASObject *clone = Clone();
01261 
01262     Product *wrking = dynamic_cast<Product*> ( clone );
01263 #ifdef DEBUG
01264     assert ( wrking != 0 );
01265 #endif
01266     wrking->ExplodeSumsIP();
01267 
01268     // Preparations
01269     resolve_parentheses<Product> ( wrking );
01270 
01271     std::vector<const CASObject*> non_singleval;
01272     wrking->GetNonSingleValues ( non_singleval );
01273 
01274     std::vector<const CASObject*> sums_only;
01275     std::vector<const CASObject*>::const_iterator sums_only_it;
01276     wrking->GetSums ( non_singleval, sums_only );
01277     if ( sums_only.size() == 0 ) {
01278         CASObject::Garbage->Put ( wrking );
01279         return Clone();
01280     }
01281 
01282     std::vector<const CASObject*> nonsums_only;
01283     std::vector<const CASObject*>::const_iterator nonsums_only_it;
01284     wrking->GetNonSums ( non_singleval, nonsums_only );
01285 #ifdef DEBUG
01286     assert ( nonsums_only.size() + sums_only.size() == non_singleval.size() );
01287 #endif
01288 
01289     std::vector<const CASObject*>::const_iterator singleval_it;
01290     std::vector<const CASObject*> singleval;
01291     wrking->GetSingleValues ( singleval );
01292 
01293     std::vector<CASObject*> result_vector;
01294     std::vector<CASObject*>::iterator result_it;
01295 
01296     std::vector<const CASObject*> temp_operands;
01297     std::vector<const CASObject*>::const_iterator temp_operands_it;
01298 
01299 
01300     // Expanding starts
01301     sums_only_it = sums_only.begin();
01302     const Sum* temp_sum = dynamic_cast<const Sum*> ( *sums_only_it );
01303 #ifdef DEBUG
01304     assert ( temp_sum != 0 );
01305 #endif
01306 
01307     GetOperands ( temp_sum, temp_operands );
01308 
01309 
01310     std::transform ( temp_operands.begin(),
01311                      temp_operands.end(),
01312                      std::back_inserter ( result_vector ),
01313                      CASCloneObject()
01314                    );
01315 
01316     std::vector<CASObject*> intermediate_results;
01317     // The first item was already processed
01318     sums_only_it++;
01319     // Expand the sums
01320     while ( sums_only_it != sums_only.end() ) {
01321         temp_sum = dynamic_cast<const Sum*> ( *sums_only_it );
01322 #ifdef DEBUG
01323         assert ( temp_sum != 0 );
01324 #endif
01325         temp_operands.clear();
01326         GetOperands ( temp_sum, temp_operands );
01327 
01328         result_it = result_vector.begin();
01329         while ( result_it != result_vector.end() ) {
01330             temp_operands_it = temp_operands.begin();
01331             while ( temp_operands_it != temp_operands.end() ) {
01332                 intermediate_results.push_back ( ( *result_it )->Multiply ( *temp_operands_it ) );
01333                 temp_operands_it++;
01334             }
01335             result_it++;
01336         }
01337         CASObject::Garbage->Put ( result_vector );
01338         result_vector.clear();
01339         std::copy ( intermediate_results.begin(),
01340                     intermediate_results.end(),
01341                     std::back_inserter ( result_vector )
01342                   );
01343         intermediate_results.clear();
01344         sums_only_it++;
01345     }
01346 #ifdef DEBUG
01347     assert ( intermediate_results.size() == 0 );
01348 #endif
01349 
01350     // Distribute the single values
01351     singleval_it = singleval.begin();
01352     while ( singleval_it != singleval.end() ) {
01353         result_it = result_vector.begin();
01354         while ( result_it != result_vector.end() ) {
01355             intermediate_results.push_back ( ( *result_it )->Multiply ( *singleval_it ) );
01356             result_it++;
01357         }
01358         CASObject::Garbage->Put ( result_vector );
01359         result_vector.clear();
01360         std::copy ( intermediate_results.begin(),
01361                     intermediate_results.end(),
01362                     std::back_inserter ( result_vector )
01363                   );
01364         intermediate_results.clear();
01365         singleval_it++;
01366     }
01367 #ifdef DEBUG
01368     assert ( intermediate_results.size() == 0 );
01369 #endif
01370 
01371     // Distribute the leftover, aka. nonsums only
01372     nonsums_only_it = nonsums_only.begin();
01373     while ( nonsums_only_it != nonsums_only.end() ) {
01374         result_it = result_vector.begin();
01375         while ( result_it != result_vector.end() ) {
01376             intermediate_results.push_back ( ( *result_it )->Multiply ( *nonsums_only_it ) );
01377             result_it++;
01378         }
01379         CASObject::Garbage->Put ( result_vector );
01380         result_vector.clear();
01381         std::copy ( intermediate_results.begin(),
01382                     intermediate_results.end(),
01383                     std::back_inserter ( result_vector )
01384                   );
01385         intermediate_results.clear();
01386         nonsums_only_it++;
01387     }
01388 #ifdef DEBUG
01389     assert ( intermediate_results.size() == 0 );
01390 #endif
01391     CASObject::Garbage->Put ( wrking );
01392 
01393     Sum *s = new Sum;
01394     SetOperands ( s, result_vector );
01395     CASObject::Garbage->Put ( result_vector );
01396 
01397     s->UnsetAllEvaluated();
01398     CASObject *result = s->Evaluate();
01399     CASObject::Garbage->Put ( s );
01400 
01401     return result;
01402 }
01403 
01411 void
01412 Product::RemoveNoOpElements() {
01413     std::vector<CASObject*>::iterator it = operands.begin();
01414     while ( it != operands.end() ) {
01415         if ( ( *it )->IsOne() ) {
01416             CASObject::Garbage->Put ( *it );
01417             it = operands.erase ( it );
01418         } else {
01419             CASTerm *term = dynamic_cast<CASTerm*> ( *it );
01420             if ( term != 0 ) {
01421                 term->RemoveNoOpElements();
01422             }
01423             it++;
01424         }
01425         // Iterator already incremented... no need for it++
01426     }
01427 }
01428 
01429 // ----------------------------------------------------------------------------
01430 
01431 // Operators
01432 // ----------------------------------------------------------------------------
01433 
01441 const Product&
01442 Product::operator= ( const Product &p ) {
01443 #ifdef SHOWCONSTRUCTOR
01444     std::cout << "# Product::operator=(const Product &p)" << std::endl;
01445 #endif
01446 
01447     if ( &p == this ) {
01448         return *this;
01449     }
01450 
01451     CASObject::Garbage->Put ( operands );
01452 
01453     operands.clear();
01454 
01455     std::transform ( p.operands.begin(),
01456                      p.operands.end(),
01457                      std::back_inserter ( operands ),
01458                      CASCloneObject() );
01459 
01460     meta = p.meta;
01461 
01462     CASObject::Garbage->Put ( exponent );
01463     exponent = p.exponent->Clone();
01464 
01465     return *this;
01466 }
01467 // ----------------------------------------------------------------------------
01468 

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