MC++
structure.hpp
00001 // Copyright (C) 2011-2012 Benoit Chachuat (b.chachuat@imperial.ac.uk)
00002 // All rights reserved.
00003 
00004 // This code is provided "as is", without any warranty of any kind,
00005 // either expressed or implied, including but not limited to, any implied
00006 // warranty of merchantability or fitness for any purpose. In no event
00007 // will any party who distributed the code be liable for damages or for
00008 // any claim(s) by any other party, including but not limited to, any
00009 // lost profits, lost monies, lost data or data rendered inaccurate,
00010 // losses sustained by third parties, or any other special, incidental or
00011 // consequential damages arising out of the use or inability to use the
00012 // program, even if the possibility of such damages has been advised
00013 // against. The entire risk as to the quality, the performance, and the
00014 // fitness of the program for any particular purpose lies with the party
00015 // using the code.
00016 
00017 // This code, and any derivative of this code, may not be used in a
00018 // commercial package without the prior explicit written permission of
00019 // the authors. Verbatim copies of this code may be made and distributed
00020 // in any medium, provided that this copyright notice is not removed or
00021 // altered in any way. No fees may be charged for distribution of the
00022 // codes, other than a fee to cover the cost of the media and a
00023 // reasonable handling fee.
00024 
00097 #ifndef MC__SPARSE_H
00098 #define MC__SPARSE_H
00099 
00100 #include <iostream>
00101 #include <map>
00102 
00103 namespace mc
00104 {
00105 
00111 class Structure
00113 {
00114   // friends of class Structure for operator overloading
00115   friend Structure operator+
00116     ( const Structure& );
00117   friend Structure operator+
00118     ( const Structure&, const Structure& );
00119   friend Structure operator+
00120     ( const double, const Structure& );
00121   friend Structure operator+
00122     ( const Structure&, const double );
00123   friend Structure operator-
00124     ( const Structure& );
00125   friend Structure operator-
00126     ( const Structure&, const Structure& );
00127   friend Structure operator-
00128     ( const double, const Structure& );
00129   friend Structure operator-
00130     ( const Structure&, const double );
00131   friend Structure operator*
00132     ( const Structure&, const Structure& );
00133   friend Structure operator*
00134     ( const Structure&, const double );
00135   friend Structure operator*
00136     ( const double, const Structure& );
00137   friend Structure operator/
00138     ( const Structure&, const Structure& );
00139   friend Structure operator/
00140     ( const Structure&, const double );
00141   friend Structure operator/
00142     ( const double, const Structure& );
00143   friend std::ostream& operator<<
00144     ( std::ostream&, const Structure& );
00145   friend bool operator==
00146     ( const Structure&, const Structure& );
00147   friend bool operator!=
00148     ( const Structure&, const Structure& );
00149   friend bool operator<=
00150     ( const Structure&, const Structure& );
00151   friend bool operator>=
00152     ( const Structure&, const Structure& );
00153   friend bool operator<
00154     ( const Structure&, const Structure& );
00155   friend bool operator>
00156     ( const Structure&, const Structure& );
00157 
00158   // friends of class Structure for function overloading
00159   friend Structure inv
00160     ( const Structure& );
00161   friend Structure sqr
00162     ( const Structure& );
00163   friend Structure exp
00164     ( const Structure& );
00165   friend Structure log
00166     ( const Structure& );
00167   friend Structure cos
00168     ( const Structure& );
00169   friend Structure sin
00170     ( const Structure& );
00171   friend Structure tan
00172     ( const Structure& );
00173   friend Structure acos
00174     ( const Structure& );
00175   friend Structure asin
00176     ( const Structure& );
00177   friend Structure atan
00178     ( const Structure& );
00179   friend Structure fabs
00180     ( const Structure& );
00181   friend Structure sqrt
00182     ( const Structure& );
00183   friend Structure xlog
00184     ( const Structure& );
00185   friend Structure erf
00186     ( const Structure& );
00187   friend Structure erfc
00188     ( const Structure& );
00189   friend Structure arh
00190     ( const Structure&, const double );
00191   friend Structure pow
00192     ( const Structure&, const int );
00193   friend Structure pow
00194     ( const Structure&, const double );
00195   friend Structure pow
00196     ( const Structure&, const Structure& );
00197   friend Structure min
00198     ( const Structure&, const Structure& );
00199   friend Structure max
00200     ( const Structure&, const Structure& );
00201   friend Structure min
00202     ( const unsigned int, const Structure* );
00203   friend Structure max
00204     ( const unsigned int, const Structure* );
00205 
00206 public:
00207 
00209   class Exceptions
00210   {
00211   public:
00213     enum TYPE{
00214       UNDEF=-33   
00215     };
00217     Exceptions( TYPE ierr ) : _ierr( ierr ){}
00218 
00220     int ierr(){ return _ierr; }
00221   private:
00222     TYPE _ierr;
00223   };
00224 
00225   typedef std::map<int,bool> t_Structure;
00226   typedef t_Structure::iterator it_Structure;
00227   typedef t_Structure::const_iterator cit_Structure;
00228 
00229   // other operator overloadings (inlined)
00230   Structure& operator=
00231     ( const double c )
00232     { _dep.clear(); return *this; }
00233   Structure& operator=
00234     ( const Structure&S )
00235     { if( this != &S ) _dep = S._dep; return *this; }
00236   Structure& operator+=
00237     ( const double c )
00238     { return *this; }
00239   Structure& operator+=
00240     ( const Structure&S )
00241     { return combine( S ); }
00242   Structure& operator-=
00243     ( const double c )
00244     { return *this; }
00245   Structure& operator-=
00246     ( const Structure&S )
00247     { return combine( S ); }
00248   Structure& operator*=
00249     ( const double c )
00250     { return *this; }
00251   Structure& operator*=
00252     ( const Structure&S )
00253     { return combine( S, false ); }
00254   Structure& operator/=
00255     ( const double c )
00256     { return *this; }
00257   Structure& operator/=
00258     ( const Structure&S )
00259     { return combine( S, false ); }
00260 
00264 
00265   Structure
00266     ( const double c=0. )
00267     {}
00268 /*   //! @brief Constructor for a variable with index <a>index</a>
00269   Structure
00270     ( const int ind )
00271     { _dep.insert( std::make_pair(ind,true) ); }
00272  */
00274   Structure
00275     ( const Structure&S ):
00276     _dep(S._dep)
00277     {}
00279   ~Structure()
00280     {}
00281 
00283   Structure& indep
00284     ( const int ind )
00285     { _dep.clear(); _dep.insert( std::make_pair(ind,true) ); return *this; }
00286 
00288   std::pair<bool,bool> dep
00289     ( const int ind )
00290     { cit_Structure it = _dep.find(ind);
00291       return( it==_dep.end()? std::make_pair(false,true):
00292         std::make_pair(true,it->second) ); }
00293 //   //! @brief Determines if the current object is dependent on the variable <a>S</a>
00294 //   bool dep
00295 //     ( const Structure&S )
00296 //     { return( _dep.size()==combine(*this,S)._dep.size()? true: false); }
00297 
00299   const t_Structure& dep() const
00300     { return _dep; }
00301   t_Structure& dep()
00302     { return _dep; }
00303 
00305   Structure& combine
00306     ( const Structure&S, const bool linear=true );
00308   static Structure combine
00309     ( const Structure&S1, const Structure&S2, const bool linear=true );
00311   static Structure combine
00312     ( const unsigned int n, const Structure*S, const bool linear=true );
00313 
00315   Structure& nonlinear();
00317   static Structure nonlinear
00318     ( const Structure&S );
00321 private:
00322 
00324   t_Structure _dep;
00325 };
00326 
00328 
00329 inline Structure&
00330 Structure::nonlinear()
00331 {
00332   it_Structure it = _dep.begin();
00333   for( ; it != _dep.end(); ++it ) it->second = false;
00334   return *this;
00335 }
00336 
00337 inline Structure
00338 Structure::nonlinear
00339 ( const Structure&S )
00340 {
00341   Structure S2( S );
00342   return S2.nonlinear(); 
00343 }
00344 
00345 inline Structure&
00346 Structure::combine
00347 ( const Structure&S, const bool linear )
00348 {
00349   cit_Structure cit = S._dep.begin();
00350   for( ; cit != S._dep.end(); ++cit ){
00351     std::pair<it_Structure,bool> ins = _dep.insert( *cit );
00352     if( !ins.second ) ins.first->second = ( ins.first->second && cit->second );
00353   }
00354   return( linear? *this: nonlinear() );
00355 }
00356 
00357 inline Structure
00358 Structure::combine
00359 ( const Structure&S1, const Structure&S2, const bool linear )
00360 {
00361   Structure S3( S1 );
00362   return S3.combine( S2, linear );
00363 }
00364 
00365 inline Structure
00366 Structure::combine
00367 ( const unsigned int n, const Structure*S, const bool linear )
00368 {
00369   Structure S2;
00370   for( unsigned int i=0; S && i<n; i++ ) S2.combine( S[i], linear );
00371   return S2;
00372 }
00373 
00374 inline std::ostream&
00375 operator<<
00376 ( std::ostream&out, const Structure&S)
00377 {
00378   out << "{ ";
00379   Structure::cit_Structure iS = S._dep.begin();
00380   for( ; iS != S._dep.end(); ++iS )
00381     out << iS->first << (iS->second?"L":"NL") << " ";
00382   out << "}";
00383   return out;
00384 }
00385 
00386 inline Structure
00387 operator+
00388 ( const Structure&S )
00389 {
00390   return S;
00391 }
00392 
00393 inline Structure
00394 operator-
00395 ( const Structure&S )
00396 {
00397   return S;
00398 }
00399 
00400 inline Structure
00401 operator+
00402 ( const double c, const Structure&S )
00403 {
00404   return S;
00405 }
00406 
00407 inline Structure
00408 operator+
00409 ( const Structure&S, const double c )
00410 {
00411   return S;
00412 }
00413 
00414 inline Structure
00415 operator+
00416 ( const Structure&S1, const Structure&S2 )
00417 { 
00418   return Structure::combine( S1, S2 );
00419 }
00420 
00421 inline Structure
00422 operator-
00423 ( const double c, const Structure&S )
00424 {
00425   return S;
00426 }
00427 
00428 inline Structure
00429 operator-
00430 ( const Structure&S, const double c )
00431 {
00432   return S;
00433 }
00434 
00435 inline Structure
00436 operator-
00437 ( const Structure&S1, const Structure&S2 )
00438 {
00439   return Structure::combine( S1, S2 );
00440 }
00441 
00442 inline Structure
00443 operator*
00444 ( const double c, const Structure&S )
00445 {
00446   return S;
00447 }
00448 
00449 inline Structure
00450 operator*
00451 ( const Structure&S, const double c )
00452 {
00453   return S;
00454 }
00455 
00456 inline Structure
00457 operator*
00458 ( const Structure&S1, const Structure&S2 )
00459 {
00460   return Structure::combine( S1, S2, false );
00461 }
00462 
00463 inline Structure
00464 operator/
00465 ( const Structure&S, const double c )
00466 {
00467   return S;
00468 }
00469 
00470 inline Structure
00471 operator/
00472 ( const double c, const Structure&S )
00473 {
00474   return S;
00475 }
00476 
00477 inline Structure
00478 operator/
00479 ( const Structure&S1, const Structure&S2 )
00480 {
00481   return Structure::combine( S1, S2, false );
00482 }
00483 
00484 inline Structure
00485 inv
00486 ( const Structure &S )
00487 {
00488   return Structure::nonlinear( S );
00489 }
00490 
00491 inline Structure
00492 sqr
00493 ( const Structure&S )
00494 {
00495   return Structure::nonlinear( S );
00496 }
00497 
00498 inline Structure
00499 exp
00500 ( const Structure &S )
00501 {
00502   return Structure::nonlinear( S );
00503 }
00504 
00505 inline Structure
00506 arh
00507 ( const Structure &S, const double a )
00508 {
00509   return Structure::nonlinear( S );
00510 }
00511 
00512 inline Structure
00513 log
00514 ( const Structure &S )
00515 {
00516   return Structure::nonlinear( S );
00517 }
00518 
00519 inline Structure
00520 xlog
00521 ( const Structure&S )
00522 {
00523   return Structure::nonlinear( S );
00524 }
00525 
00526 inline Structure
00527 erf
00528 ( const Structure &S )
00529 {
00530   return Structure::nonlinear( S );
00531 }
00532 
00533 inline Structure
00534 erfc
00535 ( const Structure &S )
00536 {
00537   return Structure::nonlinear( S );
00538 }
00539 
00540 inline Structure
00541 sqrt
00542 ( const Structure&S )
00543 {
00544   return Structure::nonlinear( S );
00545 }
00546 
00547 inline Structure
00548 fabs
00549 ( const Structure&S )
00550 {
00551   return Structure::nonlinear( S );
00552 }
00553 
00554 inline Structure
00555 pow
00556 ( const Structure&S, const int n )
00557 {
00558   if( n == 0 ){ Structure S2; return S2; }
00559   if( n == 1 ) return S;
00560   return Structure::nonlinear( S );
00561 }
00562 
00563 inline Structure
00564 pow
00565 ( const Structure&S, const double a )
00566 {
00567   return Structure::nonlinear( S );
00568 }
00569 
00570 inline Structure
00571 pow
00572 ( const Structure&S1, const Structure&S2 )
00573 {
00574   return Structure::combine( S1, S2, false );
00575 }
00576 
00577 inline Structure
00578 min
00579 ( const Structure&S1, const Structure&S2 )
00580 {
00581   return Structure::combine( S1, S2, false );
00582 }
00583 
00584 inline Structure
00585 max
00586 ( const Structure&S1, const Structure&S2 )
00587 {
00588   return Structure::combine( S1, S2, false );
00589 }
00590 
00591 inline Structure
00592 min
00593 ( const unsigned int n, const Structure*S )
00594 {
00595   return Structure::combine( n, S, false );
00596 }
00597 
00598 inline Structure
00599 max
00600 ( const unsigned int n, const Structure*S )
00601 {
00602   return Structure::combine( n, S, false );
00603 }
00604 
00605 inline Structure
00606 cos
00607 ( const Structure&S )
00608 {
00609   return Structure::nonlinear( S );
00610 }
00611 
00612 inline Structure
00613 sin
00614 ( const Structure &S )
00615 {
00616   return Structure::nonlinear( S );
00617 }
00618 
00619 inline Structure
00620 tan
00621 ( const Structure&S )
00622 {
00623   return Structure::nonlinear( S );
00624 }
00625 
00626 inline Structure
00627 acos
00628 ( const Structure &S )
00629 {
00630   return Structure::nonlinear( S );
00631 }
00632 
00633 inline Structure
00634 asin
00635 ( const Structure &S )
00636 {
00637   return Structure::nonlinear( S );
00638 }
00639 
00640 inline Structure
00641 atan
00642 ( const Structure &S )
00643 {
00644   return Structure::nonlinear( S );
00645 }
00646 
00647 inline bool
00648 operator==
00649 ( const Structure&S1, const Structure&S2 )
00650 {
00651   return( S1._dep == S2._dep );
00652 }
00653 
00654 inline bool
00655 operator!=
00656 ( const Structure&S1, const Structure&S2 )
00657 {
00658   return( S1._dep != S2._dep );
00659 }
00660 
00661 inline bool
00662 operator<=
00663 ( const Structure&S1, const Structure&S2 )
00664 {
00665   return( S1._dep <= S2._dep );
00666 }
00667 
00668 inline bool
00669 operator>=
00670 ( const Structure&S1, const Structure&S2 )
00671 {
00672   return( S1._dep >= S2._dep );
00673 }
00674 
00675 inline bool
00676 operator<
00677 ( const Structure&S1, const Structure&S2 )
00678 {
00679   return( S1._dep < S2._dep );
00680 }
00681 
00682 inline bool
00683 operator>
00684 ( const Structure&S1, const Structure&S2 )
00685 {
00686   return( S1._dep > S2._dep );
00687 }
00688 
00689 } // namespace mc
00690 
00691 #endif