Test entry method templates: register EPs and reducers in initnode, not initproc...
[charm.git] / tests / charm++ / method_templates / utils.h
1 #ifndef UTILS_H
2 #define UTILS_H
3
4 #include "charm++.h"
5 #include <iostream>
6
7 typedef double libdtype;
8
9 // A pup-friendly functor identical to return value of std::bind2nd(cmp(), threshold)
10 template <typename cmp>
11 class count {
12     private:
13         libdtype threshold;
14         int num;
15         cmp c;
16     public:
17         //
18         count(const libdtype _t=0): threshold(_t), num(0) {}
19
20         // Operate on an input element
21         inline void operator() (libdtype* first, libdtype *last)
22         {
23             for (libdtype *ptr = first; ptr != last; ptr++)
24                 if (c(*ptr, threshold)) num++;
25         }
26
27         // Serialize the internals
28         void pup(PUP::er &p) { p | threshold; p | num; }
29
30         // Spit results to ostream
31         friend std::ostream& operator<< (std::ostream& out, const count& obj) {
32             out << "threshold = "<< obj.threshold << "; "
33                 << "num = " << obj.num;
34             return out;
35         }
36
37         // Reducer function to accumulate across multiple count objects
38         static CkReductionMsg* reduce_count(int nMsg, CkReductionMsg **msgs)
39         {
40             CkAssert(nMsg > 0);
41             count<cmp>* result = (count<cmp>*) msgs[0]->getData();
42             for (int i = 1; i < nMsg; ++i)
43             {
44                 count<cmp> *contrib = (count<cmp>*) msgs[i]->getData();
45                 // Compare the thresholds themselves and use the appropriate one
46                 if ( result->c(contrib->threshold, result->threshold) )
47                     result->threshold = contrib->threshold;
48                 result->num += contrib->num;
49             }
50             return CkReductionMsg::buildNew(sizeof(count<cmp>), result);
51         }
52 };
53
54
55 // Functor that computes the sum and avg of a sequence of integers
56 class avg {
57     private:
58         libdtype sum;
59         int num;
60     public:
61         avg(): sum(0), num(0) {}
62
63         // Operate on an input element
64         inline void operator() (libdtype* first, libdtype *last)
65         {
66             num += std::distance(first, last);
67             for (libdtype *ptr = first; ptr != last; ptr++)
68                 sum += *ptr;
69         }
70
71         // Serialize the internals
72         void pup(PUP::er &p) { p | sum; p | num; }
73
74         // Spit results to ostream
75         friend std::ostream& operator<< (std::ostream& out, const avg& obj) {
76             out << "num = " << obj.num << "; "
77                 << "sum = " << obj.sum << "; "
78                 << "avg = " << ( obj.num ? (double)obj.sum/obj.num : obj.sum );
79             return out;
80         }
81
82         // Reducer function to accumulate across multiple avg objects
83         static CkReductionMsg* reduce_avg(int nMsg, CkReductionMsg **msgs)
84         {
85             CkAssert(nMsg > 0);
86             avg* result = (avg*) msgs[0]->getData();
87             for (int i = 1; i < nMsg; ++i)
88             {
89                 avg *contrib = (avg*) msgs[i]->getData();
90                 result->sum += contrib->sum;
91                 result->num += contrib->num;
92             }
93             return CkReductionMsg::buildNew(sizeof(avg), result);
94         }
95 };
96
97 #endif // UTILS_H