OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
PETE.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  ***************************************************************************/
7 
8 
10 //
11 // FILE NAME
12 // PETE.h
13 //
14 // CREATED
15 // July 11, 1997
16 //
17 // DESCRIPTION
18 // PETE: Portable Expression Template Engine.
19 //
20 // This header file defines the objects and operators necessary to use
21 // expression templates for a fairly large class of problems.
22 //
23 // It defines template functions for the standard unary, binary and
24 // trinary operators. Each of them is defined for only certain types to
25 // prevent clashes with global operator+.
26 //
28 
29 #ifndef PETE_H
30 #define PETE_H
31 
32 
33 // include files
34 #include "PETE/TypeComputations.h"
35 #include "Utility/PAssert.h"
36 
37 #include <cstdlib>
38 #ifndef __MWERKS__
39 #include <memory.h>
40 #endif
41 
42 
43 //=========================================================================
44 //
45 // PETE BASE CLASS DEFINITIONS
46 //
47 //=========================================================================
48 
50 //
51 // CLASS NAME
52 // PETE_Expr<W>
53 //
54 // DESCRIPTION
55 // The base class for all objects that will participate in expressions
56 // All this wrapper class needs to do is let you convert back to
57 // the type W.
58 //
59 // The intended use for PETE_Expr is as a base class for
60 // a class you want to be able to enter into PETE expressions.
61 // You construct a PETE aware class by saying:
62 //
63 // class W : public PETE_Expr<W>
64 // {
65 // ...
66 // };
67 //
68 // Then a function that will recognize PETE expressions can do:
69 //
70 // template<class W>
71 // void foo(const PETE_Expr<W>& wrapped_expr)
72 // {
73 // const W& expr = wrapped_expr.PETE_unwrap();
74 // ... do stuff with expr ...
75 // }
76 //
78 
79 template<class WrappedExpr>
80 class PETE_Expr
81 {
82 public:
83  typedef WrappedExpr Wrapped;
84 
85  WrappedExpr& PETE_unwrap()
86  {
87  return static_cast<WrappedExpr&>(*this);
88  }
89  const WrappedExpr& PETE_unwrap() const
90  {
91  return static_cast<const WrappedExpr&>(*this);
92  }
93 
94 };
95 
96 
98 //
99 // CLASS NAME
100 // PETE_Scalar<T>
101 //
102 // DESCRIPTION
103 // A wrapper around a scalar to be used in PETE expressions.
104 //
105 // This is a simple illustration of how one makes a class PETE-aware.
106 // First, notice that PETE_Scalar<T> inherits publically from
107 // PETE_Expr< PETE_Scalar<T> >. In addition, a PETE-aware class must
108 // provide two typedefs:
109 //
110 // PETE_Expr_t: this is the actual class that will be used to
111 // compute an expression. Many simple classes act as both
112 // containers and cursor-like classes, so, often, this
113 // will simply be the class itself. However, classes with
114 // an STL-like iterator should use the iterator as PETE_Expr_t.
115 // PETE_Return_t: this is the type returned by evaluating the
116 // expression. Typically, this is the element-type of a container.
117 // For PETE_Scalar, this is the type of scalar.
118 //
119 // Classes need to supply a member function of the form:
120 //
121 // PETE_Expr_t MakeExpression() const { ... }
122 //
123 // This function should construct and return an appropriate object of
124 // type PETE_Expr_t.
125 //
126 // Finally, PETE really does its work by applying Functors recursively
127 // through the tree that represents an expression. At the leaves of the
128 // tree, these Functors encounter user classes like PETE_Scalar. There
129 // are three Functors that all user classes should support:
130 //
131 // EvalFunctor_0: returns a value for the leaf part of the expression.
132 // This Functor has no arguments so most containers will need to
133 // supply a cursor-like class that returns the current container value.
134 // The cursor is bumped using another Functor, PETE_Increment.
135 // PETE_Increment: moves the cursor to the next element.
136 // PETE_CountElems: returns the number of elements in the container.
137 // Used for testing conformance, for example.
138 //
139 // The actual code for evaluating these Functors for a particular user class
140 // is contained in a global function named 'for_each'. Users classes need
141 // to define a different 'for_each' for each Functor.
142 //
144 
145 template<class T>
146 class PETE_Scalar : public PETE_Expr< PETE_Scalar<T> >
147 {
148 public:
149 
150  // Required PETE typedefs and expression creation function.
151 
153  typedef T PETE_Return_t;
154 
155  PETE_Expr_t MakeExpression() const { return *this; }
156 
157  // Default constructor takes no action.
158 
160 
161  // Constructor from a single value.
162 
163  PETE_Scalar(const T& t) : scalar(t) { }
164 
165 #ifdef IPPL_PURIFY
166  // Copy constructor.
167 
168  PETE_Scalar(const PETE_Scalar<T>& model) : scalar(model.scalar) { }
169 
170  // Assignment operator
171 
173  operator=(const PETE_Scalar<T>& rhs)
174  {
175  scalar = rhs.scalar;
176  return *this;
177  }
178 #endif
179 
180  // Conversion to a type T.
181 
182  operator T() const { return scalar; }
183 
184 private:
185 
187 
188 };
189 
190 //=========================================================================
191 //
192 // BASIC FUNCTORS AND for_each FUNCTIONS FOR PETE_Scalar
193 //
194 //=========================================================================
195 
196 // Evaluation functor, no offsets.
197 
199 {
200 #ifdef IPPL_PURIFY
201  EvalFunctor_0() {}
202  EvalFunctor_0(const EvalFunctor_0 &) {}
203  EvalFunctor_0& operator=(const EvalFunctor_0 &) { return *this; }
204 #endif
205 };
206 
207 // Increment functor
208 
210 {
211  typedef int PETE_Return_t;
212 #ifdef IPPL_PURIFY
213  PETE_Increment() {}
214  PETE_Increment(const PETE_Increment &) {}
215  PETE_Increment& operator=(const PETE_Increment &) { return *this; }
216 #endif
217 };
218 
219 // Element count functor.
220 
222 {
223  typedef int PETE_Return_t;
224 #ifdef IPPL_PURIFY
225  PETE_CountElems() {}
226  PETE_CountElems(const PETE_CountElems &) {}
227  PETE_CountElems& operator=(const PETE_CountElems &) { return *this; }
228 #endif
229 };
230 
231 // Behavior of basic Functors for PETE_Scalar:
232 
233 // Evaluate a scalar.
234 
235 template<class T>
236 inline T
238 {
239 #ifdef IPPL_SGI_PRAGMAS
240 #pragma inline here
241 #endif
242  return T(p);
243 }
244 
245 // Cursor increment, ignored by scalar.
246 
247 template<class T, class C>
248 inline int
250 {
251  return 0;
252 }
253 
254 // Count elements, scalar returns code value -1.
255 
256 template<class T, class C>
257 inline int
259 {
260  return -1;
261 }
262 
263 
264 //=========================================================================
265 //
266 // PETE TREE CLASSES
267 //
268 //=========================================================================
269 
271 //
272 // CLASS NAME
273 // PETE_TUTree<Value_t, Child_t>
274 //
275 // DESCRIPTION
276 // A tree node for representing unary expressions. The node holds a
277 // Child (of type Child_t), which is the type of the expression sub tree,
278 // a Value (of type Value_t), which is typically the operation applied to
279 // the sub tree.
280 //
282 
283 template<class Value_t, class Child_t>
284 struct PETE_TUTree : public PETE_Expr< PETE_TUTree<Value_t, Child_t> >
285 {
286  enum { IsExpr = 1 };
288  typedef typename PETEUnaryReturn<typename Child_t::PETE_Return_t,
290  const PETE_Expr_t& MakeExpression() const { return *this; };
291 
292  // The value and child expression stored in this node of the tree.
293 
294  Value_t Value;
295  Child_t Child;
296 
297  // Default constructor: takes no action.
298 
300 
301  // Constructor using both a value and the child.
302 
303  PETE_TUTree(const Value_t& v, const Child_t& c)
304  : Value(v), Child(c) { }
305 
306  // Constructor using just the child.
307 
308  PETE_TUTree(const Child_t& c)
309  : Child(c) { }
310 };
311 
312 
314 //
315 // CLASS NAME
316 // PETE_TBTree<Value_t, Left_t, Right_t>
317 //
318 // DESCRIPTION
319 // A tree node for representing binary expressions. The node holds a
320 // Left child (of type Left_t), which is the type of the LHS expression
321 // sub tree, a Right child (of type Right_t), which is the type of the RHS
322 // expression sub tree, and a Value (of type Value_t), which is typically
323 // the operation applied to the two sub trees.
324 //
326 
327 template<class Value_t, class Left_t, class Right_t>
328 struct PETE_TBTree :
329  public PETE_Expr< PETE_TBTree<Value_t, Left_t, Right_t> >
330 {
331  enum { IsExpr = 1 };
333  typedef typename PETEBinaryReturn<typename Left_t::PETE_Return_t,
334  typename Right_t::PETE_Return_t, Value_t>::type PETE_Return_t;
335  const PETE_Expr_t& MakeExpression() const { return *this; };
336 
337  // The value and left/right sub expressions stored in this node of the tree.
338 
339  Value_t Value;
340  Left_t Left;
341  Right_t Right;
342 
343  // Default ctor: takes no action.
344 
346 
347  // Constructor using both the value and the two children.
348 
349  PETE_TBTree(const Value_t& v, const Left_t& l, const Right_t& r)
350  : Value(v), Left(l), Right(r) { }
351 
352  // Constructor using just the two children.
353 
354  PETE_TBTree(const Left_t& l, const Right_t& r)
355  : Left(l), Right(r) { }
356 };
357 
358 
360 //
361 // CLASS NAME
362 // PETE_TTTree<Value_t, Left_t, Middle_t, Right_t>
363 //
364 // DESCRIPTION
365 // A tree node for representing trinary expressions. The node holds a
366 // Left child (of type Left_t), which is the type of the LHS expression
367 // sub tree (typically a comparison operation); a Middle child (of type
368 // Middle_t), which is the type of the middle (true branch) expression
369 // sub tree; a Right child (of type Right_t), which is the type of
370 // the expression (false branch) sub tree; and a Value (of type Value_t),
371 // which is typically the operation applied to the three sub trees.
372 //
374 
375 template< class Value_t, class Left_t, class Middle_t, class Right_t >
377  : public PETE_Expr< PETE_TTTree< Value_t, Left_t, Middle_t, Right_t > >
378 {
379 public:
380  enum { IsExpr = 1 };
382  typedef typename PETETrinaryReturn<typename Left_t::PETE_Return_t,
383  typename Middle_t::PETE_Return_t,
384  typename Right_t::PETE_Return_t, Value_t>::type PETE_Return_t;
385  const PETE_Expr_t& MakeExpression() const { return *this; };
386 
387  // The value and left, right, and middle sub trees stored at this node.
388 
389  Value_t Value;
390  Left_t Left;
391  Middle_t Middle;
392  Right_t Right;
393 
394  // Default ctor: takes no action.
395 
397 
398  // Constructor using the value and three children.
399 
400  PETE_TTTree(const Value_t& v, const Left_t& l,
401  const Middle_t& m, const Right_t& r)
402  : Value(v), Left(l), Middle(m), Right(r) { }
403 
404  // Constructor with just the three children.
405 
406  PETE_TTTree(const Left_t& l, const Middle_t& m,const Right_t& r)
407  : Left(l), Middle(m), Right(r) {}
408 };
409 
410 
411 //=========================================================================
412 //
413 // DEFAULT for_each FUNCTIONS INVOLVING PETE TREES
414 //
415 //=========================================================================
416 
417 template<class Op, class T1, class Functor, class Combiner>
418 inline
419 typename Functor::PETE_Return_t
420 for_each(PETE_TUTree<Op,T1>& node, Functor f, Combiner c)
421 {
422 #ifdef IPPL_SGI_PRAGMAS
423 #pragma inline here
424 #endif
425  return c(for_each(node.Child, f, c));
426 }
427 
428 template<class Op, class T1, class T2, class Functor, class Combiner>
429 inline
430 typename Functor::PETE_Return_t
431 for_each(PETE_TBTree<Op,T1,T2>& node, Functor f, Combiner c)
432 {
433 #ifdef IPPL_SGI_PRAGMAS
434 #pragma inline here
435 #endif
436  return c(for_each(node.Left, f, c), for_each(node.Right, f, c));
437 }
438 
439 template<class Op, class T1, class T2, class T3, class Functor, class Combiner>
440 inline
441 typename Functor::PETE_Return_t
442 for_each(PETE_TTTree<Op,T1,T2,T3>& node, Functor f, Combiner c)
443 {
444 #ifdef IPPL_SGI_PRAGMAS
445 #pragma inline here
446 #endif
447  return c(for_each(node.Left, f, c), for_each(node.Middle, f, c) ,
448  for_each(node.Right, f, c));
449 }
450 
451 
452 //
453 // A useful combiner.
454 //
455 template<class T, class Op>
457 {
458 #ifdef IPPL_PURIFY
459  PETE_Combiner() {}
461  PETE_Combiner<T,Op>& operator=(const PETE_Combiner<T,Op> &) { return *this; }
462 #endif
463  T operator()(T x) { return x; }
464  T operator()(T x, T y) { return PETE_apply(Op(),x,y); }
465  T operator()(T x, T y, T z) {return PETE_apply(Op(),x,PETE_apply(Op(),y,z));}
466 };
467 
469 {
470 #ifdef IPPL_PURIFY
471  AssertEquals() {}
472  AssertEquals(const AssertEquals &) {}
473  AssertEquals& operator=(const AssertEquals &) { return *this; }
474 #endif
475  int operator()(int l)
476  {
477  return l;
478  }
479  int operator()(int l, int r)
480  {
481  int ret = l;
482  if ( (l>=0) && (r>=0) ) {
483  PInsist(l==r,"Arguments not equal in AssertEquals()!!");
484  }
485  else {
486  if ( r>=0 ) return ret = r;
487  }
488  return ret;
489  }
490  int operator()(int l, int m, int r)
491  {
492  int ret = l;
493  if ( (l>=0) && (m>=0) && (r>=0) ) {
494  PInsist(m==l && m==r,"Arguments not equal in AssertEquals()!!");
495  }
496  else if ( l>=0 ) {
497  return l;
498  }
499  else if ( m>=0) {
500  return m;
501  }
502  else if ( r>=0) {
503  return r;
504  }
505  return ret;
506  }
507 };
508 
509 //
510 // A combiner for when you don't want to return a value.
511 //
512 
514 {
515 #ifdef IPPL_PURIFY
516  PETE_NullCombiner() {}
518  PETE_NullCombiner& operator=(const PETE_NullCombiner &) { return *this; }
519 #endif
520  int operator()(int) { return 0; }
521  int operator()(int, int) { return 0; }
522  int operator()(int, int, int) { return 0; }
523 };
524 
525 //
526 // Some shorthand for common combiners.
527 //
528 
532 
533 
535 
536 //
537 // for_each functions that recurse through the tree doing evaluation.
538 //
539 
540 template<class Op, class T1, class Functor>
541 inline
543 for_each(PETE_TUTree<Op,T1>& node, Functor f)
544 {
545 #ifdef IPPL_SGI_PRAGMAS
546 #pragma inline here
547 #endif
548  return PETE_apply(node.Value,
549  for_each(node.Child,f));
550 }
551 
552 
553 template<class Op, class T1, class T2, class Functor>
555 {
556  typedef typename PETEBinaryReturn<typename T1::PETE_Return_t,
557  typename T2::PETE_Return_t,Op>::type
559 
560  static inline Return_t
561  apply(PETE_TBTree<Op,T1,T2>& node, Functor f)
562  {
563  return PETE_apply(node.Value,
564  for_each(node.Left,f),
565  for_each(node.Right,f) );
566  }
567 };
568 
569 template<class T>
571 {
572  ConditionalAssign(bool q, const T& v) : cond(q), value(v) {}
573 #ifdef IPPL_PURIFY
575  {
576  cond = model.cond;
577  if (cond)
578  value = model.value;
579  }
580  ConditionalAssign& operator=(const ConditionalAssign<T> &model)
581  {
582  cond = model.cond;
583  if (cond)
584  value = model.value;
585  return *this;
586  }
587 #endif
588  bool cond;
590 };
591 
592 template<class T1, class T2, class Functor>
593 struct struct_for_each<OpWhere,T1,T2,Functor>
594 {
595  typedef typename T2::PETE_Return_t T3;
597 
598  static inline Return_t
600  {
601  if ( for_each(node.Left,f) )
602  return Return_t(true,for_each(node.Right,f));
603  else
604  return Return_t(false,T3());
605  }
606 };
607 
608 template<class Op, class T1, class T2, class Functor>
609 inline
612 {
613 #ifdef IPPL_SGI_PRAGMAS
614 #pragma inline here
615 #endif
617 }
618 
619 /***********************************************************************
620 
621  There are two ways to evaluate the trinary where operator:
622 
623  if (a) { return b; } else { return c; }
624 
625  return a ? b : c;
626 
627  The first is safer since b or c could have a divide by zero
628  or something when it is not supposed to be evaluated, but the
629  second can be much faster since there are more optimization
630  opportunities, particularly strength reduction.
631 
632  Below we have some trait magic for looking at the right hand sides
633  and deciding if the expression is "dangerous" and needs to be done
634  the first way. Otherwise it does it the second way.
635 
636  This uses partial specialization so it is user extensible for
637  special cases.
638 
639 ***********************************************************************/
640 
641 template<int I1, int I2> struct SafeCombine {};
642 template<> struct SafeCombine<0,0> { enum { safe=0 }; };
643 template<> struct SafeCombine<1,0> { enum { safe=0 }; };
644 template<> struct SafeCombine<0,1> { enum { safe=0 }; };
645 template<> struct SafeCombine<1,1> { enum { safe=1 }; };
646 
647 // Expressions are safe unless proven otherwise.
648 template<class Expr> struct SafeExpression { enum { safe=1 }; };
649 
650 // Unary expressions are safe if the sub-tree is safe.
651 template<class Op, class Sub>
653 {
655 };
656 
657 // Binary expressions are safe if both sub-trees are safe.
658 template<class Op, class Left, class Right>
659 struct SafeExpression< PETE_TBTree<Op,Left,Right> >
660 {
662 };
663 
664 // Trinary expressions are safe if the true and false sub-trees are safe.
665 template<class Op, class Left, class Middle, class Right>
666 struct SafeExpression< PETE_TTTree<Op,Left,Middle,Right> >
667 {
669 };
670 
671 // OpDivide is unsafe.
672 template<class Left, class Right>
673 struct SafeExpression< PETE_TBTree<OpDivide,Left,Right> >
674 {
675  enum { safe = 0 };
676 };
677 
678 // Functor class to evaluate the for_each.
679 // If no specialization matches, use PETE_apply.
680 // For OpWhere, this will use ?: through PETE_apply
681 template<int Safe, class T1, class T2, class T3, class Op, class Functor>
683 {
684  static inline
685  typename PETETrinaryReturn<
686  typename T1::PETE_Return_t,
687  typename T2::PETE_Return_t,
688  typename T3::PETE_Return_t,
689  Op>::type
690  apply(PETE_TTTree<Op,T1,T2,T3>& node, Functor f) {
691  return PETE_apply(node.Value,
692  for_each(node.Left,f),
693  for_each(node.Middle,f),
694  for_each(node.Right,f));
695  }
696 };
697 
698 // For an unsafe OpWhere, don't evaluate both args.
699 template<class T1, class T2, class T3, class Functor>
700 struct
702 {
703  static inline
704  typename PETETrinaryReturn<
705  typename T1::PETE_Return_t,
706  typename T2::PETE_Return_t,
707  typename T3::PETE_Return_t,
710  return for_each(node.Left,f) ?
711  for_each(node.Middle,f) : for_each(node.Right,f);
712  }
713 };
714 
715 // The general definition of for_each for trinary.
716 // This just turns around and calls the class function.
717 template<class T1, class T2, class T3, class Functor,class Op>
718 inline
719 typename PETETrinaryReturn<typename T1::PETE_Return_t,
720  typename T2::PETE_Return_t,
721  typename T3::PETE_Return_t,Op>::type
723 {
724  return TrinaryForEach<
726  ,T1,T2,T3,Op,Functor>::apply(node,f);
727 }
728 
729 //=========================================================================
730 //
731 // GENERAL PETE REDUCTION CODE
732 //
733 //=========================================================================
734 
735 #if !defined(PETE_USER_REDUCTION_CODE)
736 
737 #define PETE_USER_REDUCTION_CODE
738 
739 #endif
740 
741 template< class R, class T, class InitOp, class AccOp>
742 inline void
743 Reduction(R& ret, const PETE_Expr<T>& const_expr,
744  InitOp init_op, AccOp acc_op )
745 {
746  // Extract the expression.
747 
748  typename T::PETE_Expr_t expr(const_expr.PETE_unwrap().MakeExpression());
749 
750  // Get the number of elements we will be looping over.
751 
752  int n = for_each(expr, PETE_CountElems(), AssertEquals());
753 
754  // Make sure there is something to do.
755 
756  if (n > 0) {
757 
758  // Get the first value.
759 
760  PETE_apply(init_op, ret, for_each(expr, EvalFunctor_0()));
761 
762  // Loop over all the elements.
763  for (int i = 1; i < n; ++i)
764  {
765  // Increment the cursors.
766 
768 
769  // Accumulate.
770 
771  PETE_apply(acc_op, ret, for_each(expr, EvalFunctor_0()));
772  }
773  }
774 
775  // Allow users to augment the reduction code.
776 
778 }
779 
780 
781 //=========================================================================
782 //
783 // UNARY OPERATIONS
784 //
785 //=========================================================================
786 
787 #define PETE_DefineUnary(Fun,Expr,Op) \
788 template<class T> \
789 inline typename PETEUnaryReturn<T, Op>::type \
790 PETE_apply(Op, const T& a) \
791 { \
792  return Expr; \
793 } \
794 template<class T> \
795 inline PETE_TUTree<Op, typename T::PETE_Expr_t> \
796 Fun(const PETE_Expr<T>& l) \
797 { \
798  return PETE_TUTree<Op, typename T::PETE_Expr_t> \
799  (l.PETE_unwrap().MakeExpression()); \
800 }
801 
803 PETE_DefineUnary(operator+, (+a), OpUnaryPlus)
805 PETE_DefineUnary(operator!, (!a), OpNot)
807 
825 
826 //
827 // Define OpCast specially because it doesn't fit
828 // the pattern that the #define needs.
829 //
830 
831 template<class T1, class T2>
832 inline T1
833 PETE_apply(OpCast<T1>, const T2& a)
834 {
835  return T1(a);
836 }
837 
838 template<class T1, class Expr>
839 inline PETE_TUTree<OpCast<T1>, typename Expr::PETE_Expr_t>
840 pete_cast(const T1&, const PETE_Expr<Expr>& l)
841 {
842  return
843  PETE_TUTree<OpCast<T1>, typename Expr::PETE_Expr_t>
844  (l.PETE_unwrap().MakeExpression());
845 }
846 
847 //=========================================================================
848 //
849 // BINARY OPERATIONS
850 //
851 //=========================================================================
852 
853 #define PETE_DefineBinary(Fun,Expr,Op) \
854 template<class T1, class T2> \
855 inline typename PETEBinaryReturn<T1, T2, Op>::type \
856 PETE_apply(Op, const T1& a, const T2& b) \
857 { \
858  return Expr; \
859 } \
860 template<class T1, class T2> \
861 inline PETE_TBTree<Op, typename T1::PETE_Expr_t, typename T2::PETE_Expr_t> \
862 Fun(const PETE_Expr<T1>& l, const PETE_Expr<T2>& r) \
863 { \
864  typedef PETE_TBTree<Op,typename T1::PETE_Expr_t, \
865  typename T2::PETE_Expr_t> ret; \
866  return ret(l.PETE_unwrap().MakeExpression(), \
867  r.PETE_unwrap().MakeExpression()); \
868 }
869 
870 #define PETE_DefineBinarySynonym(Fun,Op) \
871 template<class T1, class T2> \
872 inline PETE_TBTree<Op, typename T1::PETE_Expr_t, typename T2::PETE_Expr_t> \
873 Fun(const PETE_Expr<T1>& l, const PETE_Expr<T2>& r) \
874 { \
875  typedef PETE_TBTree<Op,typename T1::PETE_Expr_t,typename T2::PETE_Expr_t> \
876  ret; \
877  return ret(l.PETE_unwrap().MakeExpression(), \
878  r.PETE_unwrap().MakeExpression()); \
879 }
880 
881 PETE_DefineBinary(operator+, (a + b), OpAdd)
882 PETE_DefineBinary(operator-, (a - b), OpSubtract)
883 PETE_DefineBinary(operator*, (a * b), OpMultipply)
884 PETE_DefineBinary(operator/, (a / b), OpDivide)
885 PETE_DefineBinary(operator%, (a % b), OpMod)
886 PETE_DefineBinary(operator<, (a < b), OpLT)
887 PETE_DefineBinary(operator<=, (a <= b), OpLE)
888 PETE_DefineBinary(operator>, (a > b), OpGT)
889 PETE_DefineBinary(operator>=, (a >= b), OpGE)
890 PETE_DefineBinary(operator==, (a == b), OpEQ)
891 PETE_DefineBinary(operator!=, (a != b), OpNE)
892 PETE_DefineBinary(operator&&, (a && b), OpAnd)
893 PETE_DefineBinary(operator||, (a || b), OpOr)
894 PETE_DefineBinary(operator&, (a & b), OpBitwiseAnd)
895 PETE_DefineBinary(operator|, (a | b), OpBitwiseOr)
896 PETE_DefineBinary(operator^, (a ^ b), OpBitwiseXor)
897  //PETE_DefineBinary(operator<<, (a << b), OpLeftShift)
898  //PETE_DefineBinary(operator>>, (a >> b), OpRightShift)
899 
905 
906 #define PETE_DefineBinaryWithScalars(Fun,Op,Sca) \
907 template<class T> \
908 inline PETE_TBTree<Op, PETE_Scalar<Sca>, typename T::PETE_Expr_t> \
909 Fun(const Sca l, const PETE_Expr<T>& r) \
910 { \
911  typedef PETE_TBTree<Op, PETE_Scalar<Sca>, typename T::PETE_Expr_t> ret; \
912  return ret(PETE_Scalar<Sca>(l), r.PETE_unwrap().MakeExpression()); \
913 } \
914 template<class T> \
915 inline PETE_TBTree<Op, typename T::PETE_Expr_t, PETE_Scalar<Sca> > \
916 Fun(const PETE_Expr<T>& l, const Sca r) \
917 { \
918  typedef PETE_TBTree<Op, typename T::PETE_Expr_t, PETE_Scalar<Sca> > ret; \
919  return ret(l.PETE_unwrap().MakeExpression(), PETE_Scalar<Sca>(r)); \
920 }
921 
922 
923 //=========================================================================
924 //
925 // TRINARY OPERATORS
926 //
927 //=========================================================================
928 
929 #define PETE_DefineTrinary(Fun,Expr,Op) \
930 template<class T1, class T2, class T3> \
931 inline typename PETETrinaryReturn<T1,T2,T3,Op>::type \
932 PETE_apply(Op, const T1& a, const T2& b, const T3& c) \
933 { \
934  return Expr; \
935 } \
936 template<class Cond_t, class True_t, class False_t> \
937 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, \
938  typename True_t::PETE_Expr_t, typename False_t::PETE_Expr_t> \
939 Fun(const PETE_Expr<Cond_t>& c, const PETE_Expr<True_t>& t, \
940  const PETE_Expr<False_t>& f) \
941 { \
942  typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, \
943  typename True_t::PETE_Expr_t, typename False_t::PETE_Expr_t> ret; \
944  return ret(c.PETE_unwrap().MakeExpression(), \
945  t.PETE_unwrap().MakeExpression(), \
946  f.PETE_unwrap().MakeExpression()); \
947 }
948 
949 template<class T1, class T2, class T3>
951 PETE_apply(OpWhere, const T1& a, const T2& b, const T3& c)
952 {
953  return a ? b : c;
954 }
955 
956 template<class Cond_t, class True_t, class False_t>
957 inline PETE_TTTree<OpWhere, typename Cond_t::PETE_Expr_t,
958  typename True_t::PETE_Expr_t,
959  typename False_t::PETE_Expr_t>
961  const PETE_Expr<False_t>& f)
962 {
963  typedef PETE_TTTree<OpWhere, typename Cond_t::PETE_Expr_t,
964  typename True_t::PETE_Expr_t,
965  typename False_t::PETE_Expr_t> ret;
966  return ret(c.PETE_unwrap().MakeExpression(),
967  t.PETE_unwrap().MakeExpression(),
968  f.PETE_unwrap().MakeExpression());
969 }
970 
971 
972 #define PETE_DefineTrinaryWithScalars(Fun, Op, Sca) \
973 template<class Cond_t, class True_t> \
974 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, \
975  typename True_t::PETE_Expr_t, PETE_Scalar<Sca> > \
976 Fun(const PETE_Expr<Cond_t>& c, const PETE_Expr<True_t>& t,Sca f) \
977 { \
978  typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, \
979  typename True_t::PETE_Expr_t, PETE_Scalar<Sca> > ret; \
980  return ret(c.PETE_unwrap().MakeExpression(), \
981  t.PETE_unwrap().MakeExpression(), PETE_Scalar<Sca>(f)); \
982 } \
983 template<class Cond_t, class False_t> \
984 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, PETE_Scalar<Sca>, \
985  typename False_t::PETE_Expr_t > \
986 Fun(const PETE_Expr<Cond_t>& c, Sca t, const PETE_Expr<False_t>& f) \
987 { \
988  typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, PETE_Scalar<Sca>, \
989  typename False_t::PETE_Expr_t > ret; \
990  return ret(c.PETE_unwrap().MakeExpression(), \
991  PETE_Scalar<Sca>(t), f.PETE_unwrap().MakeExpression()); \
992 } \
993 template<class Cond_t> \
994 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, PETE_Scalar<Sca>, \
995  PETE_Scalar<Sca> > \
996 Fun(const PETE_Expr<Cond_t>& c, Sca t, Sca f) \
997 { \
998  typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, PETE_Scalar<Sca>, \
999  PETE_Scalar<Sca> > ret; \
1000  return ret(c.PETE_unwrap().MakeExpression(), \
1001  PETE_Scalar<Sca>(t), PETE_Scalar<Sca>(f)); \
1002 }
1003 
1004 
1005 //=========================================================================
1006 //
1007 // Two argument where
1008 //
1009 // The conventional where operator has three arguments:
1010 // where(conditional, true_expr, false_expr)
1011 // It acts much like the ?: operator in expressions.
1012 //
1013 // A common usage of that structure is
1014 // A = where(conditional,true_expr,A);
1015 // to do something only in the locations where the conditional is true.
1016 // This is inefficient.
1017 //
1018 // The two argument where supports the following:
1019 // A = where(conditional,true_expr);
1020 // and means the same thing as the three argument version above.
1021 //
1022 // This form of where cannot be used in expressions in which the where
1023 // is not the whole right hand side of the expression.
1024 //
1025 //======================================================================
1026 //
1027 // EXPLANATION
1028 //
1029 // The three argument where operator above produces code something
1030 // like this in the inner loop:
1031 //
1032 // for (i=...)
1033 // a(i) = conditional(i) ? true_expr(i) : false_expr(i);
1034 //
1035 // The two argument where has to produce something like:
1036 //
1037 // for (i=...)
1038 // if ( conditional(i) )
1039 // a(i) = true_expr(i);
1040 //
1041 // Two things are being made conditional here: evaluating true_expr
1042 // and assigning it to a.
1043 //
1044 // In order to do that inside of expression templates, the following
1045 // things need to happen when evaluating an expression:
1046 //
1047 // 1. Evaluating the binary OpWhere expression returns a
1048 // ConditionalAssign<T> with two components: A boolean for whether
1049 // the conditional was true, and the result of evaluating the
1050 // expression of type T.
1051 //
1052 // 2. The expression only gets evaluated if the conditional is true.
1053 // If it is not true, then the ConditionalAssign<T> uses a default ctor
1054 // to leave the T undefined.
1055 //
1056 // 3. The assigment operator from the ConditionalAssign<T> to a type
1057 // T only actually does the assignment if the bool is true.
1058 //
1059 //=========================================================================
1060 
1062 
1063 //=========================================================================
1064 //
1065 // SCALARS
1066 //
1067 //=========================================================================
1068 
1069 #define PETE_DefineScalar(Sca) \
1070 PETE_DefineBinaryWithScalars(operator+, OpAdd, Sca) \
1071 PETE_DefineBinaryWithScalars(operator-, OpSubtract, Sca) \
1072 PETE_DefineBinaryWithScalars(operator*, OpMultipply, Sca) \
1073 PETE_DefineBinaryWithScalars(operator/, OpDivide, Sca) \
1074 PETE_DefineBinaryWithScalars(operator%, OpMod, Sca) \
1075 PETE_DefineBinaryWithScalars(operator<, OpLT, Sca) \
1076 PETE_DefineBinaryWithScalars(operator<=, OpLE, Sca) \
1077 PETE_DefineBinaryWithScalars(operator>, OpGT, Sca) \
1078 PETE_DefineBinaryWithScalars(operator>=, OpGE, Sca) \
1079 PETE_DefineBinaryWithScalars(operator==, OpEQ, Sca) \
1080 PETE_DefineBinaryWithScalars(operator!=, OpNE, Sca) \
1081 PETE_DefineBinaryWithScalars(operator&&, OpAnd, Sca) \
1082 PETE_DefineBinaryWithScalars(operator||, OpOr, Sca) \
1083 PETE_DefineBinaryWithScalars(operator&, OpBitwiseAnd, Sca) \
1084 PETE_DefineBinaryWithScalars(operator|, OpBitwiseOr, Sca) \
1085 PETE_DefineBinaryWithScalars(operator^, OpBitwiseXor, Sca) \
1086 PETE_DefineBinaryWithScalars(where, OpWhere, Sca) \
1087 PETE_DefineBinaryWithScalars(copysign, FnCopysign, Sca) \
1088 PETE_DefineBinaryWithScalars(ldexp, FnLdexp, Sca) \
1089 PETE_DefineBinaryWithScalars(pow, FnPow, Sca) \
1090 PETE_DefineBinaryWithScalars(fmod, FnFmod, Sca) \
1091 PETE_DefineBinaryWithScalars(atan2, FnArcTan2, Sca) \
1092 PETE_DefineTrinaryWithScalars(where, OpWhere, Sca)
1093 
1094 /*
1095 PETE_DefineBinaryWithScalars(operator<<, OpLeftShift, Sca) \
1096 PETE_DefineBinaryWithScalars(operator>>, OpRightShift, Sca) \
1097 */
1098 
1104 
1105 
1106 //=========================================================================
1107 //
1108 // ASSIGNMENT OPERATIONS
1109 //
1110 //=========================================================================
1111 
1112 template<class Op, class T1, class T2> struct PETE_StructApply {};
1113 
1114 #define PETE_DefineAssign(Expr,Cond,Op) \
1115 template<class T1, class T2> \
1116 struct PETE_StructApply<Op,T1,T2> \
1117 { \
1118  static void apply(T1& a,const T2& b) { Expr; } \
1119 }; \
1120  \
1121 template<class T1, class T2> \
1122 struct PETE_StructApply<Op,T1,ConditionalAssign<T2> > \
1123 { \
1124  static void apply(T1& a, const ConditionalAssign<T2>& b) \
1125  { \
1126  if ( b.cond ) \
1127  Cond; \
1128  } \
1129 }; \
1130  \
1131 template<class T1, class T2> \
1132 inline void \
1133 PETE_apply(Op, T1 &a, const T2& b) \
1134 { \
1135  PETE_StructApply<Op,T1,T2>::apply(a,b); \
1136 }
1137 
1138 PETE_DefineAssign((a = b) ,(a = b.value) , OpAssign)
1139 PETE_DefineAssign((a += b) ,(a += b.value) , OpAddAssign)
1140 PETE_DefineAssign((a -= b) ,(a -= b.value) , OpSubtractAssign)
1141 PETE_DefineAssign((a *= b) ,(a *= b.value) , OpMultipplyAssign)
1142 PETE_DefineAssign((a /= b) ,(a /= b.value) , OpDivideAssign)
1143 PETE_DefineAssign((a %= b) ,(a %= b.value) , OpModAssign)
1144 PETE_DefineAssign((a |= b) ,(a |= b.value) , OpBitwiseOrAssign)
1145 PETE_DefineAssign((a &= b) ,(a &= b.value) , OpBitwiseAndAssign)
1146 PETE_DefineAssign((a ^= b) ,(a ^= b.value) , OpBitwiseXorAssign)
1147 PETE_DefineAssign((a <<= b),(a <<= b.value), OpLeftShiftAssign)
1148 PETE_DefineAssign((a >>= b),(a >>= b.value), OpRightShiftAssign)
1149 
1150 
1151 //=========================================================================
1152 //
1153 // FUNCTOR NAME
1154 // Expressionize
1155 //
1156 // DESCRIPTION
1157 // Sometimes the result of MakeExpression on a user type isn't itself an
1158 // expression. That is perfectly reasonable, but sometimes you need to
1159 // be make it one. This just looks for that case and wraps it in an
1160 // identity operation if it is not already an expression.
1161 //
1162 //=========================================================================
1163 
1164 //
1165 // If it is a general expression, wrap it.
1166 //
1167 template<class T>
1169 {
1171  static inline type
1172  apply(const T& t) { return type(t); }
1173 };
1174 
1175 //
1176 // If it is a PETE_Expr, return it as is.
1177 //
1178 template<class T>
1180 {
1182  static inline const type&
1183  apply(const PETE_Expr<T>& t) { return t; }
1184 };
1185 
1186 //=========================================================================
1187 //
1188 // REDUCTIONS
1189 //
1190 //=========================================================================
1191 
1192 #ifdef __MWERKS__
1193 // Workaround for CodeWarrior 4 bug
1194 template<class T>
1195 struct Sum {
1196  typedef typename T::PETE_Expr_t::PETE_Return_t type_t;
1197  static inline type_t apply(const PETE_Expr<T>& expr) {
1198  type_t val ;
1199  Reduction(val, Expressionize<typename T::PETE_Expr_t>::apply( expr.PETE_unwrap().MakeExpression() ),
1200  OpAssign(), OpAddAssign());
1201  return val;
1202  }
1203 };
1204 
1205 template<class T>
1206 inline typename Sum<T>::type_t
1207 sum(const PETE_Expr<T>& expr) {
1208  return Sum<T>::apply(expr);
1209 }
1210 #else
1211 template<class T>
1212 inline typename T::PETE_Expr_t::PETE_Return_t
1213 sum(const PETE_Expr<T>& expr)
1214 {
1215  typename T::PETE_Expr_t::PETE_Return_t val ;
1216  Reduction(val, Expressionize<typename T::PETE_Expr_t>::apply( expr.PETE_unwrap().MakeExpression() ),
1217  OpAssign(), OpAddAssign());
1218  return val;
1219 }
1220 #endif // __MWERKS__
1221 
1222 #ifdef __MWERKS__
1223 // Workaround for CodeWarrior 4 bug
1224 template<class T>
1225 struct Prod {
1226  typedef typename T::PETE_Expr_t::PETE_Return_t type_t;
1227  static inline type_t apply(const PETE_Expr<T>& expr) {
1228  type_t val ;
1231  return val;
1232  }
1233 };
1234 
1235 template<class T>
1236 inline typename Prod<T>::type_t
1237 prod(const PETE_Expr<T>& expr) {
1238  return Prod<T>::apply(expr);
1239 }
1240 #else
1241 template<class T>
1242 inline typename T::PETE_Expr_t::PETE_Return_t
1243 prod(const PETE_Expr<T>& expr)
1244 {
1245  typename T::PETE_Expr_t::PETE_Return_t val ;
1248  return val;
1249 }
1250 #endif // __MWERKS__
1251 
1253 //
1254 // Some macros to make it easier to define new operators.
1255 //
1257 
1258 #define UNARY_FUNCTION(RET,FUNC,ARG) \
1259 struct FnUnary_ ## FUNC { \
1260  enum { tag = PETE_UnaryPassThruTag }; \
1261 }; \
1262 PETE_DefineUnary(FUNC,FUNC(a),FnUnary_ ## FUNC) \
1263 template <> \
1264 struct PETEUnaryReturn<ARG, FnUnary_ ## FUNC> { \
1265  typedef RET type; \
1266 };
1267 
1268 #define BINARY_FUNCTION(RET,FUNC,ARG1,ARG2) \
1269 struct FnBinary_ ## FUNC { \
1270  enum { tag = PETE_BinaryPromoteTag }; \
1271 }; \
1272 PETE_DefineBinary(FUNC,(FUNC(a,b)),FnBinary_ ## FUNC) \
1273 template<> \
1274 struct PETEBinaryReturn<ARG1,ARG2,FnBinary_ ## FUNC> { \
1275  typedef RET type; \
1276 };
1277 
1278 
1280 //
1281 // END OF FILE
1282 //
1284 
1285 #endif // PETE_H
1286 
T::PETE_Return_t Reduction(const PETE_Expr< T > &const_expr, CompOp comp_op, AccOp acc_op, NDIndex< D > &loc)
#define PETE_DefineUnary(Fun, Expr, Op)
Definition: PETE.h:787
static type apply(const T &t)
Definition: PETE.h:1172
void PETE_apply(const OpPeriodic< T > &e, T &a, const T &b)
Definition: BCond.hpp:373
PETE_TUTree()
Definition: PETE.h:299
int PETE_Return_t
Definition: PETE.h:223
Definition: PETE.h:80
#define PETE_DefineAssign(Expr, Cond, Op)
Definition: PETE.h:1114
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
Definition: PETE.h:808
T operator()(T x, T y)
Definition: PETE.h:464
#define PETE_DefineScalar(Sca)
Definition: PETE.h:1069
Definition: rbendmap.h:8
static Return_t apply(PETE_TBTree< OpWhere, T1, T2 > &node, Functor f)
Definition: PETE.h:599
static Return_t apply(PETE_TBTree< Op, T1, T2 > &node, Functor f)
Definition: PETE.h:561
FTps< T, N > erf(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Error function.
Definition: FTpsMath.h:385
The VALUE command.
Definition: Value.h:28
static const type & apply(const PETE_Expr< T > &t)
Definition: PETE.h:1183
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Definition: PETE.h:815
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
int operator()(int, int)
Definition: PETE.h:521
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:811
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
const PETE_Expr_t & MakeExpression() const
Definition: PETE.h:290
PETEBinaryReturn< typename Left_t::PETE_Return_t, typename Right_t::PETE_Return_t, Value_t >::type PETE_Return_t
Definition: PETE.h:334
WrappedExpr & PETE_unwrap()
Definition: PETE.h:85
Value_t Value
Definition: PETE.h:335
PETE_ComputeUnaryType< PETE_Type2Index< T >::val, Op::tag >::type type
Tps< T > tan(const Tps< T > &x)
Tangent.
Definition: TpsMath.h:147
PETE_TTTree()
Definition: PETE.h:396
int PETE_Return_t
Definition: PETE.h:211
int operator()(int, int, int)
Definition: PETE.h:522
PETE_TUTree(const Child_t &c)
Definition: PETE.h:308
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1213
PETE_TUTree< OpCast< T1 >, typename Expr::PETE_Expr_t > pete_cast(const T1 &, const PETE_Expr< Expr > &l)
Definition: PETE.h:840
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
static PETETrinaryReturn< typename T1::PETE_Return_t, typename T2::PETE_Return_t, typename T3::PETE_Return_t, OpWhere >::type apply(PETE_TTTree< OpWhere, T1, T2, T3 > &node, Functor f)
Definition: PETE.h:709
double Sub(double a, double b)
PETE_TBTree()
Definition: PETE.h:345
PETEUnaryReturn< typename Child_t::PETE_Return_t, Value_t >::type PETE_Return_t
Definition: PETE.h:289
T scalar
Definition: PETE.h:186
int operator()(int l)
Definition: PETE.h:475
PETE_TTTree(const Left_t &l, const Middle_t &m, const Right_t &r)
Definition: PETE.h:406
ConditionalAssign< T3 > Return_t
Definition: PETE.h:596
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
Definition: TpsMath.h:222
PETE_Scalar(const T &t)
Definition: PETE.h:163
const PETE_Expr_t & MakeExpression() const
Definition: PETE.h:335
PETE_TTTree< Value_t, Left_t, Middle_t, Right_t > PETE_Expr_t
Definition: PETE.h:381
Value_t Value
Definition: PETE.h:290
Left_t Left
Definition: PETE.h:340
const PETE_Expr_t & MakeExpression() const
Definition: PETE.h:385
static PETETrinaryReturn< typename T1::PETE_Return_t, typename T2::PETE_Return_t, typename T3::PETE_Return_t, Op >::type apply(PETE_TTTree< Op, T1, T2, T3 > &node, Functor f)
Definition: PETE.h:690
Child_t Child
Definition: PETE.h:295
PETE_TUTree< OpIdentity, T > type
Definition: PETE.h:1170
const WrappedExpr & PETE_unwrap() const
Definition: PETE.h:89
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:810
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
Right_t Right
Definition: PETE.h:392
Left_t Left
Definition: PETE.h:390
int operator()(int)
Definition: PETE.h:520
PETE_ComputeBinaryType< PETE_Type2Index< T2 >::val, PETE_Type2Index< T3 >::val, Op::tag >::type type
PETE_TTTree< OpWhere, typename Cond_t::PETE_Expr_t, typename True_t::PETE_Expr_t, PETE_Scalar< Vektor< T, Dim > > > where(const PETE_Expr< Cond_t > &c, const PETE_Expr< True_t > &t, const Vektor< T, Dim > &f)
T operator()(T x)
Definition: PETE.h:463
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Middle_t Middle
Definition: PETE.h:391
PETE_TBTree< FnLdexp, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > ldexp(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_Scalar< T > PETE_Expr_t
Definition: PETE.h:152
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
int operator()(int l, int m, int r)
Definition: PETE.h:490
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TUTree< Value_t, Child_t > PETE_Expr_t
Definition: PETE.h:287
PETE_Scalar()
Definition: PETE.h:159
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
#define PETE_DefineBinarySynonym(Fun, Op)
Definition: PETE.h:870
WrappedExpr Wrapped
Definition: PETE.h:83
ConditionalAssign(bool q, const T &v)
Definition: PETE.h:572
PETE_Combiner< bool, OpAnd > PETE_AndCombiner
Definition: PETE.h:529
T operator()(T x, T y, T z)
Definition: PETE.h:465
#define PETE_USER_REDUCTION_CODE
Definition: PETE.h:737
T PETE_Return_t
Definition: PETE.h:153
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1243
PETE_Combiner< bool, OpOr > PETE_OrCombiner
Definition: PETE.h:530
PETE_TBTree< Value_t, Left_t, Right_t > PETE_Expr_t
Definition: PETE.h:332
PETE_Expr_t MakeExpression() const
Definition: PETE.h:155
#define PETE_DefineBinary(Fun, Expr, Op)
Definition: PETE.h:853
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
Definition: PETE.h:809
PETE_TTTree(const Value_t &v, const Left_t &l, const Middle_t &m, const Right_t &r)
Definition: PETE.h:400
PETEBinaryReturn< typename T1::PETE_Return_t, typename T2::PETE_Return_t, Op >::type Return_t
Definition: PETE.h:558
#define PInsist(c, m)
Definition: PAssert.h:135
Value_t Value
Definition: PETE.h:385
Right_t Right
Definition: PETE.h:341
PETE_TUTree(const Value_t &v, const Child_t &c)
Definition: PETE.h:303
bool for_each(const BareFieldIterator< T, D > &p, SameFieldID s, C)
Definition: AssignDefs.h:30
int operator()(int l, int r)
Definition: PETE.h:479
PETE_TBTree(const Value_t &v, const Left_t &l, const Right_t &r)
Definition: PETE.h:349
Tps< T > tanh(const Tps< T > &x)
Hyperbolic tangent.
Definition: TpsMath.h:240
PETE_TUTree< OpIdentity, typename T::PETE_Expr_t > PETE_identity(const PETE_Expr< T > &l)
Definition: PETE.h:806
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Definition: TpsMath.h:204
PETE_TBTree(const Left_t &l, const Right_t &r)
Definition: PETE.h:354
PETE_TUTree< FnLog10, typename T::PETE_Expr_t > log10(const PETE_Expr< T > &l)
Definition: PETE.h:818
PETETrinaryReturn< typename Left_t::PETE_Return_t, typename Middle_t::PETE_Return_t, typename Right_t::PETE_Return_t, Value_t >::type PETE_Return_t
Definition: PETE.h:384
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:816
PETE_Combiner< int, OpAdd > PETE_SumCombiner
Definition: PETE.h:531