00001 00024 #ifndef GALOIS_ACCUMULATOR_H 00025 #define GALOIS_ACCUMULATOR_H 00026 00027 #include "Galois/Runtime/PerThreadStorage.h" 00028 00029 #include <limits> 00030 00031 namespace Galois { 00032 00044 template<typename T, typename BinFunc> 00045 class GReducible { 00046 protected: 00047 BinFunc m_func; 00048 Galois::Runtime::PerThreadStorage<T> m_data; 00049 const T m_initial; 00050 00051 explicit GReducible(const BinFunc& f, const T& initial): m_func(f), m_initial(initial) { } 00052 00053 public: 00057 explicit GReducible(const BinFunc& f = BinFunc()): m_func(f), m_initial(T()) { } 00058 00063 void update(const T& rhs) { 00064 T& lhs = *m_data.getLocal(); 00065 m_func(lhs, rhs); 00066 } 00067 00071 T& reduce() { 00072 T& d0 = *m_data.getLocal(); 00073 for (unsigned int i = 1; i < m_data.size(); ++i) { 00074 T& d = *m_data.getRemote(i); 00075 m_func(d0, d); 00076 d = m_initial; 00077 } 00078 return d0; 00079 } 00080 00084 void reset() { 00085 for (unsigned int i = 0; i < m_data.size(); ++i) { 00086 *m_data.getRemote(i) = m_initial; 00087 } 00088 } 00089 }; 00090 00091 00093 template<typename T> 00094 struct gmax { 00095 const T& operator()(const T& lhs, const T& rhs) const { 00096 return std::max<T>(lhs, rhs); 00097 } 00098 }; 00099 00101 template<typename T> 00102 struct gmin { 00103 const T& operator()(const T& lhs, const T& rhs) const { 00104 return std::min<T>(lhs, rhs); 00105 } 00106 }; 00107 00112 template<typename BinFunc> 00113 struct ReduceAssignWrap { 00114 BinFunc fn; 00115 ReduceAssignWrap(const BinFunc& f = BinFunc()): fn(f) { } 00116 template<typename T> 00117 void operator()(T& lhs, const T& rhs) const { 00118 lhs = fn(lhs, rhs); 00119 } 00120 }; 00121 00126 template<typename BinFunc> 00127 struct ReduceVectorWrap { 00128 BinFunc fn; 00129 ReduceVectorWrap(const BinFunc& f = BinFunc()): fn(f) { } 00130 template<typename T> 00131 void operator()(T& lhs, const T& rhs) const { 00132 if (lhs.size() < rhs.size()) 00133 lhs.resize(rhs.size()); 00134 typename T::iterator ii = lhs.begin(); 00135 for (typename T::const_iterator jj = rhs.begin(), ej = rhs.end(); jj != ej; ++ii, ++jj) { 00136 fn(*ii, *jj); 00137 } 00138 } 00139 }; 00140 00145 template<typename BinFunc> 00146 struct ReduceMapWrap { 00147 BinFunc fn; 00148 ReduceMapWrap(const BinFunc& f = BinFunc()): fn(f) { } 00149 template<typename T> 00150 void operator()(T& lhs, const T& rhs) const { 00151 for (typename T::const_iterator jj = rhs.begin(), ej = rhs.end(); jj != ej; ++jj) { 00152 fn(lhs[jj->first], jj->second); 00153 } 00154 } 00155 }; 00156 00161 template<typename CollectionTy,template<class> class AdaptorTy> 00162 struct ReduceCollectionWrap { 00163 typedef typename CollectionTy::value_type value_type; 00164 00165 void operator()(CollectionTy& lhs, const CollectionTy& rhs) { 00166 AdaptorTy<CollectionTy> adapt(lhs, lhs.begin()); 00167 std::copy(rhs.begin(), rhs.end(), adapt); 00168 } 00169 00170 void operator()(CollectionTy& lhs, const value_type& rhs) { 00171 AdaptorTy<CollectionTy> adapt(lhs, lhs.begin()); 00172 *adapt = rhs; 00173 } 00174 }; 00175 00182 template<typename T, typename BinFunc> 00183 class GSimpleReducible: public GReducible<T, ReduceAssignWrap<BinFunc> > { 00184 typedef GReducible<T, ReduceAssignWrap<BinFunc> > base_type; 00185 public: 00186 explicit GSimpleReducible(const BinFunc& func = BinFunc()): base_type(func) { } 00187 }; 00188 00190 template<typename T> 00191 class GAccumulator: public GReducible<T, ReduceAssignWrap<std::plus<T> > > { 00192 typedef GReducible<T, ReduceAssignWrap<std::plus<T> > > base_type; 00193 00194 public: 00195 GAccumulator& operator+=(const T& rhs) { 00196 base_type::update(rhs); 00197 return *this; 00198 } 00199 00200 GAccumulator& operator-=(const T& rhs) { 00201 base_type::update(-rhs); 00202 return *this; 00203 } 00204 00205 T unsafeRead() const { 00206 T d0 = *this->m_data.getRemote(0); 00207 for (unsigned int i = 1; i < this->m_data.size(); ++i) { 00208 const T& d = *this->m_data.getRemote(i); 00209 this->m_func(d0, d); 00210 } 00211 return d0; 00212 } 00213 }; 00214 00220 template<typename CollectionTy,template<class> class AdaptorTy> 00221 class GCollectionAccumulator: public GReducible<CollectionTy, ReduceCollectionWrap<CollectionTy, AdaptorTy> > { 00222 typedef ReduceCollectionWrap<CollectionTy, AdaptorTy> Func; 00223 typedef GReducible<CollectionTy, Func> base_type; 00224 typedef typename CollectionTy::value_type value_type; 00225 00226 Func func; 00227 00228 public: 00229 void update(const value_type& rhs) { 00230 CollectionTy& v = *this->m_data.getLocal(); 00231 func(v, rhs); 00232 } 00233 }; 00234 00236 template<typename SetTy> 00237 class GSetAccumulator: public GCollectionAccumulator<SetTy, std::insert_iterator> { }; 00238 00240 template<typename VectorTy> 00241 class GVectorAccumulator: public GCollectionAccumulator<VectorTy, std::back_insert_iterator> { }; 00242 00245 template<typename VectorTy> 00246 class GVectorElementAccumulator: public GReducible<VectorTy, ReduceVectorWrap<ReduceAssignWrap<std::plus<typename VectorTy::value_type> > > > { 00247 typedef ReduceAssignWrap<std::plus<typename VectorTy::value_type> > ElementFunc; 00248 typedef GReducible<VectorTy, ReduceVectorWrap<ElementFunc> > base_type; 00249 typedef typename VectorTy::value_type value_type; 00250 00251 ElementFunc func; 00252 00253 public: 00254 00255 void resize(size_t s) { 00256 for (int i = 0; i < this->m_data.size(); ++i) 00257 this->m_data.getRemote(i)->resize(s); 00258 } 00259 00260 VectorTy& getLocal() { 00261 return *this->m_data.getLocal(); 00262 } 00263 00264 void update(size_t index, const value_type& rhs) { 00265 VectorTy& v = *this->m_data.getLocal(); 00266 if (v.size() <= index) 00267 v.resize(index + 1); 00268 func(v[index], rhs); 00269 } 00270 }; 00271 00274 template<typename MapTy> 00275 class GMapElementAccumulator: public GReducible<MapTy, ReduceMapWrap<ReduceAssignWrap<std::plus<typename MapTy::mapped_type> > > > { 00276 typedef ReduceAssignWrap<std::plus<typename MapTy::mapped_type> > ElementFunc; 00277 typedef GReducible<MapTy, ReduceMapWrap<ElementFunc> > base_type; 00278 typedef typename MapTy::mapped_type mapped_type; 00279 typedef typename MapTy::key_type key_type; 00280 00281 ElementFunc func; 00282 00283 public: 00284 void update(const key_type& index, const mapped_type& rhs) { 00285 MapTy& v = *this->m_data.getLocal(); 00286 func(v[index], rhs); 00287 } 00288 }; 00289 00291 template<typename T> 00292 class GReduceMax: public GReducible<T, ReduceAssignWrap<gmax<T> > > { 00293 typedef GReducible<T, ReduceAssignWrap<gmax<T> > > base_type; 00294 public: 00295 GReduceMax(): base_type(ReduceAssignWrap<gmax<T> >(), std::numeric_limits<T>::min()) { } 00296 }; 00297 00299 template<typename T> 00300 class GReduceMin: public GReducible<T, ReduceAssignWrap<gmin<T> > > { 00301 typedef GReducible<T, ReduceAssignWrap<gmin<T> > > base_type; 00302 public: 00303 GReduceMin(): base_type(ReduceAssignWrap<gmin<T> >(), std::numeric_limits<T>::max()) { } 00304 }; 00305 00306 } 00307 #endif