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