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