proj home

Files   Classes   Functions   Hierarchy  

rpn.cpp

Go to the documentation of this file.
00001 
00002 
00003 #include <cassert>
00004 #include <algorithm>
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <deque>
00008 #include <string>
00009 #include <bitset>
00010 #include <limits>
00011 
00012 using namespace std;
00013 
00014 #include <rpn.h>
00015 
00016 #ifndef NDEBUG
00017 // Toggle Debug code.
00018 #define DEBUG_RFC
00019 #endif
00020 
00021 // Magic Number
00022 #define PRECISION 30
00023 
00024 
00025 
00026 
00027 // Implementation
00028 // ------------------------------------------------------------ 
00029 //
00030 
00031 /* g++ wants these. */
00032 rpnbase::~rpnbase() {}
00033 rpnbase* rpnbase::copy() const { return 0; }
00034 
00035 ostream& operator << (ostream& os, rpnbase* const p) 
00036   { return p->print(os); }
00037 
00038 
00039 rpnreal::rpnreal(deque<rpnbase*>& ds, long double const n)
00040   : num(n)
00041 {
00042   eval(ds);
00043 }
00044 
00045 /*
00046 This is a MAGIC NUMBER. 
00047 
00048  <TODO> Make configurable for user.
00049 
00050   Why 30?  I do not know, but it is beyond the accuracy
00051   of my type and hence displaysed the computers approximation.
00052 
00053   eg. On my machine
00054     73.4 resulted in 
00055     0: 73.40000000000000568434
00056 
00057   An accuracy of 15 digits. Ofcourse the computer has
00058    a binary representation/approximation.
00059 
00060   The good thing about displaying the garbage is you
00061   get to see how inaccurate the computer actually is,
00062   and its scary.
00063 
00064 */
00065 ostream& rpnreal::print(ostream& os) const
00066 {
00067   return os << fixed << showpoint 
00068     << setprecision( PRECISION ) << num;
00069 } 
00070 
00071 rpnbase* rpnreal::copy() const
00072 {
00073   rpnreal* n = new rpnreal();
00074   n->num = num;
00075   return n;
00076 }
00077 
00078 
00079 rpncomplex::rpncomplex
00080 (
00081   deque<rpnbase*>& ds,
00082   long double const x, 
00083   long double const y
00084 )
00085   : num(x,y)
00086 {
00087   eval(ds);
00088 }
00089 
00090 
00091 rpncomplex::rpncomplex
00092 (
00093   deque<rpnbase*>& ds,
00094   complex<long double> const & x
00095 )
00096   : num(x)
00097 {
00098   eval(ds);
00099 }
00100 
00101 
00102 ostream& rpncomplex::print(ostream& os) const
00103 {
00104   return os << fixed << showpoint 
00105     << setprecision( PRECISION ) << num;
00106 }
00107 
00108 rpnbase* rpncomplex::copy() const
00109 {
00110   rpncomplex* n = new rpncomplex();
00111   n->num = num;
00112 
00113   return n;
00114 }
00115 
00116  
00117 
00118 
00119 
00120 
00121 
00122 unsigned int rpninteger::displaybase(10);
00123 
00124 
00125 rpninteger::rpninteger(deque<rpnbase*>& ds, long int const n)
00126   : num(n)
00127 {
00128   eval(ds);
00129 }
00130 
00131 ostream& rpninteger::print(ostream& os) const
00132 {
00133 
00134   switch( displaybase )
00135   {
00136     case 10: 
00137       os.unsetf(ios::hex);
00138       os.unsetf(ios::oct);
00139       os.setf(ios::dec);
00140       break;
00141 
00142     case 8:
00143       os.unsetf(ios::dec);
00144       os.unsetf(ios::hex);
00145       os.setf(ios::oct);
00146       break;
00147 
00148     case 16:
00149       os.unsetf(ios::dec);
00150       os.unsetf(ios::oct);
00151       os.setf(ios::hex);
00152       break;
00153 
00154     case 2: 
00155 
00156       os << bitset<numeric_limits<long int>::digits>( num );
00157       return os;
00158   };
00159 
00160   return os << num;
00161 }
00162 
00163 rpnbase* rpninteger::copy() const
00164 {
00165   rpninteger* n = new rpninteger();
00166   n->num = num;
00167   return n;
00168 }
00169 
00170 
00171 rpnstring::rpnstring(deque<rpnbase*>& ds,string const & s)
00172   :str(s)
00173 {
00174   eval(ds);
00175 }
00176 
00177 ostream& rpnstring::print(ostream& os) const
00178 {
00179   if (str=="/")
00180     return os << "\"/\"";
00181 
00182   if (str.find(' ')!=string::npos)
00183     return os << '"' << str << '"';
00184 
00185   return os << str;
00186 
00187 /*
00188   if (str != "/")
00189     return os << str;
00190 
00191   // To distinguish between division and root node. 
00192   return os << string("\"/");
00193 */
00194 }
00195 
00196 rpnbase* rpnstring::copy() const
00197 {
00198   rpnstring* s = new rpnstring();
00199   s->str = str;
00200   return s;
00201 }
00202 
00203 void rpnstring::eval( deque<rpnbase*>& ds )
00204 {
00205   ds.push_front(this); 
00206 }
00207 
00208 
00209 void rpnprogram::vinc()
00210 {
00211   if (!v.empty())
00212   {
00213     for (unsigned int i=0, imax=v.size(); i<imax; ++i)
00214       v[i]->inc();
00215   }
00216 }
00217 
00218 void rpnprogram::inc()
00219 {
00220   ++ counter;
00221 
00222   vinc();
00223 
00224   if (!variables.empty())
00225   {
00226     for (unsigned int i=0, imax=variables.size(); i<imax; ++i)
00227       variables[i]->inc();
00228   }
00229 }
00230 
00231 
00232 rpnprogram::rpnprogram
00233 (
00234   deque<rpnbase*>& ds, 
00235   deque<rpnbase*>& ds2,
00236   bool const evaluate 
00237 )
00238   : state(3)
00239 {
00240   v = ds2;
00241   reverse(v.begin(),v.end()); /* <TODO> make efficent with reverse copy? */
00242 
00243   if (evaluate)
00244   {
00245     eval(ds);
00246     return;
00247   }
00248 
00249   ds.push_front(this);
00250 }
00251 
00252 rpnprogram::rpnprogram(deque<rpnbase*>& ds)
00253 {
00254   ds.push_front(this);
00255 }
00256 
00257 rpnprogram::rpnprogram()
00258   : state(3)
00259 {
00260 }
00261 
00262 ostream& rpnprogram::print(ostream& os) const
00263 {
00264   os << "{";
00265   if( v.empty())
00266     return os << " }";
00267 
00268   for (unsigned int i=0,imax=v.size(); i<imax; ++i)
00269   {
00270     os << " ";
00271     v[i]->print(os);
00272   }
00273 
00274   return os << " }";
00275 }
00276 
00277 rpnbase* rpnprogram::copy() const
00278 {
00279   /* A deep copy is required. */
00280 
00281   rpnprogram* p = new rpnprogram();
00282 
00283   if (v.empty())
00284   {  
00285     if (variables.empty())
00286       return p;
00287 
00288     for (unsigned int i=0, imax=variables.size(); i<imax; ++i)
00289     {
00290       rpnbase* tmp = variables[i]->copy();
00291       p->variables.push_back( (rpnvar*)tmp ); 
00292     }
00293 
00294     return p;
00295   }
00296 
00297   deque<rpnbase*> &v2 = p->v;
00298 
00299   for (unsigned int i=0, imax=v.size(); i<imax; ++i)
00300     v2.push_back( v[i]->copy() );
00301 
00302   if (variables.empty())
00303     return p;
00304 
00305   for (unsigned int i=0, imax=variables.size(); i<imax; ++i)
00306   {
00307     rpnbase* tmp = variables[i]->copy();
00308     p->variables.push_back( (rpnvar*)tmp );
00309   }
00310 
00311   return p;
00312 };
00313   
00314 rpnprogram::~rpnprogram()
00315 {
00316   if (!v.empty())
00317   {
00318     for (unsigned int i=0, imax=v.size(); i<imax; ++i)
00319       v[i]->dec();
00320     v.clear();
00321   }
00322 
00323   if (!variables.empty())
00324   {
00325     for (unsigned int i=0, imax=variables.size(); i<imax; ++i)
00326       variables[i]->dec();
00327     variables.clear();
00328   }
00329 }
00330 
00331 void rpnprogram::eval_01( deque<rpnbase*>& ds )
00332 {
00333   if(!v.empty())
00334   {
00335     for (unsigned int i=0,imax=v.size(); i<imax; ++i )
00336     {
00337       v[i]->inc();
00338       if (v[i]->isprogram())
00339         ds.push_front(v[i]);
00340       else
00341         v[i]->eval(ds);
00342     }
00343   }
00344 }
00345 
00346 void rpnprogram::eval_00()
00347 {
00348   if(!v.empty())
00349   {
00350     for (unsigned int i=0,imax=v.size(); i<imax; ++i )
00351     {
00352       v[i]->inc();
00353       if (v[i]->isprogram())
00354         rpnprogramstackstate().ds().push_front(v[i]);
00355       else
00356         v[i]->eval(rpnprogramstackstate().ds());
00357     }
00358   }
00359 }
00360 
00361 void rpnprogram::eval_11( deque<rpnbase*>& ds )
00362 {
00363   deque<rpnprogram*>& ps(* rpnprogramstackstate().ps);
00364   ps.push_front(this);
00365 
00366   if(!v.empty())
00367   {
00368     for (unsigned int i=0,imax=v.size(); i<imax; ++i )
00369     {
00370       v[i]->inc();
00371       if (v[i]->isprogram())
00372         ds.push_front(v[i]);
00373       else
00374         v[i]->eval(ds);
00375     }
00376   }
00377 
00378   // Remove self from program stack.
00379   if (ps.front()==this)
00380     rpnprogramstackstate().pop();
00381   else
00382   {
00383     unsigned int const imax=ps.size();
00384     for (unsigned int i=1; i<imax; ++i)
00385     {
00386       if (ps[i]==this)
00387       {
00388         ps.erase(ps.begin()+i);
00389         i=imax;
00390       }
00391     }
00392   }
00393 }
00394 
00395 void rpnprogram::eval_10()
00396 {
00397   deque<rpnprogram*>& ps(* rpnprogramstackstate().ps);
00398   ps.push_front(this);
00399 
00400   if(!v.empty())
00401   {
00402     for (unsigned int i=0,imax=v.size(); i<imax; ++i )
00403     {
00404       v[i]->inc();
00405       if (v[i]->isprogram())
00406         rpnprogramstackstate().ds().push_front(v[i]);
00407       else
00408         v[i]->eval(rpnprogramstackstate().ds());
00409     }
00410   }
00411 
00412   // Remove self from program stack.
00413   if (ps.front()==this)
00414     rpnprogramstackstate().pop();
00415   else
00416   {
00417     unsigned int const imax=ps.size();
00418     for (unsigned int i=1; i<imax; ++i)
00419     {
00420       if (ps[i]==this)
00421       {
00422         ps.erase(ps.begin()+i);
00423         i=imax;
00424       }
00425     }
00426   }
00427 }
00428 
00429 
00430 void rpnprogram::eval( deque<rpnbase*>& ds )
00431 {
00432   switch( state )
00433   {
00434     case 3: eval_11(ds); break;
00435     case 1: eval_10();   break;
00436     case 2: eval_01(ds); break;
00437     case 0: eval_00();   break;
00438   }
00439 
00440   dec();
00441 
00442 /*
00443   deque<rpnprogram*>& ps(* rpnprogramstackstate().ps);
00444   ps.push_front(this);
00445 //  rpnprogramstackstate().push(this);
00446 
00447 
00448 
00449 cout << "rpnprogram::eval( deque<rpnbase*>& ds )" << endl;
00450 
00451   if(!v.empty())
00452   {
00453     for (unsigned int i=0,imax=v.size(); i<imax; ++i )
00454     {
00455       v[i]->inc();
00456       if (v[i]->isprogram())
00457         ds.push_front(v[i]);
00458       else
00459         v[i]->eval(ds);
00460     }
00461   }
00462 
00463 //bool found=false;
00464 
00465   // Remove self from program stack.
00466   if (ps.front()==this)
00467   {
00468 //found=true;
00469     rpnprogramstackstate().pop();
00470   }
00471   else
00472   {
00473     unsigned int const imax=ps.size();
00474     for (unsigned int i=1; i<imax; ++i)
00475     {
00476       if (ps[i]==this)
00477       {
00478 //found=true;
00479         ps.erase(ps.begin()+i);
00480         i=imax;
00481       }
00482     }
00483   }
00484 
00485 //cout << "found=" << found << endl;
00486 
00487 //  rpnprogramstackstate().pop();
00488  
00489   dec();
00490 */
00491 }
00492 
00493 
00494 
00495 void rpnvar::inc()
00496 { 
00497   ++counter;
00498   x->inc();
00499 }
00500 
00501 rpnvar::~rpnvar()
00502 {
00503   if (x==0)
00504     return;
00505 
00506   x->dec();
00507 }
00508 
00509 rpnvar::rpnvar(rpnprogram& prog, rpnbase* x_, string const & s)
00510   : varname(s), x(x_)
00511 {
00512   prog.variables.push_front(this);
00513 }
00514 
00515 rpnvar::rpnvar(rpnbase* x_, string const & s)
00516   : varname(s), x(x_)
00517 {
00518 }
00519 
00520 rpnbase* rpnvar::copy() const
00521 {
00522   return new rpnvar( x->copy(),varname);
00523 }
00524 
00525 ostream& rpnvar::print(ostream& os) const
00526 {
00527   os << varname << " : ";
00528   return x->print(os);
00529 }
00530 
00531 
00532 rpnvector::rpnvector(int index)
00533 {
00534   reverseindex = indexcomplement(index);
00535 }
00536 
00537 rpnbase* rpnvector::copy() const
00538 {
00539   /* I do not want a default contructor, so put a dummy
00540      argument in.  The reverseindex should be preserved
00541      with a copy as they point to the same place.
00542   */
00543   rpnvector* p = new rpnvector((int)0);
00544   p->reverseindex = reverseindex;
00545   return p;
00546 }
00547 
00548 int const rpnvector::indexcomplement(int const n) const
00549 {
00550   int k = rpnprogramstackstate().ds().size();
00551   k -= n;
00552   return k;
00553 }
00554 
00555 const int rpnvector::index() const
00556 {
00557   return indexcomplement(reverseindex);
00558 }
00559 
00560 
00561 ostream& rpnvector::print(ostream& os) const
00562 {
00563   return os << " " << index() << " [] ";
00564   //return os << " " << indexcomplement(reverseindex) << " [] ";
00565 }
00566   
00567 
00568 rpnbase* rpnfunction::copy() const
00569 {
00570   return 0;
00571 }
00572 
00573 
00574 deque<rpnbase*> rpnprogramstackstate::ds2;
00575 deque<rpnprogram*>* rpnprogramstackstate::ps =
00576   new deque<rpnprogram*>();
00577 rpnprogram rpnprogramstackstate::rpnhome;
00578 string rpnprogramstackstate::findprogrampath;
00579 
00580 void rpnprogramstackstate::find 
00581 (
00582   bool & result,
00583   unsigned int & indexi,
00584   unsigned int & indexk,
00585   rpnvar* & x,
00586   string const & nm
00587 ) const
00588 {
00589   result=false;
00590 
00591   for (unsigned int i=0, imax=ps->size(); i<imax; ++i)
00592   {
00593     deque<rpnprogram*>& w = *ps; // <TODO> optimize.
00594     if ( ! w[i]->variables.empty() )
00595     {
00596       deque<rpnvar*>& z = w[i]->variables;
00597       for (unsigned int k=0, kmax=z.size(); k<kmax; ++k)
00598       {
00599         if (z[k]->varname==nm)
00600         {
00601           result=true;
00602           indexi = i;
00603           indexk = k;
00604           x = z[k];
00605 
00606           return;
00607         }
00608       }
00609     }
00610   }
00611 }
00612 
00613 
00614 
00615 /* While developing rely on general find, optimize at a later date. */
00616 
00617 
00618 
00619 void rpnprogramstackstate::exists
00620 (
00621   bool & res,
00622   string const & nm
00623 ) const
00624 {
00625   unsigned int i,k;
00626   rpnvar* x;
00627 
00628   find(res,i,k,x,nm);
00629 }
00630 
00631 
00632 void rpnprogramstackstate::evaluate
00633 (
00634   deque<rpnbase*>& ds,
00635   string const & nm
00636 ) const
00637 {
00638   bool res;
00639   unsigned int i,k;
00640   rpnvar* x;
00641 
00642   find(res,i,k,x,nm);
00643   if (res)
00644     x->x->copy()->eval(ds);
00645 }
00646 
00647 void rpnprogramstackstate::recall
00648 (
00649   deque<rpnbase*>& ds,
00650   string const & nm
00651 ) const
00652 {
00653   bool res;
00654   unsigned int i,k;
00655   rpnvar* x;
00656 
00657   find(res,i,k,x,nm);
00658   if (res)
00659     ds.push_front(x->x->copy());
00660 }
00661 
00662 void rpnprogramstackstate::recallpointer
00663 (
00664   deque<rpnbase*>& ds,
00665   string const & nm
00666 ) const
00667 {
00668   bool res;
00669   unsigned int i,k;
00670   rpnvar* x;
00671 
00672   find(res,i,k,x,nm);
00673   if (res)
00674   {
00675     x->x->inc();
00676     ds.push_front(x->x);
00677   }
00678 }
00679 
00680 
00681 void rpnprogramstackstate::replace(rpnbase* x, string const & nm)
00682 {
00683   bool res;
00684   unsigned int i,k;
00685   rpnvar* x2;
00686 
00687   find(res,i,k,x2,nm);
00688   if (res)
00689   {
00690     x2->x->dec();
00691     x2->x = x; 
00692   }
00693   else
00694     x->dec();  /* harsh */
00695 }
00696 
00697 void rpnprogramstackstate::erase(string const & nm)
00698 {
00699   bool res;
00700   unsigned int i,k;
00701   rpnvar* x2;
00702 
00703   find(res,i,k,x2,nm);
00704   if (res)
00705   {
00706     deque<rpnprogram*>& w = *ps;
00707     w[i]->variables.erase( w[i]->variables.begin()+k );
00708   }
00709 }
00710 
00711 void rpnprogramstackstate::init()
00712 {
00713   ps->push_front( &rpnhome );
00714 }
00715 
00716 ostream& rpnprogramstackstate::print(ostream& os) const
00717 {
00718   for (unsigned int i=0, imax=ps->size(); i<imax; ++i)
00719   {
00720     os << "{ ";
00721     deque<rpnprogram*>& w = *ps;
00722     if ( ! w[i]->variables.empty() )
00723     {
00724       deque<rpnvar*>& z = w[i]->variables;
00725       for (unsigned int k=0, kmax=z.size(); k<kmax; ++k)
00726       {
00727         os << "(" << z[k]->varname << ",";
00728         z[k]->x->print(os);
00729         os << ") ";
00730       }
00731     }
00732     os << "}" << endl;
00733   }
00734   return os;
00735 }
00736 
00737 void rpnprogramstackstate::add(rpnbase* x, string const & s)
00738 {
00739   ps->front()->variables.push_front( new rpnvar(x,s) );
00740 }
00741 
00742 
00743 void rpnprogramstackstate::findprogram
00744 (
00745   bool& found, 
00746   string& path, 
00747   rpnprogram* targ
00748 )
00749 {
00750   found = false;
00751 
00752 
00753   if (targ==&rpnhome)
00754   {
00755     findprogrampath = path = "/";
00756     found = true;
00757     return;
00758   }
00759 
00760   findprogram(found,&rpnhome,"",targ);
00761 
00762   if (found)
00763     path = findprogrampath;
00764 }
00765 
00766 void rpnprogramstackstate::findprogram
00767 (
00768   bool& found, 
00769   rpnprogram* p, 
00770   string const path, 
00771   rpnprogram* targ
00772 )
00773 {
00774   /* Depth first search. */
00775   /* Assume non-cyclic data structure. */
00776 
00777   if (!p->variables.empty())
00778   {
00779     for (unsigned int i=0, imax=p->variables.size(); i<imax; ++i)
00780     {
00781       if (found)
00782         return;
00783 
00784       if (p->variables[i]->x->isprogram())
00785       {
00786         rpnprogram* pr = (rpnprogram*)(p->variables[i]->x);
00787 
00788         string pathnew( path + string("/") + p->variables[i]->varname );
00789 
00790         if (pr == targ)
00791         {
00792           found = true;
00793           findprogrampath = pathnew;
00794           return;
00795         }
00796         else
00797           findprogram(found,pr,pathnew,targ);
00798 
00799       }
00800     }
00801   }
00802 }
00803 
00804 
00805 ostream& operator << (ostream& os, rpnprogramstackstate const & ps)
00806   { return ps.print(os); }
00807 
00808 
00809 
00810 

Generated on Fri Mar 4 00:49:30 2011 for Chelton Evans Source by  doxygen 1.5.8