GiNaCRA
0.6.4
|
00001 /* 00002 * GiNaCRA - GiNaC Real Algebra package 00003 * Copyright (C) 2010-2012 Ulrich Loup, Joachim Redies, Sebastian Junges 00004 * 00005 * This file is part of GiNaCRA. 00006 * 00007 * GiNaCRA is free software: you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation, either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * GiNaCRA is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GiNaCRA. If not, see <http://www.gnu.org/licenses/>. 00019 * 00020 */ 00021 00022 00023 #include <list> 00024 #include <assert.h> 00025 #include <stdexcept> 00026 #include <locale> 00027 #include <vector> 00028 00029 #include "MultivariatePolynomialMR.h" 00030 #include "MultivariateTermMR.h" 00031 #include "VariableListPool.h" 00032 00033 using GiNaC::ex; 00034 using GiNaC::add; 00035 using GiNaC::const_iterator; 00036 using GiNaC::is_exactly_a; 00037 00038 namespace GiNaCRA 00039 { 00040 bool operator !=( const MonomMRCompare& m1, const MonomMRCompare& m2 ) 00041 { 00042 return m1.GetMonomOrdering() != m2.GetMonomOrdering(); 00043 } 00044 00045 MultivariatePolynomialMR::MultivariatePolynomialMR(): 00046 mCmp(), 00047 mTerms() /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00048 {} 00049 00050 MultivariatePolynomialMR::MultivariatePolynomialMR( const MonomMRCompare& comp ): 00051 mCmp( comp ), 00052 mTerms( comp ) /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00053 {} 00054 00055 MultivariatePolynomialMR::MultivariatePolynomialMR( const MultivariateTermMR& t1, const MonomMRCompare& comp ): 00056 mCmp( comp ), 00057 mTerms( mCmp ) /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00058 { 00059 mTerms.insert( t1 ); 00060 } 00061 00062 MultivariatePolynomialMR::MultivariatePolynomialMR( const MultivariateTermMR& t1, const MultivariateTermMR& t2, const MonomMRCompare& comp ): 00063 mCmp( comp ), 00064 mTerms( mCmp ) /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00065 { 00066 mTerms.insert( t1 ); 00067 mTerms.insert( t2 ); 00068 } 00069 00070 MultivariatePolynomialMR::MultivariatePolynomialMR( sMT_It begin, sMT_It last, const MonomMRCompare& comp ): 00071 mCmp( comp ), 00072 mTerms( begin, last, comp ) /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00073 {} 00074 00075 MultivariatePolynomialMR::MultivariatePolynomialMR( sMT_It begin1, sMT_It last1, sMT_It begin2, sMT_It last2, const MonomMRCompare& comp ): 00076 mCmp( comp ), 00077 mTerms( comp ) /* , mpVarList(VariableListPool::getPtToStdVarList()), mpParList(VariableListPool::getPtToStdParList()) */ 00078 { 00079 sMT_It inputIt = mTerms.begin(); 00080 MonomOrderingFc less = mCmp.GetMonomOrdering(); 00081 while( begin1 != last1 ) 00082 { 00083 if( begin2 == last2 ) 00084 { 00085 mTerms.insert( begin1, last1 ); 00086 } 00087 if( less( *begin1, *begin2 )) 00088 { 00089 inputIt = mTerms.insert( inputIt, *begin1 ); 00090 ++begin1; 00091 continue; 00092 } // else if 00093 if( less( *begin1, *begin2 )) 00094 { 00095 inputIt = mTerms.insert( inputIt, *begin2 ); 00096 ++begin2; 00097 continue; 00098 } // else (equal) 00099 inputIt = mTerms.insert( inputIt, MultivariateTermMR( *begin1, begin1->getCoeffExpr() + begin2->getCoeffExpr() )); 00100 ++begin1; 00101 ++begin2; 00102 } 00103 mTerms.insert( begin2, last2 ); 00104 } 00105 00106 MultivariatePolynomialMR::MultivariatePolynomialMR( const GiNaC::ex& expr, const MonomMRCompare& cmp ): 00107 mCmp( cmp ), 00108 mTerms( cmp ) 00109 { 00110 ex expression = expr.expand(); 00111 GiNaC::lst list = GiNaC::lst(); 00112 std::vector<symbol> vars = VariableListPool::getVariables(); 00113 for( std::vector<symbol>::const_iterator it = vars.begin(); it != vars.end(); ++it ) 00114 { 00115 list.append( *it ); 00116 } 00117 if( !expression.is_polynomial( list )) 00118 throw std::invalid_argument( "Argument is not a polynomial" ); 00119 if( is_exactly_a<GiNaC::add>( expression )) // GiNaC::add because of overriding the name "add" by the current function 00120 { 00121 for( const_iterator i = expression.begin(); i != expression.end(); ++i ) // iterate through the summands 00122 { 00123 if( GiNaC::is_constant( *i, vars )) 00124 { // polynomial is constant in the current list of variables, so is a coefficient with the 1 monomial 00125 mTerms.insert( MultivariateTermMR( *i )); 00126 } 00127 else if( GiNaC::is_exactly_a<GiNaC::mul>( *i )) // GiNaC::mul because of overriding the name "mul" by the current function 00128 { // polynomial is just a product 00129 GiNaC::ex coeff = GiNaC::ex( 1 ); 00130 00131 std::vector<std::pair<unsigned, unsigned> > mon = std::vector<std::pair<unsigned, unsigned> >(); 00132 for( const_iterator j = i->begin(); j != i->end(); ++j ) // iterate through the possible powers 00133 { 00134 std::vector<symbol>::const_iterator s = vars.begin(); 00135 unsigned ind = 0; 00136 for( ; s != vars.end(); ++s ) // only tak)e symbols given in the list (all other things are coefficient) 00137 { 00138 if( j->degree( *s ) > 0 ) 00139 { 00140 mon.push_back( std::pair<unsigned, unsigned>( ind, j->degree( *s ))); 00141 break; 00142 } 00143 ++ind; 00144 } 00145 if( s == vars.end() ) 00146 { // current power is not build upon a variable, so it belongs to the coefficient 00147 coeff = coeff * *j; 00148 break; 00149 } 00150 } 00151 mTerms.insert( MultivariateTermMR( MultivariateMonomialMR( mon.begin(), mon.end() ), coeff )); 00152 } 00153 else if( GiNaC::is_exactly_a<GiNaC::power>( *i ) || GiNaC::is_exactly_a<symbol>( *i )) 00154 { 00155 std::vector<symbol>::const_iterator s = vars.begin(); 00156 unsigned ind = 0; 00157 for( ; s != vars.end(); ++s ) // only take symbols given in the list (all other things are coefficient) 00158 { 00159 if( i->degree( *s ) > 0 ) 00160 { 00161 mTerms.insert( MultivariateTermMR( MultivariateMonomialMR( ind, (unsigned)(i->degree( *s ))))); 00162 break; 00163 } 00164 ++ind; 00165 } 00166 if( s == vars.end() ) 00167 { 00168 mTerms.insert( MultivariateTermMR( *i )); 00169 } 00170 } 00171 else if( is_exactly_a<numeric>( *i )) 00172 mTerms.insert( MultivariateTermMR( *i )); 00173 00174 else if( i->is_zero() ) 00175 ; 00176 } 00177 00178 } 00179 else 00180 { 00181 if( GiNaC::is_constant( expr, vars )) 00182 { // polynomial is constant in the current list of variables, so is a coefficient with the 1 monomial 00183 mTerms.insert( MultivariateTermMR( expr )); 00184 } 00185 else if( GiNaC::is_exactly_a<GiNaC::mul>( expr )) // GiNaC::mul because of overriding the name "mul" by the current function 00186 { // polynomial is just a product 00187 GiNaC::ex coeff = GiNaC::ex( 1 ); 00188 00189 std::vector<std::pair<unsigned, unsigned> > mon = std::vector<std::pair<unsigned, unsigned> >(); 00190 for( const_iterator j = expr.begin(); j != expr.end(); ++j ) // iterate through the possible powers 00191 { 00192 std::vector<symbol>::const_iterator s = vars.begin(); 00193 unsigned ind = 0; 00194 for( ; s != vars.end(); ++s ) // only tak)e symbols given in the list (all other things are coefficient) 00195 { 00196 if( j->degree( *s ) > 0 ) 00197 { 00198 mon.push_back( std::pair<unsigned, unsigned>( ind, j->degree( *s ))); 00199 break; 00200 } 00201 ++ind; 00202 } 00203 if( s == vars.end() ) 00204 { // current power is not build upon a variable, so it belongs to the coefficient 00205 coeff = coeff * *j; 00206 break; 00207 } 00208 } 00209 mTerms.insert( MultivariateTermMR( MultivariateMonomialMR( mon.begin(), mon.end() ), coeff )); 00210 } 00211 else if( GiNaC::is_exactly_a<GiNaC::power>( expr ) || GiNaC::is_exactly_a<symbol>( expr )) 00212 { 00213 std::vector<symbol>::const_iterator s = vars.begin(); 00214 unsigned ind = 0; 00215 for( ; s != vars.end(); ++s ) // only take symbols given in the list (all other things are coefficient) 00216 { 00217 if( expr.degree( *s ) > 0 ) 00218 { 00219 mTerms.insert( MultivariateTermMR( MultivariateMonomialMR( ind, (unsigned)(expr.degree( *s ))))); 00220 break; 00221 } 00222 ++ind; 00223 } 00224 if( s == vars.end() ) 00225 { 00226 mTerms.insert( MultivariateTermMR( expr )); 00227 } 00228 } 00229 else if( is_exactly_a<numeric>( expr )) 00230 mTerms.insert( MultivariateTermMR( expr )); 00231 00232 else if( expr.is_zero() ) 00233 ; 00234 } 00235 00236 //if(expr.is_polynomial()) 00237 } 00238 00239 GiNaC::ex MultivariatePolynomialMR::toEx() const 00240 { 00241 GiNaC::ex expr = GiNaC::ex( 0 ); 00242 for( sMT_cIt it = mTerms.begin(); it != mTerms.end(); ++it ) 00243 { 00244 expr += it->toEx(); 00245 } 00246 return expr; 00247 } 00248 00249 bool operator ==( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00250 { 00251 //TODO what to do with different ordering?! 00252 if( p1.mTerms.size() != p2.mTerms.size() ) 00253 return false; 00254 return std::equal( p1.mTerms.begin(), p1.mTerms.end(), p2.mTerms.begin() ); 00255 } 00256 00257 bool operator !=( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00258 { 00259 //TODO what to do with different ordering?! 00260 if( p1.mTerms.size() != p2.mTerms.size() ) 00261 return true; 00262 return !std::equal( p1.mTerms.begin(), p1.mTerms.end(), p2.mTerms.begin() ); 00263 } 00264 00265 const MultivariatePolynomialMR operator +( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00266 { 00267 //TODO what if not equal polynomialordering! It is correct although very slow. 00268 //return MultivariatePolynomialMR(p1.mTerms.begin(), p1.mTerms.end(), p2.mTerms.begin(), p2.mTerms.end(), p1.mCmp); 00269 MultivariatePolynomialMR newPol( p1.mCmp ); 00270 sMT_It inputIt = newPol.mTerms.begin(); 00271 MonomOrderingFc less = p1.mCmp.GetMonomOrdering(); 00272 00273 sMT_It p1it = p1.mTerms.begin(); 00274 sMT_It p2it = p2.mTerms.begin(); 00275 sMT_It p1end = p1.mTerms.end(); 00276 sMT_It p2end = p2.mTerms.end(); 00277 00278 while( p1it != p1end ) 00279 { 00280 if( p2it == p2end ) 00281 { 00282 newPol.mTerms.insert( p1it, p1end ); 00283 return newPol; 00284 } 00285 if( p1it->hasEqualExponents( *p2it )) 00286 { 00287 ex newCoeff = p1it->getCoeffExpr() + p2it->getCoeffExpr(); 00288 if( newCoeff != 0 ) 00289 { 00290 inputIt = newPol.mTerms.insert( inputIt, MultivariateTermMR( *p1it, newCoeff )); 00291 } 00292 ++p1it; 00293 ++p2it; 00294 continue; 00295 } 00296 if( less( *p1it, *p2it )) 00297 { 00298 inputIt = newPol.mTerms.insert( inputIt, *(p1it++) ); 00299 //++p1it; 00300 continue; 00301 } // else if 00302 else 00303 { // (less(*p1it, *p2it)) { 00304 inputIt = newPol.mTerms.insert( inputIt, *(p2it++) ); 00305 //++p2it; 00306 continue; 00307 } // else (equal) 00308 } 00309 newPol.mTerms.insert( p2it, p2end ); 00310 return newPol; 00311 00312 } 00313 00314 const MultivariatePolynomialMR operator +( const MultivariatePolynomialMR& p1, const MultivariateTermMR& t1 ) 00315 { 00316 MultivariatePolynomialMR newPol = MultivariatePolynomialMR( p1 ); 00317 std::pair<sMT_It, bool> ret = newPol.mTerms.insert( t1 ); 00318 if( ret.second ) 00319 return newPol; 00320 //the same monomial already exists. 00321 //we remove the old one and construct a new term. 00322 00323 //prepare a pointer to the location where the next should be inserted after. 00324 sMT_It newIt = ret.first; 00325 --newIt; 00326 00327 //calculate the coeff 00328 ex newCoeff = t1.getCoeffExpr() + ret.first->getCoeffExpr(); 00329 00330 newPol.mTerms.erase( ret.first ); 00331 00332 //If the new coefficient is zero, we do not add the term. 00333 if( newCoeff == 0 ) 00334 { 00335 return newPol; 00336 } 00337 00338 newPol.mTerms.insert( newIt, MultivariateTermMR( t1, newCoeff )); 00339 return newPol; 00340 } 00341 00342 const MultivariatePolynomialMR operator +( const MultivariateTermMR& t1, MultivariatePolynomialMR& p1 ) 00343 { 00344 return p1 + t1; 00345 } 00346 00347 const MultivariatePolynomialMR operator +( const MultivariatePolynomialMR& p1, const MultivariateMonomialMR& m1 ) 00348 { 00349 MultivariatePolynomialMR newPol = MultivariatePolynomialMR( p1 ); 00350 std::pair<sMT_It, bool> ret = newPol.mTerms.insert( m1 ); 00351 if( ret.second ) 00352 return newPol; 00353 //the same monomial already exists. 00354 //we remove the old one and construct a new term. 00355 00356 //prepare a pointer to the location where the next should be inserted after. 00357 sMT_It newIt = ret.first; 00358 --newIt; 00359 00360 //the new term has coefficient 0? 00361 if( ret.first->getCoeffExpr() == -1 ) 00362 { 00363 newPol.mTerms.erase( ret.first ); 00364 return newPol; 00365 } 00366 00367 //calculate the coefficient 00368 ex newCoeff = 1 + ret.first->getCoeffExpr(); 00369 00370 newPol.mTerms.erase( ret.first ); 00371 newPol.mTerms.insert( newIt, MultivariateTermMR( m1, newCoeff )); 00372 00373 return newPol; 00374 } 00375 00376 const MultivariatePolynomialMR operator +( const MultivariateMonomialMR& m1, const MultivariatePolynomialMR& p1 ) 00377 { 00378 return p1 + m1; 00379 } 00380 00381 const MultivariatePolynomialMR operator -( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00382 { 00383 MultivariatePolynomialMR newPol( p1.mCmp ); 00384 sMT_It inputIt = newPol.mTerms.begin(); 00385 MonomOrderingFc less = p1.mCmp.GetMonomOrdering(); 00386 00387 sMT_It p1it = p1.mTerms.begin(); 00388 sMT_It p2it = p2.mTerms.begin(); 00389 sMT_It p1end = p1.mTerms.end(); 00390 sMT_It p2end = p2.mTerms.end(); 00391 00392 while( p1it != p1end ) 00393 { 00394 if( p2it == p2end ) 00395 { 00396 newPol.mTerms.insert( p1it, p1end ); 00397 return newPol; 00398 } 00399 00400 if( p1it->hasEqualExponents( *p2it )) 00401 { 00402 ex newCoeff = p1it->getCoeffExpr() - p2it->getCoeffExpr(); 00403 if( newCoeff != 0 ) 00404 { 00405 inputIt = newPol.mTerms.insert( inputIt, MultivariateTermMR( *p1it, newCoeff )); 00406 } 00407 ++p1it; 00408 ++p2it; 00409 continue; 00410 } 00411 if( less( *p1it, *p2it )) 00412 { 00413 inputIt = newPol.mTerms.insert( inputIt, *(p1it) ); 00414 ++p1it; 00415 continue; 00416 } // else if 00417 else 00418 { // if (less(*p2it, *p1it)) { 00419 inputIt = newPol.mTerms.insert( inputIt, (p2it->negate())); 00420 ++p2it; 00421 continue; 00422 } // else (equal) 00423 00424 } 00425 for( ; p2it != p2end; ++p2it ) 00426 { 00427 inputIt = newPol.mTerms.insert( inputIt, p2it->negate() ); 00428 } 00429 return newPol; 00430 } 00431 00432 const MultivariatePolynomialMR operator -( const MultivariatePolynomialMR& p1 ) 00433 { 00434 MultivariatePolynomialMR newPol = MultivariatePolynomialMR( p1.mCmp ); 00435 sMT_It inputloc = newPol.mTerms.begin(); 00436 for( sMT_It it = p1.mTerms.begin(); it != p1.mTerms.end(); ++it ) 00437 { 00438 inputloc = newPol.mTerms.insert( inputloc, it->negate() ); 00439 } 00440 return newPol; 00441 00442 } 00443 // 00444 // const MultivariatePolynomialMR operator *( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00445 // { 00446 // // MultivariatePolynomialMR 00447 // } 00448 00449 const MultivariatePolynomialMR operator *( const MultivariatePolynomialMR& p1, const MultivariateTermMR& t1 ) 00450 { 00451 MultivariatePolynomialMR newPol( p1.mCmp ); 00452 sMT_cIt end1 = p1.mTerms.end(); 00453 sMT_It inputloc = newPol.mTerms.begin(); 00454 for( sMT_cIt it = p1.mTerms.begin(); it != end1; ++it ) 00455 { 00456 inputloc = newPol.mTerms.insert( inputloc, (*it) * t1 ); 00457 } 00458 return newPol; 00459 } 00460 00461 const MultivariatePolynomialMR operator *( const MultivariateTermMR& t1, MultivariatePolynomialMR& p1 ) 00462 { 00463 return p1 * t1; 00464 } 00465 00466 const MultivariatePolynomialMR operator *( const MultivariatePolynomialMR& p1, const MultivariateMonomialMR& m1 ) 00467 { 00468 MultivariatePolynomialMR newPol( p1.mCmp ); 00469 sMT_cIt end1 = p1.mTerms.end(); 00470 sMT_It inputloc = newPol.mTerms.begin(); 00471 for( sMT_cIt it = p1.mTerms.begin(); it != end1; ++it ) 00472 { 00473 inputloc = newPol.mTerms.insert( inputloc, (*it) * m1 ); 00474 } 00475 return newPol; 00476 } 00477 00478 const MultivariatePolynomialMR operator *( const MultivariateMonomialMR& m1, const MultivariatePolynomialMR& p1 ) 00479 { 00480 return p1 * m1; 00481 } 00482 00483 std::ostream& operator <<( std::ostream& os, const MultivariatePolynomialMR& rhs ) 00484 { 00485 for( sMT_rIt it = rhs.mTerms.rbegin(); it != rhs.mTerms.rend(); ++it ) 00486 { 00487 os << *it << " "; 00488 } 00489 return os; 00490 } 00491 00492 const MultivariatePolynomialMR MultivariatePolynomialMR::SPol( const MultivariatePolynomialMR& p1, const MultivariatePolynomialMR& p2 ) 00493 { 00494 //std::cout << "p1:" << p1 << "\np2:" << p2 << std::endl; 00495 if( p1.getMonomOrder() != p2.getMonomOrder() ) 00496 { 00497 throw std::invalid_argument( "Different orderings are not yet supported" ); 00498 } 00499 if( p1.nrOfTerms() == 1 && p2.nrOfTerms() == 1 ) 00500 { 00501 return MultivariatePolynomialMR( p1.mCmp ); 00502 } 00503 else if( p1.nrOfTerms() == 1 ) 00504 { 00505 return -(p2.lterm().lcmdivt( p1.lmon() ) * p2.truncLT()); 00506 } 00507 else if( p2.nrOfTerms() == 1 ) 00508 { 00509 return (p1.lterm().lcmdivt( p2.lmon() ) * p1.truncLT()); 00510 } 00511 //std::cout << p2.lterm().lcmdivt(p1.lmon()) << std::endl; 00512 //std::cout << p2.truncLT(); 00513 // std::cout << (p2.truncLT().multiply(p2.lterm().lcmdivt(p1.lmon()))) << std::endl; 00514 return p1.truncLT().multiply( p1.lterm().lcmdivt( p2.lmon() )) - (p2.truncLT().multiply( p2.lterm().lcmdivt( p1.lmon() ))); 00515 } 00516 00517 MultivariatePolynomialMR MultivariatePolynomialMR::CalculateRemainder( std::list<MultivariatePolynomialMR>::const_iterator ideallistBegin, 00518 std::list<MultivariatePolynomialMR>::const_iterator ideallistEnd ) const 00519 { 00520 MultivariatePolynomialMR* p = new MultivariatePolynomialMR( *this ); 00521 MultivariatePolynomialMR* r = new MultivariatePolynomialMR( MonomMRCompare( mCmp )); 00522 00523 while( !p->isZero() ) 00524 { 00525 //std::cout << "a" << std::endl; 00526 std::list<MultivariatePolynomialMR>::const_iterator fIt = ideallistBegin; 00527 bool divOccured = false; 00528 while( !divOccured && fIt != ideallistEnd ) 00529 { 00530 //MultivariatePolynomialMR temp(*p); 00531 std::pair<MultivariateTermMR, bool> red = p->lterm().divby( fIt->lterm() ); 00532 00533 if( red.second ) 00534 { 00535 *p = (*p) - (fIt->multiply( red.first )); 00536 divOccured = true; 00537 } 00538 else 00539 { 00540 ++fIt; 00541 } 00542 } 00543 //std::cout << "b" << std::endl; 00544 if( !divOccured ) 00545 { 00546 r->mTerms.insert( p->lterm() ); 00547 p->mTerms.erase( p->lterm() ); 00548 } 00549 } 00550 const MultivariatePolynomialMR ret = MultivariatePolynomialMR( *r ); 00551 delete p; 00552 return ret; 00553 } 00554 00555 MultivariatePolynomialMR MultivariatePolynomialMR::normalized() 00556 { 00557 MultivariatePolynomialMR n = MultivariatePolynomialMR( mCmp ); 00558 ex lc = this->lcoeff(); 00559 for( std::set<MultivariateTermMR, MonomMRCompare>::iterator i = mTerms.begin(); i != mTerms.end(); ++i ) 00560 n.mTerms.insert( i->divide( lc )); 00561 return n; 00562 } 00563 }