introduction  —  namespaces  —  modules  —  classes  —  files  —  globals  —  members  —  examples  —  Marc Toussaint

std.h

Go to the documentation of this file.
00001 /*  Copyright (C) 2000, 2006  Marc Toussaint.
00002     email: mtoussai@inf.ed.ac.uk
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Lesser General Public
00006     License as published by the Free Software Foundation; either
00007     version 2.1 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Lesser General Public License for more details.
00013 
00014     A copy of the GNU Lesser General Public License can usually be found
00015     at http://www.gnu.org/copyleft/lesser.html; if not, write to the Free
00016     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00017     02110-1301 USA */
00018 
00022 #ifndef MT_std_h
00023 #define MT_std_h
00024 
00025 
00026 //--------- standard includes:
00027 #include <iostream>
00028 #include <iomanip>
00029 #include <fstream>
00030 #include <sstream>
00031 #include <math.h>
00032 #include <vector>
00033 #include <typeinfo>
00034 #if defined MT_MSVC || defined MT_Windows || defined WIN32 || defined _WIN32 || defined _MSC_VER
00035 #  undef  MT_MSVC
00036 #  define MT_MSVC
00037 #  include<limits>
00038 #  include<time.h>
00039 #  include<sys/timeb.h> 
00040 #  ifdef MT_QT
00041 #    include<windows.h>
00042 #    undef min //I hate it that windows defines these macros!
00043 #    undef max
00044 #    undef  NOUNICODE
00045 #    define NOUNICODE
00046 //#    define QT_DLL
00047 //#    define _MSC_VER 1300
00048 //#    define _GDI32_
00049 //#    define _MBCS
00050 //#    define QT_THREAD_SUPPORT
00051 #  endif
00052 #  pragma warning(disable: 4305 4244 4250 4355 4786)
00053 #else
00054 #  include<unistd.h>
00055 #  include<sys/time.h>
00056 #  include<sys/times.h>
00057 #  include<sys/resource.h>
00058 #endif
00059 
00060 #ifdef MT_doxy
00061 #  define DOX !\brief
00062 #endif
00063 
00064 //--------- my namespace:
00066 namespace MT{
00067   inline int debugBreakpoint(){
00068     char c; c=0;
00069     //std::cout <<"HALT breakpoint..." <<std::endl; std::cin.getline(&c,1); //force to wait
00070     return 0; //insert a break point here, if you want...
00071   }
00072 }
00073 
00074 
00075 //--------- error handling:
00076 #ifndef HALT
00077 #  define MT_MSG(msg) { std::cerr <<__FILE__ <<':' <<__LINE__ <<": " <<msg <<std::endl; }
00078 #  define HALT(msg) { std::cerr <<"HALT:" <<__FILE__ <<':' <<__LINE__\
00079                       <<":\n --- "<<msg<<" --- "<<std::endl; MT::debugBreakpoint(); abort();}
00080 #endif
00081 
00082 
00083 //--------- check macros:
00084 #ifndef MT_NOCHECK
00085 #  define CHECK(cond,msg) if(!(cond)) HALT("CHECK failed: "<<msg);
00086 #else
00087 #  define CHECK(cond,msg)
00088 #endif
00089 
00090 
00091 //--------- basic defs:
00092 #define MT_PI 3.14159265358979323846
00093 #define MT_2PI (2.*3.14159265358979323846)
00094 #define MT_LN2 0.69314718055994528622676398299518041312694549560546875
00095 typedef unsigned char byte; 
00096 typedef unsigned int uint;  
00097 typedef void (*voidFct)();  
00098 
00099 
00100 //--------- macros for looping
00101 #ifndef forall
00102 #define forall(i,a)            for(a.First(i)              ;a.CheckNext(i);    a.Next(i))
00103 #define forall_rev(i,a)        for(a.Last(i)               ;a.CheckPrev(i);    a.Prev(i))
00104 #define forall_save(i,j,a)     for(a.First(i),j=i,a.Next(j);a.CheckNext(i);i=j,a.Next(j))
00105 #define forall_rev_save(i,j,a) for(a.Last(i) ,j=i,a.Prev(j);a.CheckPrev(i);i=j,a.Prev(j))
00106 #endif
00107 
00108 
00109 //--------- macros to define the standard << and >> operatos for most my classes:
00110 #define stdInPipe(type)\
00111   inline std::istream& operator>>(std::istream& is,type& x){ x.read(is);return is; }
00112 #define stdOutPipe(type)\
00113   inline std::ostream& operator<<(std::ostream& os,const type& x){ x.write(os); return os; }
00114 #define stdPipes(type)\
00115   inline std::istream& operator>>(std::istream& is,type& x){ x.read(is);return is; }\
00116   inline std::ostream& operator<<(std::ostream& os,const type& x){ x.write(os); return os; }
00117 #define fwdStdPipes(type)\
00118   inline std::istream& operator>>(std::istream& is,type& x);\
00119   inline std::ostream& operator<<(std::ostream& os,const type& x);
00120 
00121 
00122 //--------- macros for piping doubles EXACTLY (without rounding errors) in hex coding:
00123 #define OUTHEX(y) "0x" <<std::hex <<*((unsigned long*)&y) <<std::dec
00124 #define INHEX(y) std::hex >>*((unsigned long*)&y) >>std::dec
00125 
00126 
00127 
00128 //--------- standard conversion base type to a class:
00129 #ifndef MT_doxy
00130 
00131 template<class T>
00132 class basetype{
00133 public:
00134   T x; 
00135   basetype():x(){};
00136   basetype(const T _x):x(_x){};
00137 
00138   operator T() const{ return x; } 
00139   void read(std::istream& is){ is >>x; } 
00140   void write(std::ostream& os) const{ os <<x; } 
00141 };
00142 template<class T> stdInPipe(basetype<T>);
00143 template<class T> stdOutPipe(basetype<T>);
00144 
00145 namespace MT{
00146   typedef basetype<byte> Byte;
00147   typedef basetype<int> Int;
00148   typedef basetype<float> Float;
00149   typedef basetype<double> Double;
00150 }
00151 #endif
00152 
00153 //--------- tools to scan (parse) from a stream"
00154 namespace MT{
00155   inline char skip(std::istream&,char* skipchars=" \n\r\t"); //forward declaration..
00156 }
00158 inline std::istream& operator>>(std::istream& is,const char* str){
00159   uint i,n=strlen(str);
00160   char *buf=new char [n+1]; buf[n]=0;
00161   MT::skip(is," \n\r\t");
00162   is.read(buf,n);
00163   if(!is.good() || strcmp(str,buf)){
00164     for(i=n;i--;) is.putback(buf[i]);
00165     is.setstate(std::ios::failbit);
00166     std::cout <<"WARNING: scanning of constant string `" <<str
00167         <<"' failed! (read instead: `" <<buf <<"')" <<std::endl;
00168   }
00169   delete[] buf;
00170   return is;
00171 }
00173 inline std::istream& operator>>(std::istream& is,char* str){
00174   return is >>(const char*)str;
00175 }
00176 
00177 
00178 
00179 //===========================================================================
00180 //
00181 // what follows is somewhat messy organized:
00182 // standard methods for my namespace
00183 //
00184 
00185 namespace MT{
00186   extern int argc;
00187   extern char** argv;
00188   extern std::ifstream cfgFile;
00189   extern bool cfgOpenFlag;
00190   extern std::vector<void*> parameters;
00192   extern bool IOraw;
00193 
00195   std::ofstream& log(const char *name="MT.log",bool _nolog=false);
00196 
00198   void open(std::ofstream& fs,const char *name,char* errmsg="");
00199 
00201   void open(std::ifstream& fs,const char *name,char* errmsg="");
00202 
00206   template<class T>
00207   void save(const T& x,const char *filename){
00208     std::ofstream file;
00209     MT::open(file,filename);
00210     file <<x;
00211     file.close();
00212   }
00213 
00217   template<class T>
00218   void load(T& x,const char *filename){
00219     std::ifstream file;
00220     MT::open(file,filename);
00221     file >>x;
00222     file.close();
00223   }
00224 
00226   inline bool contains(const char* s,char c){
00227     for(uint i=0;s[i];i++) if(s[i]==c) return true;
00228     return false;
00229   }
00230 
00232   inline char skip(std::istream& is,char* skipchars){
00233     char c;
00234     do{ c=is.get(); } while(contains(skipchars,c));
00235     is.putback(c);
00236     return c;
00237   }
00238 
00240   inline void skipLine(std::istream& is){
00241     char c;
00242     do{ c=is.get(); } while(c!='\n');
00243   }
00244 
00246   byte bit(byte *str,uint i);
00247 
00249   void flip(byte& b,uint i);
00250 
00252   void flip(int& b,uint i);
00253 
00256   double modMetric(double x,double y,double mod);
00257 
00259   double sign(double x);
00260 
00262   double linsig(double x);
00263 
00264   void constrain(float& x,float a,float b);
00265 
00267   float phi(float dx,float dy);
00268 
00271   inline double DIV(double x,double y,bool force=false){
00272     if(x==0.) return 0.;
00273     if(force){ if(y==0.) return 0.; }else CHECK(y!=0,"Division by Zero!");
00274     return x/y;
00275   }
00276 
00277   inline double sigmoid11(double x){ return x/(1.+::fabs(x)); }
00278 
00279   template<class T> T MIN(T a,T b){ return a<b?a:b; }
00280   template<class T> T MAX(T a,T b){ return a>b?a:b; }
00281 
00283   double approxExp(double x);
00284 
00286   double Log(double x);
00287 
00289   uint Log2(uint n);
00290 
00292   double sqr(double x);
00293 
00296   double realTime();
00297 
00300   double cpuTime();
00301 
00305   double sysTime();
00306 
00309   double totalTime();
00310   
00312   char *date();
00313 
00315   void wait(double sec);
00316 
00318   void wait();
00319 
00321   long mem();
00322 
00324   void resetTimer();
00325 
00327   double getTimer(bool reset=true);
00328 
00330   void init(int _argc, char *_argv[]);
00331 
00333   bool checkOption(const char *tag);
00334 
00336   bool getOption(const char *tag,char* &option);
00337 
00341   void openConfigFile(char* name=0);
00342 
00343 #ifdef MT_QT
00344 
00345   void initQt();
00346 #ifndef MT_doxy
00347 
00348   struct InitQt{ InitQt(){ initQt(); } };
00349 #endif
00350 #else
00351   inline void initQt(){ MT_MSG("Warning: initQt without QT configured"); }
00352 #endif
00353 }
00354 
00355 
00356 
00357 //===========================================================================
00358 //
00359 // Parameter class - I use it frequently to read parameters from file or cmd line
00360 // 
00361 
00362 namespace MT{
00367   template<class type>
00368   class Parameter{
00369   public:
00370     const char* typeName;
00371     type value,Default;
00372     char* tag;
00373     bool initialized,hasDefault;
00374 
00375 
00376   public:
00378 
00380     Parameter(char* _tag){
00381       typeName=typeid(type).name();
00382       MT::parameters.push_back(this);
00383       initialized=false;
00384       tag=_tag;
00385       hasDefault=false;
00386     };
00387 
00390     Parameter(char* _tag,const type& _default){
00391       typeName=typeid(type).name();
00392       MT::parameters.push_back(this);
00393       initialized=false;
00394       tag=_tag;
00395       hasDefault=true;
00396       Default=_default;
00397     };
00398 
00399     ~Parameter(){
00400       std::vector<void*>::iterator it;
00401       for(it=MT::parameters.begin();it!=MT::parameters.end();it++)
00402   if(*it==this){ MT::parameters.erase(it); return; }
00403     }
00404 
00406 
00408     operator type(){ if(!initialized) initialize(); return value; }
00409 
00411     type& operator()(){ if(!initialized) initialize(); return value; }
00412 
00413 
00415 
00417     type& operator=(const type v){ initialized=true; value=v; return value; }
00418 
00420     void setTag(char* _tag){ tag=_tag; }
00421 
00425     void reInitialize(){ initialized=false; }
00426 
00427 
00429 
00433     bool grabFromCmdLine(){
00434       char* opt;
00435       if(!getOption(tag,opt)) return false;
00436       std::istringstream s(opt);
00437       s >>value;
00438       if(s.fail()) HALT("error when reading parameter from command line: " <<tag);
00439       return true;
00440     }
00441 
00445     bool grabFromCfgFile(){
00446       if(!cfgOpenFlag){
00447   log() <<"..." <<std::endl;
00448   openConfigFile();
00449   log() <<std::setw(40) <<"..." <<": " <<std::setw(5);
00450       }
00451       cfgFile.clear();
00452       cfgFile.seekg(std::ios::beg);
00453       if(!cfgFile.good()) return false;
00454 
00455       unsigned n=strlen(tag);
00456       char *buf=new char [n+2]; memset(buf,0,n+2);
00457       while(cfgFile.good()){
00458   memmove(buf,buf+1,n);
00459   buf[n]=cfgFile.get();
00460   if(buf[n]==' ' || buf[n]==':' || buf[n]=='='){ buf[n]=0; if(!strcmp(tag,buf)) break; buf[n]=':'; }
00461       };
00462       delete[] buf;
00463 
00464       if(!cfgFile.good()) return false;
00465  
00466       skip(cfgFile," :=\n\r\t");
00467       cfgFile >>value;
00468  
00469       if(cfgFile.fail()) HALT("error when reading parameter " <<tag);
00470       return true;
00471     }
00473 
00474   private:
00475     void initialize(){
00476       if(!initialized){
00477         if(!cfgOpenFlag) openConfigFile();
00478   initialized=1;
00479   if(!tag) HALT("uninitialized parameter without tag!");
00480   log() <<std::setw(20) <<tag <<": " <<std::setw(5);
00481   log().flush();
00482 
00483   if(grabFromCmdLine()){
00484     log() <<value <<" [" <<typeid(value).name() <<"] (cmd line!)" <<std::endl;
00485     return;
00486   }
00487 
00488   if(grabFromCfgFile()){
00489     log() <<value <<" [" <<typeid(value).name() <<"]" <<std::endl;
00490     return;
00491   }
00492 
00493   if(hasDefault){
00494     value=Default;
00495     log() <<value <<" [" <<typeid(value).name() <<"] (default!)"<<std::endl;
00496     return;
00497   }
00498 
00499   HALT("could not initialize parameter `" <<tag
00500        <<"': parameter has no default;\n     either use command option `-"
00501        <<tag <<" ...' or specify `"
00502        <<tag <<"= ...' in the config file `MT.cfg'");
00503       }
00504     }
00505   };
00506 
00507 }
00508 
00509 
00510 
00511 //===========================================================================
00512 //
00513 // random number generator
00514 //
00515 
00516 namespace MT{
00520   class Rnd{
00521   private:
00522     bool ready;
00523     int rpoint;     /* Feldindex    */
00524     long rfield[256];   /* Schieberegisterfeld  */
00525 
00526 
00527   public:
00529     Rnd(){ ready=false; };
00530 
00531 
00532   public:
00533 
00534     unsigned long seed(unsigned long n);
00535 
00537     unsigned long seed();
00538 
00540     unsigned long clockSeed();
00541 
00542   public:
00543 
00544     inline uint num(){ if(!ready) seed(); return (uint)rnd250() >> 5; }
00546     inline uint operator ()(){ return num(); }
00548     inline uint num(uint limit){
00549       CHECK(limit,"zero limit in rnd.num()"); return num() % limit; }
00550     inline uint num(int lo,int hi){ return lo+num(hi-lo+1); }
00552     inline uint operator ()(uint i){ return num(i); }
00553     inline uint operator ()(int lo,int hi){ return num(lo,hi); }
00555     inline double uni(){ return ((double)num(1<<22))/(1<<22); }
00557     inline double uni(double low,double high){ return low+uni()*(high-low); }
00559     double gauss(double stdDev);
00563     uint poisson(double mean);
00565 
00566 
00567   private:
00568     inline long  rnd250(){
00569       rpoint = (rpoint+1) & 255;          // Index erhoehen
00570       return rfield[rpoint] =  rfield[(rpoint-250) & 255]
00571                        ^ rfield[(rpoint-103) & 255];
00572     }
00573 
00574     void seed250(long seed);
00575   };
00576 
00578   extern Rnd rnd;
00579 }
00580 
00581 
00582 
00583 //===========================================================================
00584 //
00585 // string class
00586 //
00587 
00588 namespace MT{
00589   typedef std::iostream IOStream;
00590   
00597   class String:public IOStream{
00598   private:
00599     class StringBuf:public std::streambuf{
00600     public:
00601       std::vector<char> arr;
00602       const char* ptr() const{ return &(arr[0]); }
00603       char* ptr(){ return &(arr[0]); }
00604       virtual int overflow(int C = EOF){
00605   arr[arr.size()-1]=C; arr.push_back(0); resetI();
00606   return C;
00607       }
00608       void resetI(){ setg(ptr(),ptr(),ptr()+arr.size()-1); }
00609       char *getIpos(){ return gptr(); }
00610       void setIpos(char* p){
00611   setg(ptr(),p,ptr()+arr.size()-1);
00612       }
00613     };
00614     
00615   public:
00616     StringBuf buf;
00618     String():IOStream(&buf){ clr(); }
00620     String(const String& s):IOStream(&buf){ this->operator=(s); }
00622     String(const char* s):IOStream(&buf){ this->operator=(s); }
00624     IOStream& str(){ return (IOStream&)(*this); }
00627     operator char*(){ return buf.ptr(); }
00629     operator const char*() const{ return buf.ptr(); }
00631     char* ptr(){ return buf.ptr(); }
00633     char operator()(uint i){ return buf.arr[i]; }
00635     void operator=(const String& s){ buf.arr=s.buf.arr; buf.resetI(); }
00637     void operator=(const char *s){ buf.arr.resize(strlen(s)+1); memmove(buf.ptr(),s,strlen(s)+1); buf.resetI(); }
00639     bool operator==(const char *s){ return !strcmp(buf.ptr(),s); }
00641     bool operator==(const String& s){ return !strcmp(buf.ptr(),s.buf.ptr()); }
00643     String& clr(){ buf.arr.resize(1); buf.arr[0]=0; clear(); return *this; }
00647     String& resetI(){ buf.resetI(); clear(); return *this; }
00648     char *getIpos(){ return buf.getIpos(); }
00649     void setIpos(char* p){buf.setIpos(p); }
00650     
00652     uint N() const{ return buf.arr.size()-1; }
00655     template<class T>
00656     String operator+(const T& v) const{
00657       String news(*this); news <<v; return news;
00658     }
00660     void write(std::ostream& os) const{ os <<buf.ptr(); }
00663     void read(std::istream& is,char *stopSymbols="\n\r"){
00664       buf.arr.resize(0);
00665       char c=is.get();
00666       while(is.good() && !MT::contains(stopSymbols,c)){
00667   buf.arr.push_back(c); c=is.get(); }
00668       is.putback(c);
00669       is.clear();
00670       buf.arr.push_back(0);
00671       resetI();
00672     }
00673   };
00674 }
00675 stdPipes(MT::String);
00676 
00677 #define STRING(x) ((MT::String&)(MT::String().str()<<x)).ptr()
00678 
00679 
00680 
00681 //===========================================================================
00682 //
00683 // color class
00684 //
00685 
00686 #ifndef MT_doxy
00687 namespace MT{
00689   class Color{
00690   public:
00691     float
00692       r, 
00693       g, 
00694       b; 
00695     
00697     friend inline Color operator+(const Color& c1,const Color& c2){
00698       return Color(c1.r+c2.r, c1.g+c2.g, c1.b+c2.b); }
00699     
00701     friend inline Color operator*(float f,const Color& c2){
00702       return Color(f*c2.r, f*c2.g, f*c2.b); }
00703     
00704   public:
00706     Color(){ setGray(1.); }
00707     
00709     Color(float red,float green,float blue){ setRgb(red,green,blue); }
00710     
00712     Color& operator=(const Color& c){ r=c.r; g=c.g; b=c.b; return *this; }
00713     
00715     bool operator!(){ if(r==0. && g==0. && b==0.) return true; return false; }
00716     
00718     operator const float*() const{ return (float*)this; }
00719     
00721     void setIndex(unsigned i){
00722       if(!i) setRgb(0.,0.,0.); else setHsv(((i-1)*63)%360,255,255); }
00723     
00725     void setRgb(float red,float green,float blue){ r=red; g=green; b=blue; }
00726     
00728     void setRgbByte(byte red,byte green,byte blue){
00729       r=(float)red/255.; g=(float)green/255.; b=(float)blue/255.; }
00730     
00732     void setHsv(int hue,byte sat,byte val){
00733       float h=(double)hue/60.,s=(double)sat/255.,v=(double)val/255.;
00734       h=fmod(h,6);
00735       r=g=b=0.;
00736       if(h<=1.)        { r=v; g=v*h; }
00737       if(h>1. && h<=2.){ g=v; r=v*(2.-h); }
00738       if(h>2. && h<=3.){ g=v; b=v*(h-2.); }
00739       if(h>3. && h<=4.){ b=v; g=v*(4.-h); }
00740       if(h>4. && h<=5.){ b=v; r=v*(h-4.); }
00741       if(h>5. && h<=6.){ r=v; b=v*(6.-h); }
00742       r=s*r+(1-s)*v;
00743       g=s*g+(1-s)*v;
00744       b=s*b+(1-s)*v;
00745     }
00746     
00748     void setTemp(float temp){
00749       Color hot(1.,0.,0.),middle(1.,1.,0.),cold(0.,0.,1.);
00750       if(temp>1.) temp=1.;
00751       if(temp<0.) temp=0.;
00752       if(temp>.5){ temp=2.*temp-1.; *this=temp*hot + (1.-temp)*middle; }
00753       else{ temp=2.*temp; *this=temp*middle + (1.-temp)*cold; }
00754     }
00755     
00757     void setTemp2(float temp){
00758       Color r(1.,0.,0.),y(1.,1.,0.),zero(.5,.5,.5),g(0.,1.,0.),b(0.,0.,1.);
00759       if(temp>1.) temp=1.;
00760       if(temp<-1.) temp=-1.;
00761       if(temp>.5){  temp=2.*temp-1.; *this=temp*r + (1.-temp)*y; return; }
00762       if(temp>.0){  temp=2.*temp;    *this=temp*y + (1.-temp)*zero; return; }
00763       if(temp>-.5){ temp=-2.*temp;   *this=temp*g + (1.-temp)*zero; return; }
00764       { temp=-2.*temp-1.;*this=temp*b + (1.-temp)*g; return; }
00765     }
00766     
00768     void setGray(float gray){ if(gray<0) gray=0.; if(gray>1) gray=1.; r=g=b=gray; }
00769     
00771     void getRgb(byte& R,byte& G,byte& B) const{
00772       R=(byte)(255.*r); G=(byte)(255.*g); B=(byte)(255.*b); }
00773     
00775     float getGray() const{ return (r+g+b)/3.; }
00776     
00778     void whiten(float f){
00779       if(f>1.) f=1.; else if(f<0.) f=0.;
00780       r+=f*(1.-r); g+=f*(1.-g); b+=f*(1.-b);
00781     }
00782     
00784     void blacken(float f){
00785       if(f>1.) f=1.; else if(f<0.) f=0.;
00786       r-=f*r; g-=f*g; b-=f*b;
00787     }
00788     
00790     void mix(Color& A,Color& B,float f=.5){
00791       if(f>1.) f=1.; else if(f<0.) f=0.;
00792       r=f*A.r+(1.-f)*B.r;
00793       g=f*A.g+(1.-f)*B.g;
00794       b=f*A.b+(1.-f)*B.b;
00795     }
00796     
00798     void mixAdd(Color& A,Color& B,float f=.5){
00799       if(f>1.) f=1.; else if(f<0.) f=0.;
00800       r=1.-f*(1.-A.r)+(1.-f)*(1.-B.r);
00801       g=1.-f*(1.-A.g)+(1.-f)*(1.-B.g);
00802       b=1.-f*(1.-A.b)+(1.-f)*(1.-B.b);
00803     }
00804     
00806     void mixSub(Color& A,Color& B,float f=.5){
00807       if(f>1.) f=1.; else if(f<0.) f=0.;
00808       r=1.-::pow(1.f-A.r,f)*::pow(1.f-B.r,1.f-f);
00809       g=1.-::pow(1.f-A.g,f)*::pow(1.f-B.g,1.f-f);
00810       b=1.-::pow(1.f-A.b,f)*::pow(1.f-B.b,1.f-f);
00811     }
00812     
00814     void min(Color& A,Color& B){
00815       r=A.r<B.r?A.r:B.r;
00816       g=A.g<B.g?A.g:B.g;
00817       b=A.b<B.b?A.b:B.b;
00818     }
00819 
00821     void write(std::ostream& os) const{ os <<"(" <<r <<":" <<g <<":" <<b <<")"; }
00822     
00824     void read(std::istream& is){ is >>"(" >>r >>":" >>g >>":" >>b >>")"; }
00825   };
00826 }
00827 stdPipes(MT::Color);
00828 #endif
00829 
00830 
00831 //===========================================================================
00832 //
00833 // gnuplot calls
00834 //
00835 
00836 void gnuplot(const char* command);
00837 void gnuplotEPS(const char* file,const char* command);
00838 
00839 
00840 //===========================================================================
00841 //
00842 // implementations
00843 //
00844 
00845 #ifdef MT_IMPLEMENTATION
00846 #  include"std.cpp"
00847 #endif
00848 
00849 
00850 
00851 //===========================================================================
00852 //
00853 // USING's
00854 //
00855 
00856 //using std::cout;
00857 //using std::endl;
00858 using std::ofstream;
00859 using std::ifstream;
00860 using MT::rnd;
00861 using MT::Color;
00862 using MT::Parameter;
00863 using MT::String;
00864 
00865 
00866 #endif
[]