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_TREENODES_H
30 #define PETE_PETE_TREENODES_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 NAME
43 //   Reference<T>
44 //
45 // DESCRIPTION
46 //   Reference is a special kind of node that contains a reference to an object
47 //   of type T.  It can be converted to a (const T &), and other tree objects
48 //   will perform this conversion before returning their elements.
49 //
50 //-----------------------------------------------------------------------------
51 
52 template<class T>
53 struct Reference
54 {
55   //---------------------------------------------------------------------------
56   // Export the type of thing we're referencing.
57 
58   typedef T Type_t;
59 
60   //---------------------------------------------------------------------------
61   // Reference can be created from a const ref.
62 
ReferenceReference63   inline Reference(const T& reference) : reference_m(reference) {}
64 
65   //---------------------------------------------------------------------------
66   // Copy constructor
67 
ReferenceReference68   inline Reference(const Reference<T>& model) : reference_m(model.reference()) {}
69 
70   //---------------------------------------------------------------------------
71   // Reference can be converted to a const ref
72 
referenceReference73   inline const T& reference() const { return reference_m; }
74 
75   //---------------------------------------------------------------------------
76   // Conversion operators.
77 
78   operator const T&() const { return reference_m; }
79   operator T&() const { return const_cast<T&>(reference_m); }
80 
81   const T& reference_m;
82 };
83 
84 //-----------------------------------------------------------------------------
85 //
86 // CLASS NAME
87 //   DeReference<T>
88 //
89 // DESCRIPTION
90 //   DeReference is a simple traits class that unwraps the Reference struct.
91 //   If T is not a reference object then DeReference gives (const T &).
92 //   If T is a Reference object, then DeReference gives a const ref to the
93 //   wrapped object.
94 //
95 //-----------------------------------------------------------------------------
96 
97 template<class T>
98 struct DeReference
99 {
100   typedef const T& Return_t;
101   typedef T Type_t;
applyDeReference102   static inline Return_t apply(const T& a) { return a; }
103 };
104 
105 template<class T>
106 struct DeReference<Reference<T>>
107 {
108   typedef const T& Return_t;
109   typedef T Type_t;
110   static inline Return_t apply(const Reference<T>& a) { return a.reference(); }
111 };
112 
113 //-----------------------------------------------------------------------------
114 //
115 // CLASS NAME
116 //   UnaryNode<Op, Child>
117 //
118 // DESCRIPTION
119 //   A tree node for representing unary expressions. The node holds a
120 //   child (of type Child), which is the type of the expression sub tree and a
121 //   an operation (of type Op), which is typically the operation applied to
122 //   the sub tree.
123 //
124 //-----------------------------------------------------------------------------
125 
126 template<class Op, class Child>
127 class UnaryNode
128 {
129 public:
130   //---------------------------------------------------------------------------
131   // Accessors making the operation and child available to the outside.
132 
133   inline const Op& operation() const { return op_m; }
134 
135   inline typename DeReference<Child>::Return_t child() const { return DeReference<Child>::apply(child_m); }
136 
137   //---------------------------------------------------------------------------
138   // Constructor using both a operation and the child.
139 
140   inline UnaryNode(const Op& o, const Child& c) : op_m(o), child_m(c) {}
141 
142   //---------------------------------------------------------------------------
143   // Constructor using just the child.
144 
145   inline UnaryNode(const Child& c) : child_m(c) {}
146 
147   //---------------------------------------------------------------------------
148   // Copy constructor.
149 
150   inline UnaryNode(const UnaryNode<Op, Child>& t) : op_m(t.operation()), child_m(t.child()) {}
151 
152   //---------------------------------------------------------------------------
153   // Constructor using a UnaryNode with a different child and/or a different
154   // storage tag. Note: for this to work, a Child must be constructable
155   // from an OtherChild.
156 
157   template<class OtherChild>
158   inline UnaryNode(const UnaryNode<Op, OtherChild>& t) : op_m(t.operation()), child_m(t.child())
159   {}
160 
161   //---------------------------------------------------------------------------
162   // Constructor using a UnaryNode with a different child,
163   // some arbitrary argument, and a different storage tag.
164   // Note: for this to work, a Child must be constructable
165   // from an OtherChild and an Arg.
166 
167   template<class OtherChild, class Arg>
168   inline UnaryNode(const UnaryNode<Op, OtherChild>& t, const Arg& a) : op_m(t.operation()), child_m(t.child(), a)
169   {}
170 
171   //---------------------------------------------------------------------------
172   // Constructor using a BinaryNode with a different Child and
173   // two arbitrary arguments.
174   // Note: for this to work, a Child  must be constructable
175   // from an OtherChild and an Arg1 & Arg2.
176 
177   template<class OtherChild, class Arg1, class Arg2>
178   inline UnaryNode(const UnaryNode<Op, OtherChild>& t, const Arg1& a1, const Arg2& a2)
179       : op_m(t.operation()), child_m(t.child(), a1, a2)
180   {}
181 
182 private:
183   Op op_m;
184   Child child_m;
185 };
186 
187 
188 //-----------------------------------------------------------------------------
189 //
190 // CLASS NAME
191 //   BinaryNode<Op, Left, Right>
192 //
193 // DESCRIPTION
194 //   A tree node for representing binary expressions. The node holds a
195 //   left child (of type Left), which is the type of the LHS expression
196 //   sub tree, a right child (of type Right), which is the type of the RHS
197 //   expression sub tree, and an operation (of type OP), which is applied
198 //   to the two sub trees.
199 //
200 //-----------------------------------------------------------------------------
201 
202 template<class Op, class Left, class Right>
203 class BinaryNode
204 {
205 public:
206   //---------------------------------------------------------------------------
207   // Accessors making the operation and children available to the outside.
208 
209   inline const Op& operation() const { return op_m; }
210 
211   inline typename DeReference<Left>::Return_t left() const { return DeReference<Left>::apply(left_m); }
212 
213   inline typename DeReference<Right>::Return_t right() const { return DeReference<Right>::apply(right_m); }
214 
215   //---------------------------------------------------------------------------
216   // Constructor using both the operation and the two children.
217 
218   inline BinaryNode(const Op& o, const Left& l, const Right& r) : op_m(o), left_m(l), right_m(r) {}
219 
220   //---------------------------------------------------------------------------
221   // Constructor using just the two children.
222 
223   inline BinaryNode(const Left& l, const Right& r) : left_m(l), right_m(r) {}
224 
225   //---------------------------------------------------------------------------
226   // Copy constructor.
227 
228   inline BinaryNode(const BinaryNode<Op, Left, Right>& t) : op_m(t.operation()), left_m(t.left()), right_m(t.right()) {}
229 
230   //---------------------------------------------------------------------------
231   // Constructor using a BinaryNode with a different Left/Right.
232   // Note: for this to work, the Left/Right must be constructable
233   // from an OtherLeft/OtherRight.
234 
235   template<class OtherLeft, class OtherRight>
236   inline BinaryNode(const BinaryNode<Op, OtherLeft, OtherRight>& t)
237       : op_m(t.operation()), left_m(t.left()), right_m(t.right())
238   {}
239 
240   //---------------------------------------------------------------------------
241   // Constructor using a BinaryNode with a different Left/Right and
242   // some arbitrary argument.
243   // Note: for this to work, a Left/Right must be constructable
244   // from an OtherLeft/OtherRight and an Arg.
245 
246   template<class OtherLeft, class OtherRight, class Arg>
247   inline BinaryNode(const BinaryNode<Op, OtherLeft, OtherRight>& t, const Arg& a)
248       : op_m(t.operation()), left_m(t.left(), a), right_m(t.right(), a)
249   {}
250 
251   //---------------------------------------------------------------------------
252   // Constructor using a BinaryNode with a different Left/Right and
253   // two arbitrary arguments.
254   // Note: for this to work, a Left/Right must be constructable
255   // from an OtherLeft/OtherRight and an Arg1 & Arg2.
256 
257   template<class OtherLeft, class OtherRight, class Arg1, class Arg2>
258   inline BinaryNode(const BinaryNode<Op, OtherLeft, OtherRight>& t, const Arg1& a1, const Arg2& a2)
259       : op_m(t.operation()), left_m(t.left(), a1, a2), right_m(t.right(), a1, a2)
260   {}
261 
262 private:
263   //---------------------------------------------------------------------------
264   // The operation and left/right sub expressions stored in this node of the
265   // tree.
266 
267   Op op_m;
268   Left left_m;
269   Right right_m;
270 };
271 
272 
273 //-----------------------------------------------------------------------------
274 //
275 // CLASS NAME
276 //   TrinaryNode<Op, Left, Middle, Right>
277 //
278 // DESCRIPTION
279 //   A tree node for representing trinary expressions. The node holds a
280 //   Left child (of type Left), which is the type of the LHS expression
281 //   sub tree (typically a comparison operation); a Middle child (of type
282 //   Middle), which is the type of the middle (true branch) expression
283 //   sub tree; a Right child (of type Right), which is the type of
284 //   the expression (false branch) sub tree; and an operation (of type Op),
285 //   which is applied to the three sub trees.
286 //
287 //-----------------------------------------------------------------------------
288 
289 template<class Op, class Left, class Middle, class Right>
290 class TrinaryNode
291 {
292 public:
293   //---------------------------------------------------------------------------
294   // Accessors making the operation and children available to the outside.
295 
296   inline const Op& operation() const { return op_m; }
297 
298   inline typename DeReference<Left>::Return_t left() const { return DeReference<Left>::apply(left_m); }
299 
300   inline typename DeReference<Right>::Return_t right() const { return DeReference<Right>::apply(right_m); }
301 
302   inline typename DeReference<Middle>::Return_t middle() const { return DeReference<Middle>::apply(middle_m); }
303 
304   //---------------------------------------------------------------------------
305   // Constructor using the operation and three children.
306 
307   inline TrinaryNode(const Op& o, const Left& l, const Middle& m, const Right& r)
308       : op_m(o), left_m(l), middle_m(m), right_m(r)
309   {}
310 
311   //---------------------------------------------------------------------------
312   // Constructor with just the three children.
313 
314   inline TrinaryNode(const Left& l, const Middle& m, const Right& r) : left_m(l), middle_m(m), right_m(r) {}
315 
316   //---------------------------------------------------------------------------
317   // Copy constructor.
318 
319   inline TrinaryNode(const TrinaryNode<Op, Left, Middle, Right>& t)
320       : op_m(t.operation()), left_m(t.left()), middle_m(t.middle()), right_m(t.right())
321   {}
322 
323   //---------------------------------------------------------------------------
324   // Constructor using a TrinaryNode with a different Left/Middle/Right.
325   // Note: for this to work, the Left/Middle/Right must be constructable
326   // from an OtherLeft/OtherMiddle/OtherRight.
327 
328   template<class OtherLeft, class OtherMiddle, class OtherRight>
329   inline TrinaryNode(const TrinaryNode<Op, OtherLeft, OtherMiddle, OtherRight>& t)
330       : op_m(t.operation()), left_m(t.left()), middle_m(t.middle()), right_m(t.right())
331   {}
332 
333   //---------------------------------------------------------------------------
334   // Constructor using a TrinaryNode with a different Left/Middle/Right and
335   // some arbitrary argument.
336   // Note: for this to work, a Left/Middle/Right must be constructable
337   // from an OtherLeft/OtherMiddle/OtherRight and an Arg.
338 
339   template<class OtherLeft, class OtherMiddle, class OtherRight, class Arg>
340   inline TrinaryNode(const TrinaryNode<Op, OtherLeft, OtherMiddle, OtherRight>& t, const Arg& a)
341       : op_m(t.operation()), left_m(t.left(), a), middle_m(t.middle(), a), right_m(t.right(), a)
342   {}
343 
344   //---------------------------------------------------------------------------
345   // Constructor using a TrinaryNode with a different Left/Middle/Right and
346   // two arbitrary arguments.
347   // Note: for this to work, a Left/Middle/Right must be constructable
348   // from an OtherLeft/OtherMiddle/OtherRight and an Arg1 & Arg2.
349 
350   template<class OtherLeft, class OtherMiddle, class OtherRight, class Arg1, class Arg2>
351   inline TrinaryNode(const TrinaryNode<Op, OtherLeft, OtherMiddle, OtherRight>& t, const Arg1& a1, const Arg2& a2)
352       : op_m(t.operation()), left_m(t.left(), a1, a2), middle_m(t.middle(), a1, a2), right_m(t.right(), a1, a2)
353   {}
354 
355 private:
356   //---------------------------------------------------------------------------
357   // The operation and left, right, and middle sub trees stored at this node.
358 
359   Op op_m;
360   Left left_m;
361   Middle middle_m;
362   Right right_m;
363 };
364 
365 } // namespace qmcplusplus
366 #endif // PETE_PETE_TREENODES_H
367 
368 // ACL:rcsinfo
369