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