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

valuegen.h

Go to the documentation of this file.
00001 
00007 #ifndef __VALUEGEN_H__
00008 #define __VALUEGEN_H__
00009 
00010 #ifdef ANSI_COMPATIBLE
00011 /* Optional: provides definition of M_PI, drand48, and srand48 on systems lacking them */
00012 #include "ind_types.h"
00013 #endif
00014 
00015 #ifndef NO_VALGEN_STRINGS
00016 /* Optional: support for reading expressions from strings */
00017 #include "stringparser.h"
00018 #endif
00019 
00020 #include "vgen.h"
00021 
00022 
00023 /******************************************************************************/
00024 /* General-purpose random-value generators for various distributions          */
00025 /******************************************************************************/
00026 
00028 typedef double (*randomgen_fnPtr) ( double mean, double radius );
00029 
00035 inline double uniform_distribution( double mean=0.5, double radius=0.5)
00036 {  return mean + 2.0*radius*(shuffled_rand() - 0.5); }
00037 
00038 
00039 
00045 inline double normal_distribution(  double mean=0.0, double radius=1.0)
00046 {  return mean + radius*(sqrt((-2.0) * log(shuffled_rand())) * cos(2*M_PI * shuffled_rand()));  }
00047 
00048 
00049 
00050 
00051 /******************************************************************************/
00052 /* ValueGenerator objects                                                     */
00053 /******************************************************************************/
00092 template<class T=double>
00093 class ValueGenerator : public ValueGen {
00094 public:
00095   /* Constructors */
00096   ValueGenerator() : val(0), vp(&val) { }                  
00097   ValueGenerator(T  value) : val(value), vp(&val) { }      
00098   ValueGenerator(T* value_pointer) : vp(value_pointer) { } 
00100 #ifndef NO_VALGEN_STRINGS
00101   ValueGenerator(StringArgs& args)
00102     : val(0), vp(&val)  /* Legal default values */
00103     {  args.next(T(0),vp); }
00104 #endif
00105   
00106   ValueGenerator(const ValueGenerator& other) /* Copy constructor */
00107     : ValueGen(), val(other.value()),
00108       /* Tricky -- should copy pointer only if external to other */
00109       vp( (other.vp==&other.val)? &val : other.vp ) { }
00110   virtual ~ValueGenerator() { }
00111 
00112   
00114   void operator= (T new_value) { *vp=new_value; }
00115 
00117   T* valueptr()       const { return  vp; }
00118   //ValueGenerator<>* genptr() { return  this; }
00119 
00120   /* Automatic conversion to type T (disabled) */
00121   //operator T() const { return *vp; } 
00122 
00124   T value()    const { return *vp; }
00125 
00126 
00129   
00130   virtual bool next()  { return true; }
00131   virtual void reset() { }
00132 
00134   virtual ValueGenerator<T>* clone() const
00135     { return new ValueGenerator(*this); };
00136 
00138   virtual void relink(T* ptr) {  if (vp != &val) vp = ptr;  }
00140   
00141 private:
00143   T  val;
00145   T* vp;
00146 };
00147 
00148 
00150 typedef ValueGenerator<double> DGen;
00151 
00152 
00154 template<class T=double, randomgen_fnPtr random_fn=uniform_distribution>
00155 class ValueGenerator_Random : public ValueGenerator<T> {
00156   T v,m,r;
00157 
00158   T* mp; 
00159   T* rp; 
00161 public:
00162   ValueGenerator_Random(T mean, T radius=0) 
00163    : ValueGenerator<T>(&v), v(mean), m(mean), r(radius), mp(&m), rp(&r) { }
00164 
00165   ValueGenerator_Random(T* mean_ptr, T* radius_ptr) 
00166     : ValueGenerator<T>(&v), v(*mean_ptr), mp(mean_ptr), rp(radius_ptr) { }
00167 
00168 #ifndef NO_VALGEN_STRINGS
00169   ValueGenerator_Random(StringArgs& args)
00170     : ValueGenerator<T>(&v), v(0), m(0), r(0), mp(&m), rp(&r) {
00171       args.next(T(0),mp); v = *mp;
00172       args.next(T(0),rp);
00173     }
00174 #endif
00175   
00176   ValueGenerator_Random(const ValueGenerator_Random& other)
00177     : ValueGenerator<T>(&v), v(other.v), m(other.m), r(other.r),
00178       mp( (other.mp==&other.m)? &m : other.mp ),
00179       rp( (other.rp==&other.r)? &r : other.rp ) { } 
00181   virtual bool next()
00182     {  v = random_fn( *mp, *rp ); return true; }
00183 
00184   virtual void reset() { v=*mp; } // Resets to mean value
00185   
00186   virtual ValueGenerator<T>* clone() const { return new ValueGenerator_Random(*this); };
00187 };
00188 
00189 
00190 
00201 template<class T=double, randomgen_fnPtr random_fn=uniform_distribution, bool crop=true>
00202 class ValueGenerator_Correlate
00203   : public ValueGenerator<T> {
00204   T v, lb, ub, range;
00205   T* mp;          
00206   T* uncorr_p;    
00208 public:
00210   ValueGenerator_Correlate(T* master_value_ptr, T* uncorrelation_ptr,
00211                            T lower_bound, T upper_bound)
00212     : ValueGenerator<T>(&v), v(*master_value_ptr),
00213       lb(lower_bound), ub(upper_bound), range(upper_bound-lower_bound),
00214       mp(master_value_ptr), uncorr_p(uncorrelation_ptr) { }
00215 
00216 #ifndef NO_VALGEN_STRINGS
00217   ValueGenerator_Correlate(StringArgs& args, T* ref=0)
00218     : ValueGenerator<T>(&v), v(0), lb(0), ub(0), mp(ref? ref : &v), uncorr_p(&v) { 
00219       /*
00220         The defaults for mp and uncorr_p are legal but are *not* 
00221         at all useful, so those arguments really are required, 
00222         and are required to be pointers.  The other two
00223         arguments do not currently accept pointers, but could
00224         be extended to do so.
00225         
00226         If present, the ref argument is used in place of the first argument
00227         expected in the string, and the string is parsed from the beginning
00228         for the next argument.
00229       */
00230       if (!ref) args.next(v,mp); 
00231       args.next(v,uncorr_p);
00232       lb = args.next(T(0));
00233       ub = args.next(T(0));
00234       
00235       v = *mp;  
00236       range = ub-lb; 
00237     }
00238 #endif
00239   
00240   ValueGenerator_Correlate(const ValueGenerator_Correlate& other)
00241     : ValueGenerator<T>(&v), v(other.v), lb(other.lb), ub(other.ub), range(other.range),
00242       mp(other.mp), uncorr_p( other.uncorr_p)  { } 
00244   virtual bool next() {
00245     const T uncorr_radius = range*(*uncorr_p);
00246 
00247     /* This conditional will presumably be optimized away */
00248     if (crop) {
00249       const T low    = std::max(lb,*mp-uncorr_radius);
00250       const T high   = std::min(ub,*mp+uncorr_radius);
00251       const T radius = (high-low)/2;
00252       const T mean   = low+radius;
00253       v = random_fn(mean, radius);
00254     }
00255     else
00256       v = random_fn(*mp, uncorr_radius);
00257 
00258     return true;
00259   }
00260 
00261   virtual void reset() { v=*mp; } // Resets to master value
00262 
00263   virtual ValueGenerator<T>* clone() const { return new ValueGenerator_Correlate(*this); };
00264 };
00265 
00266 
00267 
00269 template<class T=double>
00270 class ValueGenerator_Increment : public ValueGenerator<T> {
00271   T v,s,inc;
00272 
00273 public:
00274   ValueGenerator_Increment(T init_value, T increment=1)
00275     : ValueGenerator<T>(&v), v(init_value), s(init_value), inc(increment) { }
00276 
00277 #ifndef NO_VALGEN_STRINGS
00278 
00279   ValueGenerator_Increment(StringArgs& args)
00280     : ValueGenerator<T>(&v), v(0), s(0), inc(1) {
00281       s   = args.next(T(0));
00282       v   = s;
00283       inc = args.next(T(1));
00284     }
00285 #endif
00286   
00287   ValueGenerator_Increment(const ValueGenerator_Increment& other)
00288     : ValueGenerator<T>(&v), v(other.v), s(other.s), inc(other.inc) { } 
00290   virtual bool next()  { v += inc; return true; }
00291   virtual void reset() { v  = s; } // Resets to starting value
00292 
00293   virtual ValueGenerator<T>* clone() const { return new ValueGenerator_Increment(*this); };
00294 };
00295 
00296 
00297 
00302 #ifndef NO_VALGEN_STRINGS
00303 
00304 template<class T=double>
00305 class ValueGenerator_Expression : public ValueGenerator<T> {
00306   const StringParser* p;
00307   T v;
00308   string expr;
00309   
00310 public:
00311   ValueGenerator_Expression(string expression, const StringParser& parser)
00312     : ValueGenerator<T>(&v), p(parser.clone()), v(p->parse(expression,v)), expr(expression) { }
00313   
00314   ValueGenerator_Expression(StringArgs& args)
00315     : ValueGenerator<T>(&v), p(args.p.clone()), v(0), expr("") {
00316       expr = args.next(string(""));
00317       p->parse(expr,v);
00318     }
00319   
00320   ValueGenerator_Expression(const ValueGenerator_Expression& other)
00321     : ValueGenerator<T>(&v), p(other.p->clone()), v(other.v), expr(other.expr) { } 
00323   ~ValueGenerator_Expression() {  delete p;  }
00324   
00325   virtual bool next() {  p->parse(expr,v); return true; }
00326   
00327   virtual void reset() { next(); } // Resets to current value of expr
00328 
00329   virtual ValueGenerator<T>* clone() const
00330     { return new ValueGenerator_Expression(*this); };
00331 };
00332 #endif
00333 
00334 
00335 
00336 
00337 /******************************************************************************/
00338 /* ValueGeneratorFactory                                                      */
00339 /******************************************************************************/
00340 
00341 #ifndef NO_VALGEN_STRINGS
00342 
00343 
00348 template<class T=double>
00349 class VGenFactory {
00350 public:
00351   VGenFactory()          { };
00352   virtual ~VGenFactory() { }
00353 
00361   virtual ValueGenerator<T>* create(StringArgs args) const =0;
00362 
00364   virtual ValueGenerator<T>* create(StringArgs args, T* ref) const =0;
00365   
00366 protected:
00369   virtual void error(const string&) const {  }
00372   virtual void warning(const string&) const {  }
00373 };
00374 
00375 
00376 
00384 template<class T=double,
00385   randomgen_fnPtr urf=uniform_distribution,
00386   randomgen_fnPtr nrf=normal_distribution>
00387 
00388 class ValueGeneratorFactory : public VGenFactory<T> {
00389 public:
00390   ValueGeneratorFactory() : VGenFactory<T>() { }
00391   virtual ~ValueGeneratorFactory() { }
00392   
00394   virtual ValueGenerator<T>* create(StringArgs args) const {
00395     
00396     /* Empty string is invalid */
00397     if (args.empty()) {
00398       warning("ValueGenerator: empty expression");
00399       return new ValueGenerator<T>;
00400     }
00401     
00402     /* Convenient shorthand: A single item specifies a numeric constant */
00403     else if (args.oneremaining())
00404       return new ValueGenerator<T>(args);
00405     
00406     /* Anything else should be the name of the ValueGenerator followed by its arguments */
00407     else {
00408       const string& vgclass  = args.next(string(""));
00409 
00410       if      (vgclass=="Random")     {  return new ValueGenerator_Random<T,urf>(          args);  }
00411       else if (vgclass=="Normal")     {  return new ValueGenerator_Random<T,nrf>(          args);  }
00412       else if (vgclass=="Increment")  {  return new ValueGenerator_Increment<T>(           args);  }
00413       else if (vgclass=="Expression") {  return new ValueGenerator_Expression<T>(          args);  }
00414       else if (vgclass=="Correlate")  {  return new ValueGenerator_Correlate<T,urf,true> ( args);  }
00415       else {
00416         error("ValueGenerator: Don't know about type `" + vgclass + "'");
00417         return new ValueGenerator<T>;
00418       }
00419     }
00420   }
00421 
00422 
00424   virtual ValueGenerator<T>* create(StringArgs args, T* ref) const {
00425     if (args.nextis(string("Uncorrelate"))) {
00426       
00427       if (ref) return new ValueGenerator_Correlate<T,urf,true>(args,ref);
00428       else {
00429         /* Swallow unneeded args */
00430         T dummyf;
00431         ValueGenerator_Correlate<T,urf,true> dummy(args,&dummyf);
00432       }
00433     }
00434     if (ref) return new ValueGenerator<T>(ref);
00435     
00436     /* Otherwise just construct and return a normal ValueGenerator */
00437     return create(args);
00438   }
00439 };
00440 #endif
00441 
00442 
00443 
00444 
00445 #endif

Generated at Mon Aug 21 00:30:55 2000 for RF-LISSOM by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000