00001 #ifndef PhysicsTools_Utilities_FunctClone_h 00002 #define PhysicsTools_Utilities_FunctClone_h 00003 #include <boost/shared_ptr.hpp> 00004 #include <vector> 00005 #include <algorithm> 00006 00007 namespace funct { 00008 00009 template<typename F> 00010 struct Master { 00011 Master(const F& f) : f_(new F(f)), toBeUpdated_(1, true) { 00012 } 00013 double operator()() const { 00014 return get(0); 00015 } 00016 double operator()(double x) const { 00017 return get(0, x); 00018 } 00019 void add() const { 00020 toBeUpdated_.resize(size() + 1, true); 00021 } 00022 size_t size() const { return toBeUpdated_.size(); } 00023 double get(size_t i) const { 00024 if(toBeUpdated_[i]) update(); 00025 toBeUpdated_[i] = true; 00026 return value_; 00027 } 00028 double get(size_t i, double x) const { 00029 if(toBeUpdated_[i]) update(x); 00030 toBeUpdated_[i] = true; 00031 return value_; 00032 } 00033 private: 00034 void reset() const { 00035 std::fill(toBeUpdated_.begin(), toBeUpdated_.end(), true); 00036 } 00037 void clear() const { 00038 std::fill(toBeUpdated_.begin(), toBeUpdated_.end(), false); 00039 } 00040 void update() const { 00041 clear(); 00042 value_ = (*f_)(); 00043 } 00044 void update(double x) const { 00045 clear(); 00046 value_ = (*f_)(x); 00047 } 00048 const boost::shared_ptr<F> f_; 00049 mutable double value_; 00050 mutable std::vector<bool> toBeUpdated_; 00051 }; 00052 00053 template<typename F> 00054 struct Slave { 00055 Slave(const Master<F>& master) : master_(master), id_(master.size()) { 00056 assert(id_ > 0); 00057 master_.add(); 00058 } 00059 double operator()() const { return master_.get(id_); } 00060 double operator()(double x) const { return master_.get(id_, x); } 00061 void setId(size_t i) { id_ = i; } 00062 private: 00063 const Master<F> & master_; 00064 size_t id_; 00065 }; 00066 00067 template<typename F> 00068 Master<F> master(const F& f) { return Master<F>(f); } 00069 00070 template<typename F> 00071 Slave<F> slave(const Master<F>& m) { return Slave<F>(m); } 00072 } 00073 00074 #endif