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

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

00001 #ifndef __pipemodules_h
00002 #define __pipemodules_h
00003 
00004 #include <assert.h>
00005 #include <stream.h>
00006 
00007 template <class Tout>
00008 class PipeModule {
00009 
00010 protected:
00011 
00012   // The value last computed by this module;
00013   // cached here to avoid recomputation
00014 
00015   Tout value;
00016   Tout last; //add by Donald
00017 
00018   // This'll be filled in later when we lift things
00019   // For now, its a placeholder for constant lifting
00020 
00021   virtual Tout compute_local_fn(int) {return value;};
00022 
00023 protected:
00024 
00025   // For bookeeping what data has passed through
00026 
00027   int frame_count;
00028 
00029 public:
00030 
00031   PipeModule() {frame_count = -1;};
00032   PipeModule(Tout x) {value = x;};  // For lifting constants
00033 
00034   // This is the generic updating algorithm ...
00035 
00036   virtual void keepup( int fcin ) {}  //add by Donald
00037 
00038   virtual Tout get_value(int fcin) {
00039 
00040     if( fcin < frame_count) { //add by Donald
00041       return last ;
00042     }
00043     if (fcin > frame_count) {
00044       last = value ;          //add by Donald
00045       value = compute_local_fn(fcin);
00046       frame_count = fcin;
00047       keepup(fcin);           //add by Donald
00048     }
00049     return value;
00050   }
00051 
00052   virtual Tout next_value() {
00053     return get_value(frame_count+1);
00054   }
00055 
00056 };
00057 
00058 // add by Donald
00059 // exception class
00060 class BrokenPipe {};
00061 // end Donald
00062 
00063 // Pipes are what the user actually defines
00064 // They are really Handles, but they carry types and so
00065 // act as a cosmetic sugar on Handles; they also allow automatically
00066 // lifting constants.  In practice, Pipes allow us to make
00067 // equations where the same expression appears on both sides of 
00068 // the statement
00069 
00070 template <class Tout>
00071 class Pipe  {
00072 
00073 protected:
00074   friend class PipeModule<Tout>;
00075 
00076   // This is the actual node in the graph that does the work
00077 
00078   PipeModule<Tout> *module;
00079 
00080   // If an uninitialized Pipe is used in an expression, we
00081   // make a list of nodes that use it an  "backpatch" once an assignment
00082   // is made; this make it possible to use local variables in Pipe equations 
00083   // without them having disappeared when the graph is executed.
00084 
00085   Pipe<Tout> *backpatch_nodes; 
00086 
00087   // This does the backpatching once a module assignment is known.
00088 
00089   void backpatch(PipeModule<Tout> *m) {
00090     module = m;
00091     if (backpatch_nodes) {
00092       backpatch_nodes->backpatch(m);
00093     }
00094     backpatch_nodes = NULL;
00095   }
00096 
00097 
00098 public:
00099 
00100   Pipe() : module(NULL), backpatch_nodes(NULL) {};
00101   Pipe(PipeModule<Tout> *v) : module(v),  backpatch_nodes(NULL) {};
00102 
00103   // This is the way to create a "backpatch" list; only used internally
00104   // while constructing the graph; unfortunately it's not possible to
00105   // easily "friend" it to PipeModule, but it's not for public consumption
00106 
00107   Pipe(Pipe<Tout> *v) : module(v->module),  backpatch_nodes(NULL) {
00108     if (module == NULL) {
00109       backpatch_nodes = v->backpatch_nodes;
00110       v->backpatch_nodes = this;
00111     }
00112   };
00113 
00114   // This allows the compler to automatically lift constants
00115 
00116   Pipe(const Tout v) : module(new PipeModule<Tout>(v)) {};
00117 
00118   Pipe(const Pipe<Tout> &v) : module(v.module),  backpatch_nodes(NULL) {
00119     assert(module != NULL);
00120   };
00121 
00122   // Ideally, I'd like an automatic cast to the stored PipeModule ..
00123   // this overload is a little confusing
00124 
00125   PipeModule<Tout> *operator ->() const {return module;}
00126 
00129   Pipe<Tout> &operator=(const Pipe<Tout> &xvp) {
00130     assert(xvp.module != NULL);
00131     assert(xvp.backpatch_nodes == NULL);
00132     backpatch(xvp.module);
00133     return *this;
00134   }
00135 
00136   // add by Donald
00137   void run() { try{ for(;;) module->next_value(); } catch(BrokenPipe) {} }
00138   // end Donald
00139 };
00140 
00141 // We now go into "lifting" operators that admit functions to the class.  There
00142 // are four types of "lifts:" pure functions, class member functions, "implicit" functions, 
00143 // and operators. Implicit functions are needed becuse C++ doesn't allow template 
00144 // matching based on output type, so we have to artifically add another argument to the function.
00145 // Worth noting that we allow class member functions that change internal class state; 
00146 // if we wanted to be militant, we would require those functions to be "const" on the
00147 // class, in which case we get the equivalent of closures.
00148 
00149 template <class Tout,class Tclass>
00150 class PipeModuleLiftClass0 : PipeModule<Tout> {
00151 
00152 protected:
00153 
00154   // The value last computed by this module;
00155   // cached here to avoid recomputation
00156 
00157   typedef Tout (Tclass::*LiftC0Type)(void); //modified by Donald
00158 
00159   Tclass state;
00160   LiftC0Type proc;
00161 
00162   virtual Tout compute_local_fn(int) {return (state.*proc)();};
00163 
00164 public:
00165 
00166   PipeModuleLiftClass0(const Tclass &xin,LiftC0Type proc_in) : 
00167     PipeModule(), state(xin), proc(proc_in) {}
00168 
00169   Pipe<Tout> &operator () () const
00170     {
00171       return *(new Pipe<Tout>(new PipeModuleLiftClass0(state,proc)));
00172     }
00173 };
00174 
00175 
00176 template <class Tout>
00177 class PipeModuleLift0: public PipeModule<Tout> {
00178 
00179   typedef Tout (*Lift0Type)();
00180   Lift0Type fn;
00181 
00182 public:
00183 
00184   PipeModuleLift0(Lift0Type fnin): PipeModule<Tout>(), fn(fnin) {};
00185 
00186   Pipe<Tout> &operator () () const
00187     {
00188       return *(new Pipe<Tout>(new PipeModuleLift0(fn)));
00189     }
00190 
00191   Tout compute_local_fn(int fc) {return (*fn)();};
00192 };
00193 
00194 template <class Tout, class Tin>
00195 class PipeModuleLift1: public PipeModule<Tout> {
00196 
00197   typedef Tout (*Lift1Type)(const Tin&);   
00198   Lift1Type fn;
00199   const Pipe<Tin> *pred;
00200 
00201 public:
00202 
00203   PipeModuleLift1(Lift1Type fnin): fn(fnin) {};
00204 
00205   Pipe<Tout> &operator () (Pipe<Tin> &x) const
00206     {
00207       PipeModuleLift1 *temp = new PipeModuleLift1<Tout, Tin>(fn);
00208       Pipe<Tout> *tempp = new Pipe<Tout>(temp);
00209       temp->pred = new Pipe<Tin>(&x);
00210       return *tempp;
00211     }
00212 
00213   Tout compute_local_fn(int fc) 
00214     {
00215       return fn((*pred)->get_value(fc));
00216     }
00217 
00218   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00219 };
00220 
00221 template <class Tout, class Tin, class Tclass>
00222 class PipeModuleLiftClass1: public PipeModule<Tout> {
00223 
00224   typedef Tout (Tclass::*Lift1Type)(const Tin&);   
00225   Tclass state;
00226   Lift1Type fn;
00227   Pipe<Tin> *pred;
00228 
00229 public:
00230 
00231   PipeModuleLiftClass1(Lift1Type fnin, const Tclass &state_in): fn(fnin), state(state_in) {};
00232 
00233   Pipe<Tout> &operator () (Pipe<Tin> &x) const
00234     {
00235       PipeModuleLiftClass1 *temp = new PipeModuleLiftClass1<Tout, Tin, Tclass>(fn,state);
00236       Pipe<Tout> *tempp = new Pipe<Tout>(temp);
00237       temp->pred = new Pipe<Tin>(&x);
00238       return *tempp;
00239     }
00240 
00241   Tout compute_local_fn(int fc) 
00242     {
00243       return (state.*fn)((*pred)->get_value(fc));
00244     }
00245 
00246   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00247 };
00248 template <class Tout, class Tin1>
00249 class PipeModuleLiftImplicit1: public PipeModule<Tout> {
00250   
00251   Tout x;
00252   Tout (*fn)(const Tin1&, Tout&);   
00253   const Pipe<Tin1> *pred;
00254 
00255 public:
00256 
00257   PipeModuleLiftImplicit1(Tout (*fnin)(const Tin1&, Tout&)): fn(fnin) {};
00258 
00259   Pipe<Tout> &operator () (Pipe<Tin1> &x) const
00260     {
00261       PipeModuleLiftImplicit1<Tout,Tin1> *temp = new PipeModuleLiftImplicit1<Tout, Tin1>(fn);
00262       Pipe<Tout> *tempp = new Pipe<Tout>(temp);
00263       temp->pred = new Pipe<Tin1>(&x);
00264       return *tempp;
00265     }
00266 
00267   Tout compute_local_fn(int fc) 
00268     {
00269       return fn((*pred)->get_value(fc),x);
00270     }
00271 
00272   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00273 };
00274 
00275 
00276 template <class Tout, class Tin1, class Tin2>
00277 class PipeModuleLift2: public PipeModule<Tout> {
00278   
00279   Tout (*fn)(const Tin1&, const Tin2&);   
00280   const Pipe<Tin1> *pred1;
00281   const Pipe<Tin2> *pred2;
00282 
00283 public:
00284 
00285   PipeModuleLift2(Tout (*fnin)(const Tin1&, const Tin2&)): fn(fnin) {};
00286 
00287   Pipe<Tout> &operator () (Pipe<Tin1> &x, Pipe<Tin2> &y)  const
00288     {
00289       PipeModuleLift2 *temp = new PipeModuleLift2<Tout, Tin1, Tin2>(fn);
00290       Pipe<Tout> *tempp = new Pipe<Tout>(temp);
00291       temp->pred1 = new Pipe<Tin1>(&x);
00292       temp->pred2 = new Pipe<Tin2>(&y);
00293       return *tempp;
00294     }
00295 
00296   Tout compute_local_fn(int fc) 
00297     {
00298       return fn((*pred1)->get_value(fc),
00299           (*pred2)->get_value(fc));
00300     }
00301 
00302   void keepup( int fc ) { (*pred1)->get_value(fc); 
00303                           (*pred2)->get_value(fc); }  // add by Donald
00304 };
00305 
00306 
00307 template <class Tout, class Tin1, class Tin2, class Tin3>
00308 class PipeModuleLift3: public PipeModule<Tout> {
00309   
00310   Tout (*fn)(const Tin1&, const Tin2&, const Tin3&);   
00311   const Pipe<Tin1> *pred1;
00312   const Pipe<Tin2> *pred2;
00313   const Pipe<Tin3> *pred3;
00314 
00315 public:
00316 
00317   PipeModuleLift3(Tout (*fnin)(const Tin1&, const Tin2&, const Tin3&)): fn(fnin) {};
00318 
00319   Pipe<Tout> &operator () (Pipe<Tin1> &x, Pipe<Tin2> &y, Pipe<Tin3> &z)  const
00320     {
00321       PipeModuleLift3 *temp = new PipeModuleLift3<Tout, Tin1, Tin2, Tin3>(fn);
00322       Pipe<Tout> *tempp = new Pipe<Tout>(temp);
00323       temp->pred1 = new Pipe<Tin1>(&x);
00324       temp->pred2 = new Pipe<Tin2>(&y);
00325       temp->pred3 = new Pipe<Tin3>(&z);
00326       return *tempp;
00327     }
00328 
00329   Tout compute_local_fn(int fc) 
00330     {
00331       return fn((*pred1)->get_value(fc),
00332           (*pred2)->get_value(fc),
00333           (*pred3)->get_value(fc));
00334     }
00335 
00336   void keepup( int fc ) { (*pred1)->get_value(fc); 
00337                           (*pred2)->get_value(fc);
00338                           (*pred3)->get_value(fc); }  // add by Donald
00339 };
00340 
00341 template <class T>
00342 class PipeDelay: public PipeModule<T> {
00343 
00344   int have_value;
00345   int beencalled;
00346   T val;
00347   const Pipe<T> *pred;
00348 
00349   void set_value(T v) {val = v; have_value = 1;}
00350 
00351 public:
00352 
00353   PipeDelay() {beencalled = 0;have_value=0;};
00354 
00355   Pipe<T> &operator () (Pipe<T> &x,T firstval)  const
00356     {
00357       PipeDelay<T> *temp = new PipeDelay<T>;
00358       Pipe <T> *tempp = new Pipe<T>(temp);
00359       temp->set_value(firstval);
00360       temp->pred = new Pipe<T> (&x);
00361       return *tempp;
00362     }
00363 
00364   // This allow a "partial evaluation" of delay
00365 
00366   Pipe<T> &operator () (Pipe<T> &x) const
00367     {
00368       if (have_value) {
00369      return (*this)(x,val);
00370       }
00371       else {
00372      cerr << "Attempt to call uninitialized PipeDelay" << endl;
00373      exit(1);
00374       }
00375     }
00376 
00377   PipeDelay<T> &operator () (T firstval)  const
00378     {
00379       PipeDelay<T> *temp = new PipeDelay<T>;
00380       temp->set_value(firstval);
00381       return *temp;
00382     }
00383 
00384   T compute_local_fn(int fc) 
00385     {
00386       if (!beencalled) {
00387      beencalled = 1;
00388      return val;
00389       }
00390       else
00391         return((*pred)->get_value(fc-1));
00392     }
00393 
00394   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00395 };
00396 
00397 
00398 // IO Side effects
00399 
00400 template <class T>
00401 class PipeModuleLiftIO: public PipeModule<T> {
00402   
00403   int (*fn)(const T&);   
00404   Pipe<T> *pred;
00405 
00406 public:
00407 
00408   PipeModuleLiftIO(int (*fnin)(const T&)): fn(fnin) {};
00409 
00410   Pipe<T> &operator () (const Pipe<T> &x)
00411     {
00412       PipeModuleLiftIO *temp = new PipeModuleLiftIO<T>(fn);
00413       Pipe<T> *tempp = new Pipe<T>(temp);
00414       temp->pred = new Pipe<T>(&x);
00415       return *tempp;
00416     }
00417 
00418   T compute_local_fn(int fc) 
00419     {
00420      if (fn((*pred)->get_value(fc)))
00421        return get_value(fc);
00422      else {
00424        cerr << "Error in IO" << endl;
00425        exit(1);
00426      }
00427     }
00428 
00429   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00430 };
00431 
00432 template <class T>
00433 class PipeModulePrint: public PipeModule<T> {
00434   
00435   Pipe<T> *pred;
00436 
00437 public:
00438 
00439   Pipe<T> &operator () (const Pipe<T> &x)
00440     {
00441       PipeModulePrint *temp = new PipeModulePrint<T>();
00442       Pipe<T> *tempp = new Pipe<T>(temp);
00443       temp->pred = new Pipe<T>(&x);
00444       return *tempp;
00445     }
00446 
00447   T compute_local_fn(int fc) 
00448     {
00449       cout  << (*pred)->get_value(fc) << endl;
00450       return (*pred)->get_value(fc);
00451     }
00452 
00453   void keepup( int fc ) { (*pred)->get_value(fc); }  // add by Donald
00454 };
00455 
00456 // begin Donald
00457 
00458 #define LiftBinOp(OP,NM) \
00459 template <class T1, class T2>\
00460 class PipeModuleLiftBin##NM: public PipeModule<T1> {\
00461 \
00462 const Pipe<T1> *pred1;\
00463 const Pipe<T2> *pred2;\
00464 public:\
00465 \
00466   PipeModuleLiftBin##NM(Pipe<T1> &x, Pipe<T2> &y): PipeModule<T1>() \
00467   {\
00468       pred1= new Pipe<T1>(&x);\
00469       pred2= new Pipe<T2>(&y);\
00470   };\
00471 \
00472   T1 compute_local_fn(int fc) {\
00473       return ((*pred1)->get_value(fc) OP\
00474           (*pred2)->get_value(fc));\
00475   }\
00476 \
00477   void keepup( int fc ) { (*pred1)->get_value(fc); \
00478                           (*pred2)->get_value(fc); }\
00479 };\
00480 \
00481 template <class T1, class T2>\
00482 Pipe<T1> &operator##OP(Pipe<T1> &x, Pipe<T2> &y)\
00483 {\
00484   return *(new Pipe<T1>(new PipeModuleLiftBin##NM<T1,T2>(x,y)));\
00485 }\
00486 template <class T1, class T2>\
00487 Pipe<T1> &operator##OP(Pipe<T1> &x, const T2 y)\
00488 {\
00489   return *(new Pipe<T1>(new PipeModuleLiftBin##NM<T1,T2>(x,y)));\
00490 }\
00491 template <class T1, class T2>\
00492 Pipe<T1> &operator##OP(const T1 x, Pipe<T2> &y)\
00493 {\
00494   return *(new Pipe<T1>(new PipeModuleLiftBin##NM<T1,T2>(x,y)));\
00495 }\
00496 // end Donald
00497 
00498 template <class T1, class T>
00499 Pipe<T1> &operator << (const PipeModuleLift1<T1,T> &x, Pipe<T> &y)
00500 {
00501   return x(y);
00502 }  
00503 
00504 template <class T1, class T>
00505 Pipe<T1> &operator << (const PipeModuleLiftImplicit1<T1,T> &x, Pipe<T> &y)
00506 {
00507   return x(y);
00508 }  
00509 
00510 template <class T1, class T, class Tclass>
00511 Pipe<T1> &operator << (const PipeModuleLiftClass1<T1,T,Tclass> &x, Pipe<T> &y)
00512 {
00513   return x(y);
00514 }  
00515 
00516 template <class T>
00517 Pipe<T> &operator << (const PipeDelay<T> &x, Pipe<T> &y)
00518 {
00519   return x(y);
00520 }  
00521 
00522 LiftBinOp(+,Plus)
00523 LiftBinOp(-,Minus)
00524      //add by Donald
00525 LiftBinOp(*,Multiply)
00526 LiftBinOp(/,Divide)
00527 LiftBinOp(<<,LeftShift)
00528      //end Donald
00529 
00530 template <class T1, class T2>
00531 class Pair {
00532 public:
00533   T1 lval;
00534   T2 rval;
00535 
00536   Pair() {}; // needed to be able to declare an empty variable for Pipes
00537   Pair(const T1 &x, const T2 &y) :  lval(x), rval(y) {};
00538 };
00539 
00540 template <class T1, class T2>
00541 Pair<T1,T2> Pairup(const T1 &x, const T2 &y)
00542 {
00543   return Pair<T1,T2>(x,y);
00544 }
00545 
00546 template <class T1, class T2>
00547 ostream &operator << (ostream &outs,Pair<T1,T2> v)
00548 {
00549   outs << "(" << v.lval << ", " << v.rval << ")";
00550 }
00551     
00552 template <class T1, class T2>
00553 Pipe<Pair<T1,T2> > &operator&&(Pipe<T1> &x, Pipe<T2> &y)
00554 {
00555   Pair<T1,T2> (*Pairupf)(const T1 &,const T2 &) = &Pairup;
00556   PipeModuleLift2<Pair<T1,T2>,T1,T2 > temp(Pairupf);
00557 
00558   return temp(x,y);
00559 }
00560 
00561 
00562 #endif

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