00001
00002 #pragma once
00003
00004 #include <sstream>
00005 #include <assert.h>
00006 #include <iostream>
00007 #include <algorithm>
00008
00009 #include "parseTools.h"
00010
00017
00018 struct xyExpPair
00019 {
00022 inline xyExpPair();
00023
00024 inline xyExpPair( int _x_exp, int _y_exp );
00025
00026 xyExpPair(std::stringstream& sstream);
00027
00033 inline void set( int _x_exp, int _y_exp);
00034 inline unsigned int getXExp() const;
00035 inline unsigned int getYExp() const;
00036
00038 inline unsigned int getDegree() const;
00039
00042 protected:
00043 unsigned int x_exp;
00044 unsigned int y_exp;
00045
00046 unsigned int extractExplicitExponent(std::stringstream& sstream);
00047 };
00048
00049
00050
00051
00055 template <class ccoeff>
00056 struct xyMonom
00057 {
00058
00061 xyMonom();
00062
00063 xyMonom(ccoeff _coeff, int _x_exp, int _y_exp );
00064
00066 xyMonom(std::stringstream& sstream);
00067
00068 xyMonom(std::string str);
00072 void createFromStream(std::stringstream& monomListStream);
00073
00076 inline unsigned int getDegree() const;
00077
00078 inline unsigned int getXExp() const;
00079 inline unsigned int getYExp() const;
00080 inline void setExp(int _x_exp, int _y_exp);
00085 inline ccoeff getCoeff() const;
00086 inline void setCoeff(ccoeff _coeff);
00091 template <class IMultiplyCoeffWithVariable, class IMultiplyVariables, class ResultType >
00092 inline ResultType substitute( const typename IMultiplyVariables::ElementType & x,
00093 const typename IMultiplyVariables::ElementType & y,
00094 const IMultiplyCoeffWithVariable & imultCoeffXVariable,
00095 const IMultiplyVariables & imultVariableXVariable
00096 ) const;
00097
00098 template <class IMultiplyRing >
00099 typename IMultiplyRing::ElementType substitute2(
00100 const typename IMultiplyRing::ElementType & x,
00101 const typename IMultiplyRing::ElementType & y,
00102 const IMultiplyRing & imult
00103 ) const;
00104
00107 protected:
00108 ccoeff coeff;
00109
00110 xyExpPair exponents;
00111
00112 std::string monomString;
00113
00114 };
00115
00116
00117
00118
00119
00120
00121 template <class ccoeff>
00122 std::ostream & operator<<(std::ostream & out, const xyMonom<ccoeff>& xyMonomObj);
00123
00127 template <class ccoeff>
00128 std::ostream & operator<<(std::ostream & out, const xyMonom<ccoeff>& xyMonomObj)
00129 {
00130
00131 xyMonomObj.getCoeff().printMultSecure(out);
00132 out << "*x^" << xyMonomObj.getXExp() << "*y^" << xyMonomObj.getYExp() << std::endl ;
00133 return out;
00134 } ;
00135
00136
00137
00138
00139
00140
00141 inline xyExpPair::xyExpPair()
00142 {
00143 x_exp=0;
00144 y_exp=0;
00145 }
00146
00147 inline xyExpPair::xyExpPair(int _x_exp, int _y_exp )
00148 {
00149 assert(_x_exp>=0 && _y_exp>=0);
00150
00151 x_exp=_x_exp;
00152 y_exp=_y_exp;
00153 }
00154
00155 inline void xyExpPair::set(int _x_exp, int _y_exp )
00156 {
00157 assert(_x_exp>=0 &&_y_exp>=0);
00158 x_exp=_x_exp;
00159 y_exp=_y_exp;
00160 }
00161
00162 inline unsigned int xyExpPair::getDegree() const
00163 {
00164 return x_exp + y_exp;
00165 }
00166
00167 inline unsigned int xyExpPair::getXExp() const
00168 {
00169 return x_exp ;
00170 }
00171
00172 inline unsigned int xyExpPair::getYExp() const
00173 {
00174 return y_exp ;
00175 }
00176
00177
00178
00179
00180
00181
00182 template <class ccoeff>
00183 xyMonom<ccoeff>::xyMonom()
00184 {
00185 exponents.set(0,0);
00186 coeff=0;
00187 };
00188
00189 template <class ccoeff>
00190 inline unsigned int xyMonom<ccoeff>::getDegree() const
00191 {
00192 return exponents.getDegree();
00193 }
00194
00195
00196 template <class ccoeff>
00197 inline unsigned int xyMonom<ccoeff>::getXExp() const
00198 {
00199 return exponents.getXExp() ;
00200 }
00201
00202
00203
00204 template <class ccoeff>
00205 inline unsigned int xyMonom<ccoeff>::getYExp() const
00206 {
00207 return exponents.getYExp() ;
00208 }
00209
00210
00211
00212 template <class ccoeff>
00213 inline ccoeff xyMonom<ccoeff>::getCoeff() const
00214 {
00215 return coeff;
00216 }
00217
00218 template <class ccoeff>
00219 inline void xyMonom<ccoeff>::setExp(int _x_exp, int _y_exp)
00220 {
00221 assert(_x_exp>=0 && _y_exp>=0);
00222 exponents.set(_x_exp,_y_exp);
00223 }
00224
00225 template <class ccoeff>
00226 inline void xyMonom<ccoeff>::setCoeff(ccoeff _coeff)
00227 {
00228 coeff=_coeff;
00229 }
00230
00231 template <class ccoeff>
00232 void xyMonom<ccoeff>::createFromStream(std::stringstream& monomListStream)
00233 {
00234 #ifdef DEBUG
00235 std::cerr << "xyMonom:: " << std::endl;
00236 std::cerr << "monomListStream= '" << monomListStream.str() << "'";
00237 #endif
00238 ccoeff parsedCoeff;
00239 bool failed = false;
00240
00241 std::streampos pos = monomListStream.tellp ( );
00242
00243 bool negative = false;
00244
00245
00246
00247 try{
00248 #ifdef DEBUG
00249 std::cerr << std::endl <<"parsedCoeff = ccoeff(monomListStream);" << std::endl;
00250 #endif
00251 monomListStream.peek();
00252 assert( monomListStream.good() );
00253 if (monomListStream.peek()=='-')
00254 {
00255 negative=true;
00256 extractChar('-',monomListStream);
00257 }
00258 monomListStream.peek();
00259
00260 if ( !monomListStream.eof() )
00261 {
00262 parsedCoeff = ccoeff(monomListStream);
00263
00264 if (monomListStream.fail() )
00265 {
00266
00267 monomListStream.clear();
00268
00269 monomListStream.seekp(pos);
00270 assert(! monomListStream.eof() );
00271
00272 failed = true;
00273 throw "failed to get the monom coefficient";
00274 }
00275 }
00276 else
00277 {
00278 parsedCoeff=-1;
00279 negative=false;
00280 }
00281
00282 }
00283 catch(char const * error)
00284 {
00285
00286 #ifdef DEBUG
00287 std::cerr << "char const * error: failed=true" << std::endl;
00288 #endif
00289 failed = true;
00290 }
00291 catch(std::bad_exception &e)
00292 {
00293
00294 #ifdef DEBUG
00295 std::cerr << "bad_exception: failed=true" << std::endl;
00296 #endif
00297 failed = true;
00298 }
00299 catch(...)
00300 {
00301
00302 #ifdef DEBUG
00303 std::cerr << "exception (...) : failed=true" << std::endl;
00304 #endif
00305 failed = true;
00306 }
00307 if (failed)
00308 {
00309
00310 #ifdef DEBUG
00311 std::cerr << " xyMonom: get coeff from stream failed" << std::endl;
00312 #endif
00313
00314
00315 assert(! monomListStream.eof() );
00316 assert(! monomListStream.fail() );
00317 assert(! monomListStream.bad() );
00318 assert( monomListStream.good() );
00319 monomListStream.seekp(pos);
00320
00321 if (!monomListStream.eof() && (monomListStream.peek()=='x' || monomListStream.peek()=='y' || monomListStream.peek()=='-') )
00322 {
00323 #ifdef DEBUG
00324 std::cerr << "parsedCoeff=1;"<< std::endl;
00325 #endif
00326 parsedCoeff=1;
00327 if (monomListStream.peek()=='-')
00328 {
00329 parsedCoeff=-1;
00330 extractChar('-',monomListStream);
00331 }
00332 }
00333 else
00334 throw "failed to get monom coefficient";
00335 }
00336
00337 coeff = parsedCoeff;
00338
00339 if (negative)
00340 {
00341 coeff= -parsedCoeff;
00342 }
00343
00344 #ifdef DEBUG
00345 std::cerr << "monomListStream= '" << monomListStream.str() << "'";
00346 #endif
00347
00348 xyExpPair parsedxyExpPair(monomListStream);
00349
00350 exponents = parsedxyExpPair;
00351 }
00352
00353
00354 template <class ccoeff>
00355 xyMonom<ccoeff>::xyMonom(std::string monom )
00356 {
00357 std::stringstream monomstrstream(monom);
00358
00359 createFromStream(monomstrstream);
00360 }
00361
00362
00363
00364
00368
00370 template <class ccoeff>
00371 xyMonom<ccoeff>::xyMonom(std::stringstream& monomListStream)
00372 {
00373 createFromStream(monomListStream);
00374 };
00375
00376
00377
00378 template <class ccoeff>
00379 xyMonom<ccoeff>::xyMonom(ccoeff _coeff, int _x_exp, int _y_exp )
00380 {
00381 coeff=_coeff;
00382 exponents.set(_x_exp,_y_exp);
00383 }
00384
00385
00388 template <class ccoeff>
00389 template <class IMultiplyCoeffWithVariable, class IMultiplyVariables, class ResultType >
00390 ResultType xyMonom<ccoeff>::substitute(
00391 const typename IMultiplyVariables::ElementType & x,
00392 const typename IMultiplyVariables::ElementType & y,
00393 const IMultiplyCoeffWithVariable & imultCoeffXVariable,
00394 const IMultiplyVariables & imultVariableXVariable
00395 ) const
00396 {
00397
00398
00399
00400 typename IMultiplyVariables::MultiplicationResultType res= IMultiplyVariables::ElementType::One;
00401
00402 for (int currXexp=1; currXexp<=(int)exponents.getXExp(); currXexp++)
00403 {
00404 res = imultVariableXVariable.multiply(res,x);
00405 }
00406
00407 for (int currYexp=1; currYexp<=(int)exponents.getYExp(); currYexp++)
00408 {
00409 res = imultVariableXVariable.multiply(res,y);
00410 }
00411
00412 for (int currXexp=-1; currXexp>=exponents.getXExp(); currXexp--)
00413 {
00414 res = imultVariableXVariable.multiply(res, imultVariableXVariable.multInv(x) );
00415 }
00416
00417 for (int currYexp=-1; currYexp>=exponents.getYExp(); currYexp--)
00418 {
00419 res = imultVariableXVariable.multiply(res,imultVariableXVariable.multInv(y) );
00420 }
00421
00422 return imultCoeffXVariable.scalarMultiply(coeff, res);
00423 };
00424
00425
00428 template <class ccoeff>
00429 template <class IMultiplyRing >
00430 typename IMultiplyRing::ElementType xyMonom<ccoeff>::substitute2(
00431 const typename IMultiplyRing::ElementType & x,
00432 const typename IMultiplyRing::ElementType & y,
00433 const IMultiplyRing & imult
00434 ) const
00435 {
00436
00437
00438
00439
00440
00441
00442 typename IMultiplyRing::ElementType res(imult.getEpsPrecision() ,std::string("") );
00443
00444
00445 assert(imult.getEpsPrecision()>= x.getEpsPrecision() );
00446 assert(imult.getEpsPrecision()>= y.getEpsPrecision() );
00447 res.setValue(0,1);
00448
00449 for (int currXexp=1; currXexp<=(int)exponents.getXExp(); currXexp++)
00450 {
00451 imult.multiplyInPlaceRef(res,x);
00452 }
00453
00454 for (int currYexp=1; currYexp<=(int)exponents.getYExp(); currYexp++)
00455 {
00456 imult.multiplyInPlaceRef(res,y);
00457
00458 }
00459
00460 assert(exponents.getYExp()>=0);
00461 assert(exponents.getYExp()>=0);
00462
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 return imult.scalarMultiply(coeff, res);
00476
00477
00478 };
00479
00480
00481 template <class xyMonomType>
00482 class xyOneFormTerm
00483 {
00484 public:
00485 enum TermType
00486 {
00487 DXTERM, DYTERM
00488 } ;
00489
00490 xyOneFormTerm(const xyMonomType & mon, TermType whichForm);
00491 xyOneFormTerm(const std::string & str);
00492 xyOneFormTerm(std::stringstream& monomListStream);
00493
00494 xyMonomType getMonom() const { return xyMonom_m; }
00495 int getDegree() const { return xyMonom_m.getDegree(); }
00496 bool isDxTerm() const { return whichDForm_m==xyOneFormTerm::DXTERM; };
00497 bool isDyTerm() const { return whichDForm_m==xyOneFormTerm::DYTERM; };
00498
00499 private:
00500 TermType whichDForm_m;
00501 xyMonomType xyMonom_m;
00502 };
00503
00504
00505 template <class xyMonomType>
00506 xyOneFormTerm<xyMonomType>::xyOneFormTerm( const xyMonomType & mon,
00507 TermType whichForm ): xyMonom_m(mon),
00508 whichDForm_m(whichForm)
00509 {
00510
00511 }
00512
00515 template <class xyMonomType>
00516 xyOneFormTerm<xyMonomType>::xyOneFormTerm(const std::string & paramstr)
00517 {
00518
00519 std::string error("Error reading xyOneFormTerm from stream: xyOneFormTerm only supports 'xyMonom'*dx and 'xyMonom'*dy -formed terms !\n");
00520
00521
00522
00523 std::string str=eatWS(paramstr);
00524
00525 size_t pos = str.find("d");
00526
00527 #ifdef DEBUG
00528 std::cerr << "paramstr = " << paramstr << std::endl;
00529 #endif
00530
00531 size_t posPlus = str.find("+");
00532 if (posPlus!=str.npos)
00533 {
00534 assert(posPlus==0);
00535 }
00536
00537 posPlus = str.find("-");
00538 if (posPlus!=str.npos)
00539 {
00540 assert(posPlus==0);
00541 }
00542
00543 if (pos==str.npos)
00544 {
00545 std::cerr << error<< std::endl;;
00546 assert (pos!=str.npos);
00547 }
00548
00549 str.substr(pos);
00550
00553 if (pos==0 && str.length()>0 )
00554 {
00555 xyMonom_m = xyMonomType(1, 0, 0 );
00556 }
00557 else
00558 {
00559
00560 assert(pos>0);
00561 xyMonom_m = xyMonomType(1, 0, 0 );
00562 std::string monomString ;
00563 if (pos==1)
00564 {
00565
00566 monomString= str.substr(0, pos);
00567 assert(monomString.at(0)=='-' || monomString.at(0)=='+');
00568 if ( monomString.at(0)=='+')
00569 monomString= monomString.substr(1);
00570 }
00571 else
00572 {
00573 assert(str.at(pos-1)=='*');
00574 monomString= str.substr(0, pos-1);
00575
00576 }
00577
00578 std::stringstream sstream(monomString);
00579 if (monomString.length()==0)
00580 xyMonom_m = xyMonomType(1, 0, 0 );
00581 else
00582 xyMonom_m = xyMonomType(sstream);
00583
00584 };
00585
00586
00587 std::stringstream differentialFormString( str.substr(pos) );
00588
00589 extractChar( 'd', differentialFormString );
00590
00591
00592
00593 if (differentialFormString.eof() )
00594 {
00595 std::cerr << error << std::endl;;
00596 assert( ! differentialFormString.eof() );
00597 }
00598
00599 if (differentialFormString.peek()=='x')
00600 {
00601 extractChar('x', differentialFormString);
00602 whichDForm_m=DXTERM;
00603 }
00604 else if (differentialFormString.peek()=='y')
00605 {
00606 extractChar('y', differentialFormString);
00607 whichDForm_m=DYTERM;
00608 }
00609 else
00610 {
00611 std::cerr << error ;
00612 assert(false);
00613 }
00614 differentialFormString.peek();
00615 if ( ! differentialFormString.eof() )
00616 {
00617 std::cerr << error << std::endl;
00618 std::cerr << "differentialFormString" << differentialFormString.str() << std::endl;
00619 assert( differentialFormString.eof() );
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 template <class PolynomXYType>
00637 class xyOneForm
00638 {
00639 public:
00640
00641 xyOneForm(const PolynomXYType & pdx, const PolynomXYType & pdy);
00642 xyOneForm(const std::string & str);
00643 xyOneForm(std::stringstream& monomListStream);
00644
00645 PolynomXYType getDxFormPart() const { return polynomDX_m; }
00646 PolynomXYType getDyFormPart() const { return polynomDY_m; }
00647
00648
00649 private:
00650
00651 PolynomXYType polynomDX_m;
00652 PolynomXYType polynomDY_m;
00653
00654 };
00655
00656
00657 template <class PolynomXYType>
00658 xyOneForm<PolynomXYType>::xyOneForm( const PolynomXYType & pdx,
00659 const PolynomXYType & pdy): polynomDX_m(pdx),
00660 polynomDY_m(pdy)
00661 {
00662
00663 }
00664
00666 template <class PolynomXYType>
00667 xyOneForm<PolynomXYType>::xyOneForm(const std::string & str)
00668 {
00669
00670 std::string tmpString = eatWS(str);
00671
00672 typedef xyMonom < typename PolynomXYType::CoefficientType> xyMonomType;
00673
00674 std::vector<xyOneFormTerm <xyMonomType > > monomTerms;
00675
00676 size_t pos = tmpString.npos;
00677
00678
00679 size_t posKlammer = tmpString.find_last_of('(');
00680 assert( posKlammer==tmpString.npos);
00681 posKlammer = tmpString.find_last_of(')');
00682
00683
00684 assert( posKlammer==tmpString.npos);
00685
00686
00687
00688 while (pos !=0)
00689 {
00690 size_t posPlus = tmpString.find_last_of('+');
00691 size_t posMinus = tmpString.find_last_of('-');
00692
00693 assert( posPlus==tmpString.npos || posPlus<tmpString.npos);
00694 assert(posMinus==tmpString.npos || posMinus<tmpString.npos);
00695
00696 if (posPlus==tmpString.npos)
00697 pos=posMinus;
00698 else if (posMinus==tmpString.npos)
00699 pos=posPlus;
00700 else
00701 pos= std::max(posPlus, posMinus);
00702
00703 if (pos==tmpString.npos)
00704 pos=0;
00705
00706
00707
00708 assert( tmpString.npos != 0 );
00709 if ( pos != tmpString.npos )
00710 {
00711 std::string monomString = tmpString.substr(pos);
00712 xyOneFormTerm <xyMonomType > oneFormTerm(monomString);
00713 monomTerms.push_back(oneFormTerm);
00714 tmpString= tmpString.substr(0,pos);
00715 }
00716 }
00717
00718
00719
00720 int maxDegree=0;
00721
00722 for (size_t i=0;i < monomTerms.size(); i++)
00723 {
00724 maxDegree = max( monomTerms[i].getDegree(), maxDegree);
00725 }
00726
00727
00728
00729
00730 polynomDX_m.clear();
00731 polynomDX_m.setDegree(maxDegree);
00732 polynomDY_m.clear();
00733 polynomDY_m.setDegree(maxDegree);
00734
00735
00736 PolynomXYType pObserver(maxDegree);
00737 PolynomXYType qObserver(maxDegree);
00738
00739
00740 for (size_t i=0;i < monomTerms.size(); i++)
00741 {
00742
00743 xyMonomType mon = monomTerms[i].getMonom();
00744 if (monomTerms[i].isDxTerm() )
00745 {
00746
00747 assert( pObserver.getCoeff(mon.getXExp(), mon.getYExp())==typename PolynomXYType::CoefficientType(0) );
00748 polynomDX_m.setCoeff(mon.getXExp(), mon.getYExp(), mon.getCoeff() );
00749 pObserver.setCoeff(mon.getXExp(), mon.getYExp(), 1 );
00750 }
00751 else if (monomTerms[i].isDyTerm() )
00752 {
00753
00754 assert( qObserver.getCoeff(mon.getXExp(), mon.getYExp())==typename PolynomXYType::CoefficientType(0) );
00755 polynomDY_m.setCoeff( mon.getXExp(), mon.getYExp(), mon.getCoeff() );
00756 qObserver.setCoeff(mon.getXExp(), mon.getYExp(), 1 );
00757 }
00758 else
00759 assert(false);
00760
00761 }
00762
00763
00764 }
00765