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
00013
00014
00015 Tout value;
00016 Tout last;
00017
00018
00019
00020
00021 virtual Tout compute_local_fn(int) {return value;};
00022
00023 protected:
00024
00025
00026
00027 int frame_count;
00028
00029 public:
00030
00031 PipeModule() {frame_count = -1;};
00032 PipeModule(Tout x) {value = x;};
00033
00034
00035
00036 virtual void keepup( int fcin ) {}
00037
00038 virtual Tout get_value(int fcin) {
00039
00040 if( fcin < frame_count) {
00041 return last ;
00042 }
00043 if (fcin > frame_count) {
00044 last = value ;
00045 value = compute_local_fn(fcin);
00046 frame_count = fcin;
00047 keepup(fcin);
00048 }
00049 return value;
00050 }
00051
00052 virtual Tout next_value() {
00053 return get_value(frame_count+1);
00054 }
00055
00056 };
00057
00058
00059
00060 class BrokenPipe {};
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 template <class Tout>
00071 class Pipe {
00072
00073 protected:
00074 friend class PipeModule<Tout>;
00075
00076
00077
00078 PipeModule<Tout> *module;
00079
00080
00081
00082
00083
00084
00085 Pipe<Tout> *backpatch_nodes;
00086
00087
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
00104
00105
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
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
00123
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
00137 void run() { try{ for(;;) module->next_value(); } catch(BrokenPipe) {} }
00138
00139 };
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 template <class Tout,class Tclass>
00150 class PipeModuleLiftClass0 : PipeModule<Tout> {
00151
00152 protected:
00153
00154
00155
00156
00157 typedef Tout (Tclass::*LiftC0Type)(void);
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); }
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); }
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); }
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); }
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); }
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
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); }
00395 };
00396
00397
00398
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); }
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); }
00454 };
00455
00456
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
00525 LiftBinOp(*,Multiply)
00526 LiftBinOp(/,Divide)
00527 LiftBinOp(<<,LeftShift)
00528
00529
00530 template <class T1, class T2>
00531 class Pair {
00532 public:
00533 T1 lval;
00534 T2 rval;
00535
00536 Pair() {};
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