Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

/home/slang/XVision2/src/Pipes/PipeModules.h

00001 # ifndef _PIPEMODULES_H_
00002 # define _PIPEMODULES_H_
00003 
00004 # include <XVException.h>
00005 # include <XVFunctoid.h>
00006 # include "Dependency.h"
00007 
00008 // Here defines pipe exception classes. Instead of to abort when a run time 
00009 // error encountered, to throw out an exception and give user a chance to
00010 // catch them is a more elegant way. The nature of the expection can be 
00011 // determined by its type.
00012 // Note: In release version the exception object should contain more 
00013 // information besides type.
00014 
00015 // root of all pipe exceptions
00016 class PipeException : public XVException { protected:
00017   PipeException() : XVException("Pipe Exception") {} 
00018   PipeException( char * err ) : XVException(err) {} };  
00019 
00020 // source exhausted
00021 class BrokenPipe : public PipeException { public:
00022   BrokenPipe() : PipeException("Broken Pipe") {} 
00023   BrokenPipe( char * err ) : PipeException(err) {} };  
00024 
00025 // uninitialized pipe
00026 class UninitPipe : public PipeException { public:
00027   UninitPipe() : PipeException("Uninitialized Pipe") {} 
00028   UninitPipe( char * err ) : PipeException(err) {} };  
00029 
00030 // redefine pipe behavior
00031 class RedefPipe : public PipeException { public:
00032   RedefPipe() : PipeException("Redefined Pipe") {} 
00033   RedefPipe( char * err ) : PipeException(err) {} };  
00034 
00035 // PipeModule is the real calculation unit, and also serves as 
00036 // the root class for hierarchy the pipe classes.
00037 // If an garbage collector is going to be implemented, this is where
00038 // operator new and delete should be overridden.
00039 
00040 template<class T> class Pipe;
00041 
00042 template<class T>
00043 class PipeModule : protected DependencyUnit {
00044   struct Update {
00045     int fc ;
00046     T * addr ;
00047     Update * next ;
00048     Update( int fc, T * addr, Update * next=0 ) :
00049       fc(fc), addr(addr), next(next) {}
00050     ~Update() { delete next ; }
00051   } * head ;
00052 
00053  protected:
00054   void addUpdate( int fc, T * addr ) { head = new Update( fc, addr, head ); }
00055   void update( int fc, const T& data ) {
00056     Update ** p ;
00057     int k = 0 ;
00058     for( p = &head ; *p ; ) {
00059       if( (*p)->fc == fc ) {
00060      *((*p)->addr) = data ;
00061       }
00062       if( fc - (*p)->fc < 0 ) {  // leave it alone
00063      p = &((*p)->next);
00064       }else {                    // delete the node
00065      Update * temp = *p ;
00066      *p = temp->next ;
00067      temp->next = 0 ;
00068      delete temp ;
00069       }
00070     }
00071   }
00072 
00073  protected:          // The real meat of PipeModule
00074   int frame_count ;
00075 
00076   T value ;    // value of current frame count
00077 
00078  protected:
00079 # ifndef NDEBUG
00080   inline void check( bool statement ) const 
00081     { if( !statement ) throw UninitPipe(); }
00082 # else
00083   inline void check( bool ) const {}
00084 # endif
00085 
00086  protected:          // Module dependency and duplication functions
00087 
00088   void setDependency(void) {}
00089   PipeModule<T> * duplicate(void) const { return new PipeModule<T>(*this); }
00090 
00091  public:
00092   typedef T ReturnType ;   // to retrieve the return type from a given template
00093   typedef Pipe<T> ResultType ; // the type returned by operator ()
00094 
00095   PipeModule() : head(0), frame_count(-1) { setDependency(); }
00096   PipeModule( const PipeModule<T>& p ) : DependencyUnit(p),
00097     head(0), frame_count(p.frame_count), value(p.value) // last(p.last) 
00098     { setDependency(); }
00099   PipeModule( const T& x ) : 
00100     head(0), frame_count(-1), value(x) { setDependency(); }
00101 
00102   virtual T current_value(void) const { return value ; }
00103 
00104   virtual T compute_local_fn(int) { return value; }  // for constant lift
00105 
00106   virtual T get_value( int fcin ) {
00107     if( fcin != frame_count ) {            // try to pull out the new value
00108       value = compute_local_fn( fcin );
00109       frame_count = fcin ;
00110       update( frame_count, value );
00111     }
00112     return value ;
00113   }
00114   virtual void get_value( int fcin, T * ptr )  {    // late get
00115     if( fcin != frame_count ) {
00116       addUpdate( fcin, ptr );
00117     }else {
00118       *ptr = value ;
00119     }
00120   }
00121   
00122   virtual T next_value() {
00123     return get_value( frame_count+1 );
00124   }
00125 };
00126 
00127 // Pipe is a handle to the real PipeModule, plus allowing assignment 
00128 // between Pipes in order to construct the graph.
00129 
00130 template <class T>
00131 class Pipe : public PipeModule<T> {
00132  protected:
00133   PipeModule<T> ** module ;   // *module == 0 indicate uninitialized pipe
00134 
00135  protected:
00136   void setDependency(void) { addDependency((DependencyUnit**)module); }
00137   Pipe<T> * duplicate(void) const { return new Pipe<T>(*module); }
00138 
00139   //inline void check(void) const { PipeModule<T>::check( *module ); }
00140   inline void check(void) const { PipeModule<T>::check( *module ); }
00141 
00142  public:
00143   Pipe() : module(new (PipeModule<T> *)(0)) { setDependency(); }
00144   // copy constructor
00145   Pipe( const Pipe& p ) : PipeModule<T>(p), module(p.module) 
00146     { setDependency(); }
00147 
00148   // for constant lifting
00149   Pipe( const T& x ) : module(new (PipeModule<T> *)(new PipeModule<T>(x))) 
00150     { setDependency(); }
00151 
00152   // for internal use
00153   Pipe( PipeModule<T> *v ) : module(new (PipeModule<T> *)(v)) 
00154     { setDependency(); } 
00155 
00156   Pipe<T>& operator = ( const Pipe<T>& p ) 
00157     { 
00158       if( &p != this ) {   // nothing happens for self assignment
00159         if( *module ) throw RedefPipe(); 
00160         //*module = *(p.module); 
00161         *module = new Pipe<T>(p) ;
00162       }
00163       return *this ; 
00164     }
00165 
00166   T current_value(void) const { check(); return (*module)->current_value() ; }
00167   T get_value( int fcin ) { check(); return (*module)->get_value(fcin); }
00168   void get_value( int fcin, T * ptr ) 
00169     { check(); return (*module)->get_value(fcin, ptr); }
00170   T next_value() { check(); return (*module)->next_value(); }
00171   PipeModule<T>* operator ->() { check(); return *module ; }
00172 
00173   void run() 
00174     { check(); try{ for(;;) (*module)->next_value(); } catch(BrokenPipe) {} }
00175   void run( unsigned int n ) 
00176     {
00177       check();
00178       try{
00179      for( int i = 0 ; i < n ; i ++ ) {
00180        (*module)->next_value();
00181      }
00182       }catch(BrokenPipe) {}
00183     }
00184 
00185   template<class Tout, class Tin1> friend class PipeFun1 ;
00186   template<class Tout, class Tin1, class Tin2> friend class PipeFun2 ;
00187 };
00188 
00189 // We now go into "lifting" operators that admit functions to the class.
00190 // There are four types of "lifts:" pure functions, class member functions, 
00191 // "implicit" functions, and operators. Implicit functions are needed 
00192 // becuse C++ doesn't allow template matching based on output type, so we 
00193 // have to artifically add another argument to the function.
00194 // Worth noting that we allow class member functions that change internal 
00195 // class state; if we wanted to be militant, we would require those 
00196 // functions to be "const" on the class, in which case we get the equivalent 
00197 // of closures.
00198 
00199 // Donald: Obviously STL functional library can be used to avoid repetitive 
00200 // code when lifting various form of functions, however, it's still not 
00201 // enough for the task, so instead of extend STL I'm writing a functional 
00202 // class hierarchy of its own, which is in XVFunctoid.h. It's still under
00203 // construction, so we have to use this old and lengthy code for a while.
00204 
00205 // These are "generic" definitions of lifted functions useful for abstracting
00206 // intermediate pipeline expressions --- essentially making the function
00207 // operator "generic."  This is also where we could define partial
00208 // evaluation types generically if we wanted to ...
00209 
00210 template <class Tout>
00211 class PipeLift0 : public PipeModule<Tout>
00212 {
00213 public:
00214 
00215   PipeLift0() : PipeModule<Tout>() {};
00216   PipeLift0( const PipeLift0<Tout>& p ) : PipeModule<Tout>(p) {};
00217 
00218   virtual Pipe<Tout> operator()(void) const = 0;
00219 };
00220 
00221 template <class Tout,class Tin>
00222 class PipeLift1 : public PipeModule<Tout>
00223 {
00224 public:
00225 
00226   PipeLift1() : PipeModule<Tout>() {};
00227   PipeLift1( const PipeLift1<Tout,Tin>& p ) : PipeModule<Tout>(p) {};
00228 
00229   virtual Pipe<Tout> operator()(const Pipe<Tin>&) const = 0;
00230 };
00231 
00232 template <class Tout,class Tin1, class Tin2>
00233 class PipeLift2 : public PipeModule<Tout>
00234 {
00235 public:
00236 
00237   PipeLift2() : PipeModule<Tout>() {};
00238   PipeLift2( const PipeLift2<Tout,Tin1,Tin2>& p ) : PipeModule<Tout>(p) {};
00239 
00240   //virtual Pipe<Tout> operator()(const Pipe<Tin1>&,const Pipe<Tin2>&) const = 0;
00241 };
00242 
00243 
00244 template <class Tout, class Tin1, class Tin2, class Tin3>
00245 class PipeLift3 : public PipeModule<Tout>
00246 {
00247 public:
00248 
00249   PipeLift3() : PipeModule<Tout>() {};
00250   PipeLift3( const PipeLift3<Tout,Tin1,Tin2,Tin3>& p ) : PipeModule<Tout>(p) {};
00251 
00252   virtual Pipe<Tout> operator()(const Pipe<Tin1>&,const Pipe<Tin2>&, const Pipe<Tin3> &) const = 0;
00253 };
00254 
00255 
00256 // 1. Pure functions, in form of Tout func( Tin1, Tin2, ... )
00257 
00258 template<class Tout>
00259 class PipeModuleLift0 : public PipeLift0<Tout> {
00260   typedef PipeModuleLift0<Tout> ThisType ;
00261   typedef PipeLift0<Tout> BaseType ;
00262  protected:
00263   typedef Tout (*Lift0Type)(void);
00264   Lift0Type fn ;
00265 
00266  protected:
00267 
00268   void setDependency(void) {}
00269   ThisType * duplicate(void) const { return new ThisType(*this);}
00270 
00271  protected:
00272 
00273   inline void check(void) { PipeModule<Tout>::check( fn ); }
00274 
00275  public:
00276 
00277   PipeModuleLift0( Lift0Type fnin ) : fn(fnin) { setDependency(); }
00278   PipeModuleLift0( const ThisType& p ) : BaseType(p), 
00279     fn(p.fn) { setDependency(); }
00280 
00281   operator Pipe<Tout> () const { return Pipe<Tout>(dupilcate()); }
00282 
00283   Pipe<Tout> operator ()(void) const { return Pipe<Tout>(duplicate()); }
00284 
00285   Tout compute_local_fn( int fc ) { check(); return fn(); }
00286 };
00287 
00288 // Lift functions from element to pipe level
00289 // Use a PipeModule to represent that function
00290 // Note that liftP is overloaded for all applied lift classes.
00291 
00292 template<class Tout> 
00293 inline Pipe<Tout> liftP( Tout (*fn)(void) ) {
00294   return Pipe<Tout>(new PipeModuleLift0<Tout>(fn));
00295 }
00296 
00297 template <class Tout, class Tin1, class Fn>
00298 class PipeModuleLift1 : public PipeLift1<Tout,Tin1> {
00299   typedef PipeModuleLift1<Tout,Tin1,Fn> ThisType ;
00300   typedef PipeLift1<Tout,Tin1> BaseType ;
00301  protected:
00302   Fn fn ;
00303   Pipe<Tin1> *pred1 ;
00304 
00305  protected:
00306 
00307   void setDependency(void) { addDependency((DependencyUnit**)&pred1); }
00308   ThisType * duplicate(void) const { return new ThisType(*this); }
00309 
00310   inline void check(void) 
00311     { PipeModule<Tout>::check( (bool)fn && pred1 ); }
00312 
00313  public:
00314 
00315   PipeModuleLift1( Fn fnin ) : fn(fnin), pred1(0) { setDependency(); } 
00316   PipeModuleLift1( const ThisType& p ) : 
00317     BaseType(p), fn(p.fn), pred1(p.pred1) { setDependency(); } 
00318 
00319   Pipe<Tout> operator ()( const Pipe<Tin1>& x ) const 
00320     { 
00321       ThisType *p = duplicate();
00322       p->pred1 = new Pipe<Tin1>(x) ;
00323       return Pipe<Tout>(p) ; 
00324     }
00325 
00326   Tout compute_local_fn( int fc ) 
00327     { check(); return fn(pred1->get_value(fc)); }
00328 };
00329 
00330 template<class Tout, class Tin1>
00331 class PipeModuleLift1Types {
00332  public:
00333   typedef PipeModuleLift1<Tout,Tin1,Tout (*)(Tin1)> Val;
00334   typedef PipeModuleLift1<Tout,Tin1,Tout (*)(const Tin1&)> Ref;
00335 };
00336 
00337 template<class Tout, class Tin1> 
00338 inline PipeModuleLift1<Tout, Tin1, Tout (*)(Tin1)> 
00339 liftP( Tout (*fn)(Tin1) ) {
00340   return PipeModuleLift1<Tout,Tin1,Tout (*)(Tin1)>(fn);
00341 }
00342 template<class Tout, class Tin1> 
00343 inline PipeModuleLift1<Tout, Tin1, Tout (*)(const Tin1&)> 
00344 liftP( Tout (*fn)(const Tin1&) ) {
00345   return PipeModuleLift1<Tout,Tin1,Tout (*)(const Tin1&)>(fn);
00346 }
00347 
00348 
00349 template <class Tout, class Tin1, class Tin2, class Fn>
00350 class PipeModuleLift2 : public PipeLift2<Tout,Tin1,Tin2> {
00351   typedef PipeModuleLift2<Tout,Tin1,Tin2,Fn> ThisType ;
00352   typedef PipeLift2<Tout,Tin1,Tin2> BaseType ;
00353  protected:
00354   Fn fn ;
00355   Pipe<Tin1> *pred1 ;
00356   Pipe<Tin2> *pred2 ;
00357 
00358  protected:
00359 
00360   void setDependency(void) 
00361     { 
00362       addDependency((DependencyUnit**)&pred1); 
00363       addDependency((DependencyUnit**)&pred2); 
00364     }
00365   ThisType * duplicate(void) const { return new ThisType(*this); }
00366 
00367   inline void check(void) 
00368     { PipeModule<Tout>::check( (bool)fn&&pred1&&pred2 ); }
00369 
00370  public:
00371 
00372   PipeModuleLift2( Fn fnin ) : fn(fnin), pred1(0), pred2(0) 
00373     { setDependency(); } 
00374   PipeModuleLift2( const ThisType& p ) : BaseType(p), fn(p.fn), 
00375     pred1(p.pred1), pred2(p.pred2) { setDependency(); } 
00376 
00377   virtual Pipe<Tout> operator ()( const Pipe<Tin1>& x1, const Pipe<Tin2>& x2 ) const
00378     { 
00379       ThisType *p = duplicate();
00380       p->pred1 = new Pipe<Tin1>(x1); 
00381       p->pred2 = new Pipe<Tin2>(x2); 
00382       return Pipe<Tout>(p) ; 
00383     }
00384 
00385   Tout compute_local_fn( int fc ) 
00386     { 
00387       check(); 
00388       return fn(pred1->get_value(fc),pred2->get_value(fc));
00389     }
00390 };
00391 
00392 template<class Tout, class Tin1, class Tin2>
00393 class PipeModuleLift2Types {
00394  public:
00395   typedef PipeModuleLift2<Tout,Tin1,Tin2,Tout (*)(Tin1,Tin2)> Val;
00396   typedef PipeModuleLift2<Tout,Tin1,Tin2,
00397     Tout (*)(const Tin1&,const Tin2&)> Ref;
00398 };
00399 
00400 template<class Tout, class Tin1, class Tin2> 
00401 inline PipeModuleLift2<Tout, Tin1, Tin2, Tout (*)(Tin1,Tin2)> 
00402 liftP( Tout (*fn)(Tin1,Tin2) ) {
00403   return PipeModuleLift2<Tout,Tin1,Tin2,Tout (*)(Tin1,Tin2)>(fn);
00404 }
00405 template<class Tout, class Tin1, class Tin2> 
00406 inline PipeModuleLift2<Tout, Tin1, Tin2, Tout (*)(const Tin1&,Tin2)> 
00407 liftP( Tout (*fn)(const Tin1&,Tin2) ) {
00408   return PipeModuleLift2<Tout,Tin1,Tin2,Tout (*)(const Tin1&,Tin2)>(fn);
00409 }
00410 template<class Tout, class Tin1, class Tin2> 
00411 inline PipeModuleLift2<Tout, Tin1, Tin2, Tout (*)(Tin1,const Tin2&)> 
00412 liftP( Tout (*fn)(Tin1,const Tin2&) ) {
00413   return PipeModuleLift2<Tout,Tin1,Tin2,Tout (*)(Tin1,const Tin2&)>(fn);
00414 }
00415 template<class Tout, class Tin1, class Tin2> 
00416 inline PipeModuleLift2<Tout, Tin1, Tin2, Tout (*)(const Tin1&,const Tin2&)> 
00417 liftP( Tout (*fn)(const Tin1&,const Tin2&) ) {
00418   return PipeModuleLift2<Tout,Tin1,Tin2,Tout (*)(const Tin1&,const Tin2&)>(fn);
00419 }
00420 
00421 template <class Tout, class Tin1, class Tin2, class Tin3, class Fn>
00422 class PipeModuleLift3 : public PipeLift3<Tout,Tin1,Tin2,Tin3> {
00423   typedef PipeModuleLift3<Tout,Tin1,Tin2,Tin3,Fn> ThisType ;
00424   typedef PipeLift3<Tout,Tin1,Tin2,Tin3> BaseType ;
00425  protected:
00426   Fn fn ;
00427   Pipe<Tin1> *pred1 ;
00428   Pipe<Tin2> *pred2 ;
00429   Pipe<Tin3> *pred3 ;
00430 
00431  protected:
00432 
00433   void setDependency(void) 
00434     { 
00435       addDependency((DependencyUnit**)&pred1); 
00436       addDependency((DependencyUnit**)&pred2); 
00437       addDependency((DependencyUnit**)&pred3); 
00438     }
00439   ThisType * duplicate(void) const { return new ThisType(*this); }
00440 
00441   inline void check(void) 
00442     { PipeModule<Tout>::check( (bool)fn && pred1 && pred2 && pred3 ); }
00443 
00444  public:
00445 
00446   PipeModuleLift3( Fn fnin ) : fn(fnin), pred1(0), pred2(0), pred3(0) 
00447     { setDependency(); } 
00448   PipeModuleLift3( const ThisType& p ) : BaseType(p), fn(p.fn), 
00449     pred1(p.pred1), pred2(p.pred2), pred3(p.pred3) { setDependency(); }
00450  
00451   Pipe<Tout> operator ()( const Pipe<Tin1>& x1, const Pipe<Tin2>& x2,
00452                           const Pipe<Tin3>& x3 ) const
00453     { 
00454       ThisType *p = duplicate();
00455       p->pred1 = new Pipe<Tin1>(x1); 
00456       p->pred2 = new Pipe<Tin2>(x2); 
00457       p->pred3 = new Pipe<Tin3>(x3);
00458       return Pipe<Tout>(p) ; 
00459     }
00460 
00461   Tout compute_local_fn( int fc ) 
00462     { 
00463       check(); 
00464       return fn(pred1->get_value(fc),pred2->get_value(fc),
00465           pred3->get_value(fc)); 
00466     }
00467 };
00468 
00469 template<class Tout, class Tin1, class Tin2, class Tin3>
00470 class PipeModuleLift3Types {
00471  public:
00472   typedef PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00473     Tout (*)(Tin1,Tin2,Tin3)> Val;
00474   typedef PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00475     Tout (*)(const Tin1&,const Tin2&,const Tin3&)> Ref;
00476 };
00477 
00478 template<class Tout, class Tin1, class Tin2, class Tin3> 
00479 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00480   Tout (*)(Tin1,Tin2,Tin3)> 
00481 liftP( Tout (*fn)(Tin1,Tin2,Tin3) ) {
00482   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00483     Tout (*)(Tin1,Tin2,Tin3)>(fn);
00484 }
00485 template<class Tout, class Tin1, class Tin2, class Tin3> 
00486 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00487   Tout (*)(Tin1,Tin2,const Tin3&)> 
00488 liftP( Tout (*fn)(Tin1,Tin2,const Tin3&) ) {
00489   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00490     Tout (*)(Tin1,Tin2,const Tin3&)>(fn);
00491 }
00492 template<class Tout, class Tin1, class Tin2, class Tin3> 
00493 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00494   Tout (*)(Tin1,const Tin2&,Tin3)> 
00495 liftP( Tout (*fn)(Tin1,const Tin2&,Tin3) ) {
00496   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00497     Tout (*)(Tin1,const Tin2&,Tin3)>(fn);
00498 }
00499 template<class Tout, class Tin1, class Tin2, class Tin3> 
00500 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00501   Tout (*)(Tin1,const Tin2&,const Tin3&)> 
00502 liftP( Tout (*fn)(Tin1,const Tin2&,const Tin3&) ) {
00503   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00504     Tout (*)(Tin1,const Tin2&,const Tin3&)>(fn);
00505 }
00506 template<class Tout, class Tin1, class Tin2, class Tin3> 
00507 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00508   Tout (*)(const Tin1&,Tin2,Tin3)> 
00509 liftP( Tout (*fn)(const Tin1&,Tin2,Tin3) ) {
00510   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00511     Tout (*)(const Tin1&,Tin2,Tin3)>(fn);
00512 }
00513 template<class Tout, class Tin1, class Tin2, class Tin3> 
00514 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00515   Tout (*)(const Tin1&,Tin2,const Tin3&)> 
00516 liftP( Tout (*fn)(const Tin1&,Tin2,const Tin3&) ) {
00517   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00518     Tout (*)(const Tin1&,Tin2,const Tin3&)>(fn);
00519 }
00520 template<class Tout, class Tin1, class Tin2, class Tin3> 
00521 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00522   Tout (*)(const Tin1&,const Tin2&,Tin3)> 
00523 liftP( Tout (*fn)(const Tin1&,const Tin2&,Tin3) ) {
00524   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00525     Tout (*)(const Tin1&,const Tin2&,Tin3)>(fn);
00526 }
00527 template<class Tout, class Tin1, class Tin2, class Tin3> 
00528 inline PipeModuleLift3<Tout, Tin1, Tin2, Tin3, 
00529   Tout (*)(const Tin1&,const Tin2&,const Tin3&)> 
00530 liftP( Tout (*fn)(const Tin1&,const Tin2&,const Tin3&) ) {
00531   return PipeModuleLift3<Tout,Tin1,Tin2,Tin3,
00532     Tout (*)(const Tin1&,const Tin2&,const Tin3&)>(fn);
00533 }
00534 
00535 // Code marked obsolete are no longer being maintained and the use
00536 // is NOT recommended, as certain bugs may exist.
00537 // A replacement to Functoid approach will be implemented soon
00538 
00539 // ----------------------------------------------------------------
00540 // Obsolete code starts 
00541 
00542 // 2. Implicit functions, in form of Tvoid func( const Tin1&, ..., Tout& )
00543 // or Tvoid func( Tout&, const Tin1&, ... )
00544 
00545 template<class Tout, class Tvoid=Tout>
00546 class PipeModuleLiftImplicit0 : public PipeLift0<Tout> {
00547   typedef PipeModuleLiftImplicit0<Tout,Tvoid> ThisType ;
00548   typedef PipeLift0<Tout> BaseType ;
00549  protected:  
00550   typedef Tvoid (*LiftImp0Type)( Tout& y );
00551   LiftImp0Type fn ;
00552   
00553  protected:
00554 
00555   void setDependency(void) {}
00556   ThisType * duplicate(void) const { return new ThisType(*this); }
00557 
00558  protected:
00559 
00560   inline void check(void) { PipeModule<Tout>::check( fn ); }
00561 
00562  public:
00563  
00564   PipeModuleLiftImplicit0( LiftImp0Type fnin ) : fn(fnin) 
00565     { setDependency(); }
00566   PipeModuleLiftImplicit0( const ThisType& p) : 
00567     BaseType(p), fn(p.fn) { setDependency(); }
00568   operator Pipe<Tout> () const { return Pipe<Tout>(duplicate()); }
00569 
00570   Pipe<Tout> operator ()(void) const { return Pipe<Tout>(duplicate()); }
00571 
00572   Tout compute_local_fn( int fc ) { check(); fn(value); return value ; }
00573 };
00574 
00575 template<class Tout, class Tvoid>
00576  inline Pipe<Tout> liftP( Tvoid (*fn)(Tout&) ) {
00577   return Pipe<Tout>(new PipeModuleLiftImplicit0<Tout,Tvoid>(fn)) ; 
00578 }
00579 
00580 template<class Tout, class Tin1, class Tvoid=Tout>
00581 class PipeModuleLiftImplicit1 : public PipeLift1<Tout,Tin1> {
00582   typedef PipeModuleLiftImplicit1<Tout,Tin1,Tvoid> ThisType ;
00583  protected:
00584   typedef Tvoid (*LiftImp1Type1)( const Tin1& x1, Tout& y );
00585   typedef Tvoid (*LiftImp1Type2)( Tout& y, const Tin1& x1 );
00586   LiftImp1Type1 fn1 ;
00587   LiftImp1Type2 fn2 ;
00588   int which_fn ;
00589   Pipe<Tin1> *pred1 ;
00590 
00591  protected:
00592 
00593   void setDependency(void) { addDependency((DependencyUnit**)&pred1); }
00594   ThisType * duplicate(void) const { return new ThisType(*this); }
00595 
00596   inline void check(void)
00597     { PipeModule<Tout>::check( (which_fn==1?fn1!=0:fn2!=0) && pred1 ); }
00598 
00599  public:
00600   
00601   PipeModuleLiftImplicit1( LiftImp1Type1 fnin ) : 
00602     fn1(fnin), fn2(0), which_fn(1), pred1(0) { setDependency(); }
00603   PipeModuleLiftImplicit1( LiftImp1Type2 fnin ) : 
00604     fn1(0), fn2(fnin), which_fn(2), pred1(0) { setDependency(); }
00605   PipeModuleLiftImplicit1( const PipeModuleLiftImplicit1<Tout,Tin1,Tvoid>& p ):
00606     PipeLift1<Tout,Tin1>(p), fn1(p.fn1), fn2(p.fn2), 
00607     which_fn(p.which_fn), pred1(p.pred1) { setDependency(); }
00608 
00609   Pipe<Tout> operator () ( const Pipe<Tin1>& x1 ) const
00610     {
00611       PipeModuleLiftImplicit1<Tout,Tin1,Tvoid> *p = 
00612         new PipeModuleLiftImplicit1<Tout,Tin1,Tvoid>(*this) ;
00613       p->pred1 = new Pipe<Tin1>(x1);
00614       return Pipe<Tout>(p);
00615     }
00616 
00617   Tout compute_local_fn( int fc ) 
00618     { 
00619       check(); 
00620       if( which_fn == 1 ) {
00621         (*fn1)( pred1->get_value(fc), value ); 
00622       }else {   // which_fn == 2
00623         (*fn2)( value, pred1->get_value(fc) );
00624       }
00625       return value ; 
00626     }
00627 };
00628 
00629 template<class Tout, class Tin1, class Tvoid>
00630 inline PipeModuleLiftImplicit1<Tout, Tin1, Tvoid> 
00631 liftP( Tvoid (*fn)(const Tin1&, Tout&) ) {
00632   return PipeModuleLiftImplicit1<Tout,Tin1,Tvoid>(fn) ;
00633 }
00634 
00635 template<class Tout, class Tin1, class Tvoid>
00636 inline PipeModuleLiftImplicit1<Tout, Tin1, Tvoid> 
00637 liftP( Tvoid (*fn)(Tout&, const Tin1&) ) {
00638   return PipeModuleLiftImplicit1<Tout,Tin1,Tvoid>(fn) ;
00639 }
00640 
00641 // 3. Class member functions
00642 
00643 template<class Tout, class Tclass, class Fn>
00644 class PipeModuleLiftClass0 : public PipeLift0<Tout> {
00645   typedef PipeModuleLiftClass0<Tout,Tclass,Fn> ThisType ;
00646  protected:
00647   Fn fn ;
00648   Pipe<Tclass> * predc ;
00649 
00650  protected:
00651   void setDependency(void) { addDependency((DependencyUnit**)&predc); }
00652   ThisType * duplicate(void) const { return new ThisType(*this); }
00653 
00654   inline void check(void) 
00655     { PipeModule<Tout>::check( (bool)fn && predc ); }
00656 
00657  public:
00658 
00659   PipeModuleLiftClass0( Fn fnin ) : fn(fnin), predc(0) { setDependency(); }
00660   PipeModuleLiftClass0( const Pipe<Tclass>& p, Fn fnin ) :
00661     fn(fnin), predc(new Pipe<Tclass>(p)) { setDependency(); }
00662   PipeModuleLiftClass0( const ThisType& p ) : PipeLift0<Tout>(p),
00663     fn(p.fn), predc(p.predc) { setDependency(); }
00664 
00665   Pipe<Tout> operator ()(void) const 
00666     {
00667       ThisType *p = new ThisType(*this);
00668       return Pipe<Tout>(p);
00669     }
00670 
00671   Pipe<Tout> operator ()( const Pipe<Tclass>& x ) const 
00672     {
00673       if( predc ) throw RedefPipe() ;
00674       ThisType *p = new ThisType(*this);
00675       p->predc = new Pipe<Tclass>(x);
00676       return Pipe<Tout>(p);
00677     }
00678 
00679   Tout compute_local_fn( int fc )
00680     { check(); return (predc->get_value(fc).*fn)(); }
00681 };
00682 
00683 template<class Tout, class Tclass>
00684 inline PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void)>
00685 liftP( const Pipe<Tclass>& p, Tout (Tclass::*fn)(void) ) {
00686   return PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void)>( p, fn );
00687 }
00688 template<class Tout, class Tclass>
00689 inline PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void)>
00690 liftP( Tout (Tclass::*fn)(void) ) {
00691   return PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void)>( fn );
00692 }
00693 template<class Tout, class Tclass>
00694 inline PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void) const>
00695 liftP( const Pipe<Tclass>& p, Tout (Tclass::*fn)(void) const ) {
00696   return PipeModuleLiftClass0<Tout, Tclass, 
00697     Tout (Tclass::*)(void) const>( p, fn );
00698 }
00699 template<class Tout, class Tclass>
00700 inline PipeModuleLiftClass0<Tout, Tclass, Tout (Tclass::*)(void) const>
00701 liftP( Tout (Tclass::*fn)(void) const ) {
00702   return PipeModuleLiftClass0<Tout, Tclass,
00703     Tout (Tclass::*)(void) const>( fn );
00704 }
00705 
00706 template<class Tout, class Tclass, class Tin1, class Fn>
00707 class PipeModuleLiftClass1 : public PipeModule<Tout> {
00708   typedef PipeModuleLiftClass1<Tout,Tclass,Tin1,Fn> ThisType ;
00709  protected:
00710   Fn fn ;
00711   Pipe<Tclass> * predc ;
00712   Pipe<Tin1> * pred1 ;
00713 
00714  protected:
00715   void setDependency(void) 
00716     { 
00717       addDependency((DependencyUnit**)&predc); 
00718       addDependency((DependencyUnit**)&pred1); 
00719     }
00720   ThisType * duplicate(void) const { return new ThisType(*this); }
00721 
00722   inline void check(void) 
00723     { PipeModule<Tout>::check( (bool)fn && predc && pred1 ); }
00724 
00725  public:
00726 
00727   PipeModuleLiftClass1( Fn fnin ) : 
00728     fn(fnin), predc(0), pred1(0) { setDependency(); }
00729   PipeModuleLiftClass1( const ThisType& p ) : PipeModule<Tout>(p),
00730     fn(p.fn), predc(p.predc), pred1(p.pred1) { setDependency(); }
00731 
00732   Pipe<Tout> operator ()( const Pipe<Tclass>& t, const Pipe<Tin1>& x1 ) const 
00733     {
00734       ThisType *p = new ThisType(*this);
00735       p->predc = new Pipe<Tclass>(t);
00736       p->pred1 = new Pipe<Tin1>(x1);
00737       return Pipe<Tout>(p);
00738     }
00739 
00740   Tout compute_local_fn( int fc )
00741     { check(); return (predc->get_value(fc).*fn)(pred1->get_value(fc)); }
00742 };
00743 
00744 template<class Tout, class Tclass, class Tin1>
00745 inline PipeModuleLiftClass1<Tout, Tclass, Tin1, Tout (Tclass::*)(Tin1)>
00746 liftP( Tout (Tclass::*fn)(Tin1) ) {
00747   return PipeModuleLiftClass1<Tout, Tclass, Tin1, 
00748     Tout (Tclass::*)(Tin1)>( fn );
00749 }
00750 template<class Tout, class Tclass, class Tin1>
00751 inline PipeModuleLiftClass1<Tout, Tclass, Tin1, Tout (Tclass::*)(const Tin1&)>
00752 liftP( Tout (Tclass::*fn)(const Tin1&) ) {
00753   return PipeModuleLiftClass1<Tout, Tclass, Tin1, 
00754     Tout (Tclass::*)(const Tin1&)>( fn );
00755 }
00756 
00757 // PipeModeleClassLift -- Tclass is not pipe here, different from above
00758 
00759 template<class Tout, class Tclass, class Fn>
00760 class PipeModuleClassLift0 : public PipeModule<Tout> {
00761   typedef PipeModuleClassLift0<Tout,Tclass,Fn> ThisType;
00762  protected:
00763   Tclass host ;
00764   Fn fn ;
00765 
00766  protected:
00767 
00768   void setDependency(void) {}
00769   ThisType * duplicate(void) const { return new ThisType(*this);}
00770 
00771  protected:
00772 
00773   inline void check(void) { PipeModule<Tout>::check( fn ); }
00774 
00775  public:
00776 
00777   PipeModuleClassLift0( const Tclass& obj, Fn fnin ) : host(obj), fn(fnin) 
00778     { setDependency(); }
00779   PipeModuleClassLift0( const ThisType& p ) : PipeModule<Tout>(p),
00780     host(p.host), fn(p.fn) { setDependency(); }
00781 
00782   operator Pipe<Tout> () const 
00783     { return Pipe<Tout>(new ThisType(*this)); }
00784 
00785   Pipe<Tout> operator ()(void) const
00786     { ThisType *p = new ThisType(*this) ; return Pipe<Tout>(p) ; }
00787 
00788   Tout compute_local_fn( int fc ) { check(); return (host.*fn)(); }
00789 };
00790 
00791 template<class Tout, class Tclass> 
00792 inline Pipe<Tout> liftP( const Tclass& obj, Tout (Tclass::*fn)(void) ) {
00793   return Pipe<Tout>(new PipeModuleClassLift0
00794               <Tout,Tclass,Tout (Tclass::*)(void)>(obj,fn));
00795 }
00796 template<class Tout, class Tclass> 
00797 inline Pipe<Tout> liftP( const Tclass& obj, Tout (Tclass::*fn)(void) const ) {
00798   return Pipe<Tout>(new PipeModuleClassLift0
00799               <Tout,Tclass,Tout (Tclass::*)(void) const>(obj,fn));
00800 }
00801 
00802 template<class Tout, class Tin1, class Tclass, class Fn>
00803 class PipeModuleClassLift1 : public PipeLift1<Tout,Tin1> {
00804   typedef PipeModuleClassLift1<Tout,Tin1,Tclass,Fn> ThisType;
00805  protected:
00806   Tclass host ;
00807   Fn fn ;
00808   Pipe<Tin1> * pred1 ;
00809 
00810  protected:
00811 
00812   void setDependency(void) { addDependency((DependencyUnit**)&pred1); }
00813   ThisType * duplicate(void) const { return new ThisType(*this);}
00814 
00815   inline void check(void) { PipeModule<Tout>::check( (bool)fn && pred1 ); }
00816 
00817  public:
00818 
00819   PipeModuleClassLift1( const Tclass& obj, Fn fnin ) : 
00820     host(obj), fn(fnin), pred1(0) { setDependency(); }
00821   PipeModuleClassLift1( const ThisType& p ) : PipeLift1<Tout,Tin1>(p),
00822     host(p.host), fn(p.fn), pred1(p.pred1) { setDependency(); }
00823 
00824   Pipe<Tout> operator ()( const Pipe<Tin1>& x1 ) const
00825     { 
00826       ThisType *p = new ThisType(*this) ; 
00827       p->pred1 = new Pipe<Tin1>(x1) ;
00828       return Pipe<Tout>(p) ; 
00829     }
00830 
00831   Tout compute_local_fn( int fc ) 
00832     { check(); return (host.*fn)(pred1->get_value(fc)); }
00833 };
00834 
00835 template<class Tout, class Tin, class Tclass> 
00836 inline PipeModuleClassLift1<Tout,Tin,Tclass,Tout (Tclass::*)(Tin)>
00837 liftP( const Tclass& obj, Tout (Tclass::*fn)(Tin) ) {
00838   return PipeModuleClassLift1 <Tout,Tin,Tclass,Tout (Tclass::*)(Tin)>(obj,fn);
00839 }
00840 template<class Tout, class Tin, class Tclass> 
00841 inline PipeModuleClassLift1<Tout,Tin,Tclass,Tout (Tclass::*)(Tin) const>
00842 liftP( const Tclass& obj, Tout (Tclass::*fn)(Tin) const ) {
00843   return PipeModuleClassLift1
00844     <Tout,Tin,Tclass,Tout (Tclass::*)(Tin) const>(obj,fn);
00845 }
00846 template<class Tout, class Tin, class Tclass> 
00847 inline PipeModuleClassLift1<Tout,Tin,Tclass,Tout (Tclass::*)(const Tin&)>
00848 liftP( const Tclass& obj, Tout (Tclass::*fn)(const Tin&) ) {
00849   return PipeModuleClassLift1
00850     <Tout,Tin,Tclass,Tout (Tclass::*)(const Tin&)>(obj,fn);
00851 }
00852 template<class Tout, class Tin, class Tclass> 
00853 inline PipeModuleClassLift1
00854   <Tout,Tin,Tclass,Tout (Tclass::*)(const Tin&) const>
00855 liftP( const Tclass& obj, Tout (Tclass::*fn)(const Tin&) const ) {
00856   return PipeModuleClassLift1
00857     <Tout,Tin,Tclass,Tout (Tclass::*)(const Tin&) const>(obj,fn);
00858 }
00859 
00860 // Obsolete code ends...
00861 // --------------------------------------------------------------------
00862 
00863 // Lift for date member
00864 
00865 template<class Tout, class Tclass>
00866 inline PipeModuleLift1<Tout,Tclass,XVDataMemFun<Tout Tclass::*,Tout,Tclass> >
00867 liftP( Tout Tclass::*f ) {
00868   return PipeModuleLift1<Tout,Tclass,XVDataMemFun<Tout Tclass::*,Tout,Tclass> >
00869     (XVDataMemFun<Tout Tclass::*,Tout,Tclass>(f));
00870 }
00871 
00872 template<class T1, class T2>
00873 inline T1 implicitCast( const T2& x ) {
00874   return x ;
00875 }
00876 
00877 template <class T1, class T2>
00878 inline Pipe<T1> castP( const Pipe<T2>& x ) {
00879   PipeModuleLift1<T1,T2,T1 (*)(const T2&)> cast(implicitCast<T1,T2>);
00880   return cast(x) ;
00881 }
00882 
00883 // Delay module, basically just pass frame_count-1 down
00884 
00885 template<class T>
00886 class PipeDelay : public PipeModule<T> {
00887 
00888   //bool been_called ;
00889   T next ;
00890   Pipe<T> *pred ;
00891 
00892  protected:
00893 
00894   void setDependency(void) { addDependency((DependencyUnit**)&pred); }
00895   PipeDelay<T> * duplicate(void) const { return new PipeDelay<T>(*this); }
00896 
00897   inline void check(void) { PipeModule<T>::check( pred ); }
00898 
00899  public:
00900 
00901   PipeDelay( const T& x ) : next(x), pred(0) { setDependency(); }
00902   PipeDelay( const PipeDelay<T>& p ) : PipeModule<T>(p), 
00903     next(p.next), pred(p.pred) { setDependency(); }
00904 
00905   Pipe<T> operator () ( const Pipe<T>& x ) const
00906     { 
00907       PipeDelay<T> *p = new PipeDelay<T>(*this);
00908       p->pred = new Pipe<T>(x) ; 
00909       return Pipe<T>(p); 
00910     }
00911 
00912   void get_value( int fc, T * addr ) { *addr = get_value( fc ); }
00913 
00914   T get_value( int fc )
00915     {
00916       if( fc != frame_count ) {
00917      check();
00918      value = next ;
00919      frame_count = fc ;
00920      update( frame_count, value );
00921      pred->get_value( fc, &next ); 
00922       }
00923       return value ;
00924     }
00925 };
00926 
00927 template<class T>
00928 inline PipeDelay<T> delayP( const T& x ) {
00929   return PipeDelay<T>(x) ;
00930 }
00931 
00932 // Pipe operator <<=
00933 
00934 template<class T1, class T2>
00935 inline typename T1::ResultType 
00936 operator <<= ( const T1& x1, const T2& x2 ) {
00937   return x1(x2);
00938 }
00939 
00940 // Pipe operator >>=, means connect two pipes but only use data from second one
00941 
00942 template<class T1, class T2>
00943 inline T2 useSecondPipe( const T1&, const T2& x2 ) { return x2 ; }
00944 
00945 template<class T1, class T2>
00946 inline Pipe<T2> operator >>= ( const Pipe<T1>& p1, const Pipe<T2>& p2 ) {
00947   PipeModuleLift2<T2,T1,T2,T2 (*)(const T1&,const T2&)> p(useSecondPipe<T1,T2>);
00948   return p( p1, p2 ) ;
00949 }
00950 
00951 # define PARALLEL_P >>=
00952 
00953 // 4. Binary operators
00954 // Here the assumption is that the return type of binary operators
00955 // is same as its first operand. 
00956 
00957 #define LiftBinOp(OP,NM) \
00958 template<class Tout, class Tin1, class Tin2>\
00959 class PipeModuleLiftBin##NM: public PipeModule<Tout> {\
00960   typedef PipeModuleLiftBin##NM<Tout,Tin1,Tin2> ThisType ; \
00961  protected:\
00962   Pipe<Tin1> *pred1; \
00963   Pipe<Tin2> *pred2; \
00964 \
00965  protected:\
00966   void setDependency(void) \
00967   { \
00968     addDependency((DependencyUnit**)&pred1); \
00969     addDependency((DependencyUnit**)&pred2); \
00970   } \
00971   ThisType * duplicate(void) const { return new ThisType(*this); } \
00972 \
00973   inline void check(void) { PipeModule<Tout>::check( pred1 && pred2 ); }\
00974 \
00975  public:\
00976 \
00977   PipeModuleLiftBin##NM(const Pipe<Tin1>& x, const Pipe<Tin2>& y) : \
00978    PipeModule<Tout>(), pred1(new Pipe<Tin1>(x)), pred2(new Pipe<Tin2>(y)) \
00979    { setDependency(); } \
00980   PipeModuleLiftBin##NM( const ThisType& p) : \
00981    PipeModule<Tout>(p), pred1(p.pred1), pred2(p.pred2) \
00982    { setDependency(); } \
00983 \
00984   Tout compute_local_fn(int fc) \
00985       { check(); return pred1->get_value(fc) OP pred2->get_value(fc) ; } \
00986 };\
00987 \
00988 template <class T1, class T2>\
00989 Pipe<T1> operator OP(const Pipe<T1>& x, const Pipe<T2>& y)\
00990 {\
00991   return Pipe<T1>(new PipeModuleLiftBin##NM<T1,T1,T2>(x,y));\
00992 }\
00993 template <class T1, class T2>\
00994 Pipe<T1> operator OP( const Pipe<T1>& x, const T2 y)\
00995 {\
00996   return Pipe<T1>(new PipeModuleLiftBin##NM<T1,T1,T2>(x,y));\
00997 }\
00998 template <class T1, class T2>\
00999 Pipe<T1> &operator OP(const T1 x, const Pipe<T2>& y)\
01000 {\
01001   return Pipe<T1>(new PipeModuleLiftBin##NM<T1,T1,T2>(x,y));\
01002 }\
01003 
01004 LiftBinOp(+,Plus);
01005 LiftBinOp(-,Minus);
01006 LiftBinOp(*,Multiply);
01007 LiftBinOp(/,Divide);
01008 LiftBinOp(<<,LeftShift);
01009 LiftBinOp(>>,RightShift);
01010 //LiftBinOp(&&,LogicalAnd);
01011 //LiftBinOp(||,LogicalOr);
01012 LiftBinOp(&,BitwiseAnd);
01013 LiftBinOp(|,BitWiseOr);
01014 
01015 // Unary operators
01016 // Here the assumption is that the return type of unary operators
01017 // is same as its operand. 
01018 
01019 #define LiftUnOp(OP,NM) \
01020 template<class T>\
01021 class PipeModuleLiftUn##NM: public PipeModule<T> {\
01022   typedef PipeModuleLiftUn##NM<T> ThisType ; \
01023  protected:\
01024   Pipe<T> *pred; \
01025 \
01026  protected:\
01027   void setDependency(void) { addDependency((DependencyUnit**)&pred); } \
01028 \
01029   ThisType * duplicate(void) const { return new ThisType(*this); } \
01030 \
01031   inline void check(void) { PipeModule<T>::check( pred ); }\
01032 \
01033  public:\
01034 \
01035   PipeModuleLiftUn##NM( const Pipe<T>& x ) : \
01036    PipeModule<T>(), pred(new Pipe<T>(x)) { setDependency(); } \
01037   PipeModuleLiftUn##NM( const ThisType& p ) : \
01038    PipeModule<T>(p), pred(p.pred) { setDependency(); } \
01039 \
01040   T compute_local_fn(int fc) { check(); return OP pred->get_value(fc); } \
01041 };\
01042 \
01043 template<class T> \
01044 inline Pipe<T> operator OP ( const Pipe<T>& x ) { \
01045   return Pipe<T>(new PipeModuleLiftUn##NM<T>(x)) ; \
01046 } \
01047 
01048 LiftUnOp(!,Not)
01049 
01050 // Pipe function classes
01051 
01052 // PipeFun classes represent a pipe function object. After declare 
01053 // their instances, user must define them either by giving both their 
01054 // formal parameters and function bodies, or assign from lambda expressions.
01055 // After that, the function objects can evaluate to construct a graph.
01056 // formal parameters can list as constructor parameters, or at the left hand 
01057 // of equation followed by NULL, e.g. f(x,NULL) = x * 2 ;
01058 
01059 template<class Tout>
01060 class PipeFun0 : public PipeLift0<Tout> {
01061   typedef PipeFun0<Tout> ThisType ;
01062   typedef PipeLift0<Tout> BaseType ;
01063  protected:
01064   Pipe<Tout> * result ;
01065 
01066  protected:  
01067   void setDependency(void) 
01068     { addDependency((DependencyUnit**)&result); }
01069   ThisType * duplicate(void) const { return new ThisType(*this); }  
01070 
01071   inline void check(void) { return PipeModule<Tout>::check(result);}
01072 
01073  public:
01074   PipeFun0() : result(0) { setDependency(); }
01075   PipeFun0( const ThisType& p ) : BaseType(p), 
01076     result(p.result) { setDependency(); }
01077 
01078   Pipe<Tout> operator() (void)
01079     { 
01080       check(); 
01081       ThisType *p = (ThisType *) copy();
01082       return Pipe<Tout>(p) ;
01083     }
01084 
01085   // this function hacks... 
01086   Pipe<Tout> operator() (void) const 
01087     { return (*const_cast<ThisType*>(this))() ; }
01088 
01089   ThisType& operator = ( const Pipe<Tout>& p )
01090     { 
01091       if( result ) throw RedefPipe() ;
01092       result = new Pipe<Tout>(p) ;
01093       return *this; 
01094     }
01095 
01096   ThisType& operator = ( const ThisType& p )
01097     { 
01098       if( &p != this ) {
01099         if( result ) throw RedefPipe() ;
01100         result = p.result ; 
01101         return *this; 
01102       }
01103     }
01104 
01105   Tout get_value( int fc ) { check(); return result->get_value(fc); }
01106 };
01107 
01108 template<class Tout>
01109 PipeFun0<Tout> 
01110 lambdaP( const Pipe<Tout>& f ) {
01111   PipeFun0<Tout> p;
01112   return p = f ;
01113 }
01114 
01115 template<class Tout, class Tin1>
01116 class PipeFun1 : public PipeLift1<Tout,Tin1> {
01117   typedef PipeFun1<Tout,Tin1> ThisType ;
01118   typedef PipeLift1<Tout,Tin1> BaseType ;
01119  protected:
01120   Pipe<Tout> * result ;
01121   Pipe<Tin1> * param1 ;
01122 
01123  protected:
01124   
01125   void setDependency(void) 
01126     { 
01127       addDependency((DependencyUnit**)&result); 
01128       addDependency((DependencyUnit**)&param1); 
01129     }
01130   ThisType * duplicate(void) const { return new ThisType(*this); }  
01131 
01132   inline void check(void) { return PipeModule<Tout>::check(result&&param1);}
01133 
01134  public:
01135   PipeFun1() : result(0), param1(0) { setDependency(); }
01136   PipeFun1( Pipe<Tin1>& p1 ) : result(0), param1(&p1) {setDependency();}
01137   PipeFun1( const ThisType& p ) : BaseType(p), 
01138     result(p.result), param1(p.param1) { setDependency(); }
01139 
01140   ThisType& operator () ( Pipe<Tin1>& p1, void * dummy ) 
01141     {
01142       if( param1 ) throw RedefPipe() ;
01143       param1 = &p1 ;
01144       return *this ;
01145     }
01146 
01147   Pipe<Tout> operator() ( const Pipe<Tin1>& x1 )
01148     { 
01149       check(); 
01150       PipeModule<Tin1> dummy1, * save1 = *(param1->module) ;
01151       *(param1->module) = &dummy1 ;
01152       ThisType *p = (ThisType *) copy();
01153       delete *(p->param1->module) ; // assume PipeModule->duplicate() use new
01154       *(p->param1->module) = new Pipe<Tin1>(x1) ;
01155       *(param1->module) = save1 ;
01156       return Pipe<Tout>(p) ;
01157     }
01158 
01159   // this function hacks... 
01160   Pipe<Tout> operator() ( const Pipe<Tin1>& x1 ) const 
01161     { return (*const_cast<ThisType*>(this))(x1) ; }
01162 
01163   ThisType& operator = ( const Pipe<Tout>& p )
01164     { 
01165       if( result ) throw RedefPipe() ;
01166       result = new Pipe<Tout>(p) ;
01167       return *this; 
01168     }
01169 
01170   ThisType& operator = ( const ThisType& p )
01171     { 
01172       if( &p != this ) {
01173         if( result || param1 ) throw RedefPipe() ;
01174         result = p.result ; 
01175         param1 = p.param1 ; 
01176         return *this; 
01177       }
01178     }
01179 
01180   Tout get_value( int fc ) { check(); return result->get_value(fc); }
01181 };
01182 
01183 template<class Tout, class Tin1>
01184 PipeFun1<Tout,Tin1> 
01185 lambdaP( Pipe<Tin1>& x1, const Pipe<Tout>& f ) {
01186   PipeFun1<Tout,Tin1> p(x1);
01187   return p = f ;
01188 }
01189 
01190 template<class Tout, class Tin1, class Tin2>
01191 class PipeFun2 : public PipeLift2<Tout,Tin1,Tin2> {
01192   typedef PipeFun2<Tout,Tin1,Tin2> ThisType ;
01193   typedef PipeLift2<Tout,Tin1,Tin2> BaseType ;
01194  protected:
01195   Pipe<Tout> * result ;
01196   Pipe<Tin1> * param1 ;
01197   Pipe<Tin2> * param2 ;
01198 
01199  protected:
01200   
01201   void setDependency(void) 
01202     { 
01203       addDependency((DependencyUnit**)&result); 
01204       addDependency((DependencyUnit**)&param1); 
01205       addDependency((DependencyUnit**)&param2); 
01206     }
01207   ThisType * duplicate(void) const { return new ThisType(*this); }  
01208 
01209   inline void check(void) 
01210     { return PipeModule<Tout>::check(result&&param1&&param2);}
01211 
01212  public:
01213   PipeFun2() : result(0), param1(0), param2(0) { setDependency(); }
01214   PipeFun2( Pipe<Tin1>& p1, Pipe<Tin2>&p2 ) : result(0), 
01215     param1(&p1), param2(&p2) {setDependency();}
01216   PipeFun2( const ThisType& p ) : BaseType(p), result(p.result), 
01217     param1(p.param1), param2(p.param2) { setDependency(); }
01218 
01219   ThisType& operator () ( Pipe<Tin1>& p1, Pipe<Tin2>& p2, void * dummy ) 
01220     {
01221       if( param1 || param2 ) throw RedefPipe() ;
01222       param1 = &p1 ;
01223       param2 = &p2 ;
01224       return *this ;
01225     }
01226 
01227   Pipe<Tout> operator() ( const Pipe<Tin1>& x1, const Pipe<Tin2>& x2 )
01228     { 
01229       check(); 
01230       PipeModule<Tin1> dummy1, * save1 = *(param1->module) ;
01231       *(param1->module) = &dummy1 ;
01232       PipeModule<Tin2> dummy2, * save2 = *(param2->module) ;
01233       *(param2->module) = &dummy2 ;
01234       ThisType *p = (ThisType *) copy();
01235       delete *(p->param1->module) ; // assume PipeModule->duplicate() use new
01236       *(p->param1->module) = new Pipe<Tin1>(x1) ;
01237       *(param1->module) = save1 ;
01238       delete *(p->param2->module) ; // assume PipeModule->duplicate() use new
01239       *(p->param2->module) = new Pipe<Tin2>(x2) ;
01240       *(param2->module) = save2 ;
01241       return Pipe<Tout>(p) ;
01242     }
01243 
01244   // this function hacks... 
01245   Pipe<Tout> operator() ( const Pipe<Tin1>& x1, const Pipe<Tin2>& x2 ) const 
01246     { return (*const_cast<ThisType*>(this))(x1,x2) ; }
01247 
01248   ThisType& operator = ( const Pipe<Tout>& p )
01249     { 
01250       if( result ) throw RedefPipe() ;
01251       result = new Pipe<Tout>(p) ;
01252       return *this; 
01253     }
01254 
01255   ThisType& operator = ( const ThisType& p )
01256     { 
01257       if( &p != this ) {
01258         if( result || param1 || param2 ) throw RedefPipe() ;
01259         result = p.result ; 
01260         param1 = p.param1 ; 
01261         param2 = p.param2 ; 
01262         return *this; 
01263       }
01264     }
01265 
01266   Tout get_value( int fc ) { check(); return result->get_value(fc); }
01267 };
01268 
01269 template<class Tout, class Tin1, class Tin2>
01270 PipeFun2<Tout,Tin1,Tin2> 
01271 lambdaP( Pipe<Tin1>& x1, Pipe<Tin2>& x2, const Pipe<Tout>& f ) {
01272   PipeFun2<Tout,Tin1,Tin2> p(x1, x2);
01273   return p = f ;
01274 }
01275 
01276 // We need more work on PipeFun3, etc. basically "copy and paste" codes 
01277 // -- Donald
01278 
01279 
01280 // Pair class
01281 
01282 template<class T1, class T2>
01283 class Pair {
01284 public:
01285   T1 lval;
01286   T2 rval;
01287 
01288   Pair() {}; // needed to be able to declare an empty variable for Pipes
01289   Pair( const T1& x, const T2& y ) :  lval(x), rval(y) {};
01290 
01291   T1 lVal(void) const { return lval ; }
01292   T2 rVal(void) const { return rval ; }
01293 };
01294 
01295 template<class T1, class T2>
01296 Pair< T1,T2 > Pairup( T1 x, T2 y )
01297 {
01298   return Pair<T1,T2>(x,y);
01299 }
01300 
01301 template <class T1, class T2>
01302 Pipe< Pair<T1,T2> > operator&&( const Pipe<T1>& x, const Pipe<T2>& y)
01303 {
01304   Pair<T1,T2> (*Pairupf)( T1, T2 ) = &Pairup;
01305   PipeModuleLift2<Pair<T1,T2>,T1,T2,Pair<T1,T2> (*)(T1,T2)> temp(Pairupf);
01306 
01307   return temp(x,y);
01308 }
01309 
01310 # endif //_PIPEMODULES_H_

Generated at Thu Mar 29 22:37:28 2001 for XVision by doxygen1.2.0 written by Dimitri van Heesch, © 1997-2000