1 // -*- C++ -*-
2 // ACL:license
3 // ----------------------------------------------------------------------
4 // This software and ancillary information (herein called "SOFTWARE")
5 // called PETE (Portable Expression Template Engine) is
6 // made available under the terms described here.  The SOFTWARE has been
7 // approved for release with associated LA-CC Number LA-CC-99-5.
8 //
9 // Unless otherwise indicated, this SOFTWARE has been authored by an
10 // employee or employees of the University of California, operator of the
11 // Los Alamos National Laboratory under Contract No.  W-7405-ENG-36 with
12 // the U.S. Department of Energy.  The U.S. Government has rights to use,
13 // reproduce, and distribute this SOFTWARE. The public may copy, distribute,
14 // prepare derivative works and publicly display this SOFTWARE without
15 // charge, provided that this Notice and any statement of authorship are
16 // reproduced on all copies.  Neither the Government nor the University
17 // makes any warranty, express or implied, or assumes any liability or
18 // responsibility for the use of this SOFTWARE.
19 //
20 // If SOFTWARE is modified to produce derivative works, such modified
21 // SOFTWARE should be clearly marked, so as not to confuse it with the
22 // version available from LANL.
23 //
24 // For more information about PETE, send e-mail to pete@acl.lanl.gov,
25 // or visit the PETE web page at http://www.acl.lanl.gov/pete/.
26 // ----------------------------------------------------------------------
27 // ACL:license
28 
29 #ifndef PETE_PETE_COMBINERS_H
30 #define PETE_PETE_COMBINERS_H
31 
32 namespace qmcplusplus
33 {
34 ///////////////////////////////////////////////////////////////////////////////
35 //
36 // WARNING: THIS FILE IS FOR INTERNAL PETE USE. DON'T INCLUDE IT YOURSELF
37 //
38 ///////////////////////////////////////////////////////////////////////////////
39 
40 //-----------------------------------------------------------------------------
41 //
42 // CLASS NAMES
43 //   Combine1<A,Op,Tag>
44 //   Combine2<A,B,Op,Tag>
45 //   Combine3<A,B,C,Op,Tag>
46 //
47 // DESCRIPTION
48 //   A,B, and C are the types of the combined arguments
49 //   Op is the type of the operator from the expression tree
50 //   Tag is the tag type which selects the type of combiner operation
51 //
52 //   Users create their own combiner operations by specializing these
53 //   three structs for a particular user defined tag.  A typical example
54 //   might be an operation that compares the domains of all the leaves in
55 //   an expression.
56 //
57 //   Combine1 requires the user to define:
58 //      typedef ... Type_t;
59 //         - the return type of the combination
60 //      static Type_t combine(const A &a, const Op &op, const Tag &t) {}
61 //         - a function that combines a
62 //
63 //   Combine2 requires the user to define:
64 //      typedef ... Type_t;
65 //         - the return type of the combination
66 //      static Type_t combine(const A &a, const B &b, const Op &op,
67 //         const Tag &t) {}
68 //         - a function that combines a and b
69 //
70 //   Combine3 requires the user to define:
71 //      typedef ... Type_t;
72 //         - the return type of the combination
73 //      static Type_t combine(const A &a, const B &b, const C &c,
74 //         const const Op &op, const Tag &t) {}
75 //         - a function that combines a and b and c
76 //
77 //   The default actions for combiners are:
78 //
79 //      Combine1 - returns the arguments
80 //      Combine2 - no default action... the user must define this at least
81 //      Combine3 - uses Combine2 to combine a and b and combine that with c
82 //
83 //-----------------------------------------------------------------------------
84 
85 template<class A, class Op, class Tag>
86 struct Combine1
87 {
88   typedef A Type_t;
combineCombine189   inline static Type_t combine(const A& a, const Op&, const Tag&) { return a; }
90 };
91 
92 template<class A, class B, class Op, class Tag>
93 struct Combine2
94 {
95   // no default action.  It's an error to not specialize this struct.
96 };
97 
98 template<class A, class B, class C, class Op, class Tag>
99 struct Combine3
100 {
101   typedef typename Combine2<A, B, Op, Tag>::Type_t Type1_t;
102   typedef typename Combine2<Type1_t, C, Op, Tag>::Type_t Type_t;
combineCombine3103   inline static Type_t combine(const A& a, const B& b, const C& c, const Op& op, const Tag& t)
104   {
105     return Combine2<Type1_t, C, Op, Tag>::combine(Combine2<A, B, Op, Tag>::combine(a, b, op, t), c, op, t);
106   }
107 };
108 
109 //-----------------------------------------------------------------------------
110 //
111 // FUNCTION NAME
112 //   peteCombine()
113 //
114 // DESCRIPTION
115 //   These functions provide a simple user interface to PETE's CombineN
116 //   functors.  For example:
117 //
118 //   peteCombine(a, b, op, tag);
119 //
120 //   is a synonym for:
121 //
122 //   Combine2<A, B, Op, Tag>::combine(a, b, op, tag);
123 //
124 //-----------------------------------------------------------------------------
125 
126 template<class A, class Op, class Tag>
peteCombine(const A & a,const Op & op,const Tag & t)127 inline typename Combine1<A, Op, Tag>::Type_t peteCombine(const A& a, const Op& op, const Tag& t)
128 {
129   return Combine1<A, Op, Tag>::combine(a, op, t);
130 }
131 
132 template<class A, class B, class Op, class Tag>
peteCombine(const A & a,const B & b,const Op & op,const Tag & t)133 inline typename Combine2<A, B, Op, Tag>::Type_t peteCombine(const A& a, const B& b, const Op& op, const Tag& t)
134 {
135   return Combine2<A, B, Op, Tag>::combine(a, b, op, t);
136 }
137 
138 template<class A, class B, class C, class Op, class Tag>
peteCombine(const A & a,const B & b,const C & c,const Op & op,const Tag & t)139 inline typename Combine3<A, B, C, Op, Tag>::Type_t peteCombine(const A& a,
140                                                                const B& b,
141                                                                const C& c,
142                                                                const Op& op,
143                                                                const Tag& t)
144 {
145   return Combine3<A, B, C, Op, Tag>::combine(a, b, c, op, t);
146 }
147 
148 //-----------------------------------------------------------------------------
149 //
150 // CLASS NAME
151 //   TreeCombine
152 //
153 // DESCRIPTION
154 //   This combiner is provided so that the user can write a functor
155 //   that modifies the leaves of an expression and use
156 //   ForEach<Expr,UserFunctor,TreeCombine> to get the entire expression
157 //   back with modified leaves.
158 //
159 //   This type of operation is useful when expressions are being
160 //   passed around.  For example, you might subset and expression and pass
161 //   that result to another function.  The type of expression tree that you
162 //   are passing has subsetted nodes, and could be a different type from the
163 //   original expression.
164 //
165 //-----------------------------------------------------------------------------
166 
167 struct TreeCombine
168 {
169   PETE_EMPTY_CONSTRUCTORS(TreeCombine)
170 };
171 
172 template<class A, class Op>
173 struct Combine1<A, Op, TreeCombine>
174 {
175   typedef UnaryNode<Op, A> Type_t;
176   inline static Type_t combine(const A& a, const Op& op, const TreeCombine& t) { return Type_t(op, a); }
177 };
178 
179 template<class A, class B, class Op>
180 struct Combine2<A, B, Op, TreeCombine>
181 {
182   typedef BinaryNode<Op, A, B> Type_t;
183   inline static Type_t combine(const A& a, const B& b, const Op& op, const TreeCombine& t) { return Type_t(op, a, b); }
184 };
185 
186 template<class A, class B, class C, class Op>
187 struct Combine3<A, B, C, Op, TreeCombine>
188 {
189   typedef TrinaryNode<Op, A, B, C> Type_t;
190   inline static Type_t combine(const A& a, const B& b, const C& c, const Op& op, const TreeCombine& t)
191   {
192     return Type_t(op, a, b, c);
193   }
194 };
195 
196 
197 //-----------------------------------------------------------------------------
198 //
199 // CLASS NAME
200 //   OpCombine
201 //
202 // DESCRIPTION
203 //   A combiner that uses the operations in the expression tree.
204 //
205 //-----------------------------------------------------------------------------
206 
207 struct OpCombine
208 {
209   PETE_EMPTY_CONSTRUCTORS(OpCombine)
210 };
211 
212 template<class A, class Op>
213 struct Combine1<A, Op, OpCombine>
214 {
215   typedef typename UnaryReturn<A, Op>::Type_t Type_t;
216   inline static Type_t combine(A a, Op op, OpCombine) { return op(a); }
217 };
218 
219 template<class A, class B, class Op>
220 struct Combine2<A, B, Op, OpCombine>
221 {
222   typedef typename BinaryReturn<A, B, Op>::Type_t Type_t;
223   inline static Type_t combine(A a, B b, Op op, OpCombine) { return op(a, b); }
224 };
225 
226 template<class A, class B, class C, class Op>
227 struct Combine3<A, B, C, Op, OpCombine>
228 {
229   typedef typename TrinaryReturn<A, B, C, Op>::Type_t Type_t;
230   inline static Type_t combine(A a, B b, C c, Op op, OpCombine) { return op(a, b, c); }
231 };
232 
233 
234 //-----------------------------------------------------------------------------
235 //
236 // CLASS NAME
237 //   AndCombine
238 //
239 // DESCRIPTION
240 //   A handy combiner for extracting bool queries from expressions.
241 //
242 //-----------------------------------------------------------------------------
243 
244 struct AndCombine
245 {
246   PETE_EMPTY_CONSTRUCTORS(AndCombine)
247 };
248 
249 template<class Op>
250 struct Combine2<bool, bool, Op, AndCombine>
251 {
252   typedef bool Type_t;
253   inline static Type_t combine(bool a, bool b, Op, AndCombine) { return (a && b); }
254 };
255 
256 
257 //-----------------------------------------------------------------------------
258 //
259 // CLASS NAME
260 //   OrCombine
261 //
262 // DESCRIPTION
263 //   A handy combiner for extracting bool queries from expressions.
264 //
265 //-----------------------------------------------------------------------------
266 
267 struct OrCombine
268 {
269   PETE_EMPTY_CONSTRUCTORS(OrCombine)
270 };
271 
272 template<class Op>
273 struct Combine2<bool, bool, Op, OrCombine>
274 {
275   typedef bool Type_t;
276   inline static Type_t combine(bool a, bool b, Op, OrCombine) { return (a || b); }
277 };
278 
279 
280 //-----------------------------------------------------------------------------
281 //
282 // CLASS NAME
283 //   NullCombine
284 //
285 // DESCRIPTION
286 //   This combiner doesn't do anything. Used when the combination isn't meant
287 //   return anything since combiners cannot return void.
288 //
289 //-----------------------------------------------------------------------------
290 
291 struct NullCombine
292 {
293   PETE_EMPTY_CONSTRUCTORS(NullCombine)
294 };
295 
296 template<class Op>
297 struct Combine2<int, int, Op, NullCombine>
298 {
299   typedef int Type_t;
300   inline static Type_t combine(int, int, Op, NullCombine) { return 0; }
301 };
302 
303 
304 //-----------------------------------------------------------------------------
305 //
306 // CLASS NAME
307 //   SumCombine
308 //
309 // DESCRIPTION
310 //   This combiner can be used to count things in expressions.
311 //
312 //-----------------------------------------------------------------------------
313 
314 struct SumCombine
315 {
316   PETE_EMPTY_CONSTRUCTORS(SumCombine)
317 };
318 
319 template<class Op>
320 struct Combine2<int, int, Op, SumCombine>
321 {
322   typedef int Type_t;
323   inline static Type_t combine(int a, int b, Op, SumCombine) { return a + b; }
324 };
325 
326 
327 } // namespace qmcplusplus
328 #endif // PETE_PETE_COMBINERS_H
329 
330 // ACL:rcsinfo
331