src/PETE/IpplExpressions.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 
00013 //
00014 // FILE NAME
00015 //    IpplExpressions.h
00016 //
00017 // CREATED
00018 //    July 11, 1997
00019 //
00020 // DESCRIPTION
00021 //    This header file defines custom objects and operators necessary to use
00022 //    expression templates in IPPL.
00023 //
00025 
00026 #ifndef IPPL_EXPRESSIONS_H
00027 #define IPPL_EXPRESSIONS_H
00028 
00029 
00030 // We need to construct a custom version of Reduction. We must define
00031 // this macro before including PETE.h.
00032 #define PETE_USER_REDUCTION_CODE                                            \
00033   R global_ret;                                                             \
00034   reduce_masked(ret, global_ret, acc_op, 0 < n );                           \
00035   ret = global_ret;
00036 
00037 // include files
00038 #include "Message/Message.h"
00039 #include "PETE/IpplTypeComputations.h"
00040 #include "PETE/PETE.h"
00041 
00042 
00043 //=========================================================================
00044 //
00045 // UNARY OPERATIONS
00046 // 
00047 //=========================================================================
00048 
00049 // Abs is handled rather strangely. There appears to be two versions
00050 // that do the same thing: abs and Abs.
00051 
00052 PETE_DefineUnary(Abs, (0 < a ? a : -a), FnAbs)
00053 
00054 inline double
00055 PETE_apply(FnAbs, dcomplex a)
00056 {
00057   return abs(a);
00058 }
00059 
00060 template<class T>
00061 inline PETE_TUTree<FnAbs, typename T::PETE_Expr_t>
00062 abs(const PETE_Expr<T>& l)
00063 {
00064   return PETE_TUTree<FnAbs, typename T::PETE_Expr_t>
00065     (l.PETE_unwrap().MakeExpression());
00066 }
00067 
00068 PETE_DefineUnary(conj, (conj(a)), FnConj)
00069 PETE_DefineUnary(arg, (arg(a)), FnArg)
00070 PETE_DefineUnary(norm, (norm(a)), FnNorm)
00071 PETE_DefineUnary(real, (real(a)), FnReal)
00072 PETE_DefineUnary(imag, (imag(a)), FnImag)
00073 PETE_DefineUnary(sign, (sign(a)), FnSign)
00074 PETE_DefineUnary(trace, (trace(a)), FnTrace)
00075 PETE_DefineUnary(transpose, (transpose(a)), FnTranspose)
00076 PETE_DefineUnary(det, (det(a)), FnDet)
00077 PETE_DefineUnary(cofactors, (cofactors(a)), FnCofactors)
00078 
00079 
00080 //=========================================================================
00081 //
00082 // BINARY OPERATIONS
00083 //
00084 //=========================================================================
00085 
00086 // define min/max for built-in scalar types
00087 #define PETE_DefineScalarMinMax(Sca)                                      \
00088 inline Sca                                                                \
00089 Min(const Sca& a, const Sca& b)                                           \
00090 {                                                                         \
00091   return (a<b ? a : b);                                                   \
00092 }                                                                         \
00093 inline Sca                                                                \
00094 Max(const Sca& a, const Sca& b)                                           \
00095 {                                                                         \
00096   return (b<a ? a : b);                                                   \
00097 }
00098 
00099 PETE_DefineScalarMinMax(short)
00100 PETE_DefineScalarMinMax(int)
00101 PETE_DefineScalarMinMax(long)
00102 PETE_DefineScalarMinMax(float)
00103 PETE_DefineScalarMinMax(double)
00104 
00105 PETE_DefineBinary(Min, (Min(a,b)), FnMin)
00106 PETE_DefineBinary(Max, (Max(a,b)), FnMax)
00107 
00108 PETE_DefineBinary(dot, (dot(a,b)), FnDot)
00109 PETE_DefineBinary(dotdot, (dotdot(a,b)), FnDotDot)
00110 PETE_DefineBinary(outerProduct, (outerProduct(a,b)), FnOuterProduct)
00111 PETE_DefineBinary(cross, (cross(a,b)), FnCross)
00112 
00113 PETE_DefineBinarySynonym(lt, OpLT)
00114 PETE_DefineBinarySynonym(gt, OpGT)
00115 PETE_DefineBinarySynonym(le, OpLE)
00116 PETE_DefineBinarySynonym(ge, OpGE)
00117 PETE_DefineBinarySynonym(eq, OpEQ)
00118 PETE_DefineBinarySynonym(ne, OpNE)
00119 
00120 //tjw: make sure kosher to have "cross" down there (added in)
00121 #define PETE_DefineIPPLScalar(Sca)                                         \
00122 PETE_DefineBinaryWithScalars(Min, FnMin, Sca)                               \
00123 PETE_DefineBinaryWithScalars(Max, FnMax, Sca)                               \
00124 PETE_DefineBinaryWithScalars(dot, FnDot, Sca)                               \
00125 PETE_DefineBinaryWithScalars(dotdot, FnDotDot, Sca)                         \
00126 PETE_DefineBinaryWithScalars(outerProduct, FnOuterProduct, Sca)             \
00127 PETE_DefineBinaryWithScalars(cross, FnDot, Sca)                             \
00128 PETE_DefineBinaryWithScalars(lt, OpLT, Sca)                                 \
00129 PETE_DefineBinaryWithScalars(le, OpLE, Sca)                                 \
00130 PETE_DefineBinaryWithScalars(gt, OpGT, Sca)                                 \
00131 PETE_DefineBinaryWithScalars(ge, OpGE, Sca)                                 \
00132 PETE_DefineBinaryWithScalars(eq, OpEQ, Sca)                                 \
00133 PETE_DefineBinaryWithScalars(ne, OpNE, Sca)
00134 
00135 PETE_DefineIPPLScalar(short)
00136 PETE_DefineIPPLScalar(int)
00137 PETE_DefineIPPLScalar(long)
00138 PETE_DefineIPPLScalar(float)
00139 PETE_DefineIPPLScalar(double)
00140 
00141 PETE_DefineScalar(dcomplex)
00142 PETE_DefineBinaryWithScalars(eq, OpEQ, dcomplex)
00143 PETE_DefineBinaryWithScalars(ne, OpNE, dcomplex)
00144 
00145 #undef PETE_DefineIPPLScalar
00146 
00147 // Now we need to provide special cases for Vektors, SymTenzors, and Tenzors
00148 // so we can remove PETE_Expr base class.
00149 
00150 #define PETE_DefineBinaryWithVSTScalars(Fun,Op,Sca)                         \
00151 template<class T1, unsigned Dim, class T2>                                  \
00152 inline PETE_TBTree<Op, PETE_Scalar< Sca<T1, Dim> >,                         \
00153   typename T2::PETE_Expr_t>                                                 \
00154 Fun(const Sca<T1, Dim> &l, const PETE_Expr<T2>& r)                          \
00155 {                                                                           \
00156   typedef PETE_TBTree<Op, PETE_Scalar< Sca<T1, Dim> >,                      \
00157     typename T2::PETE_Expr_t> ret;                                          \
00158   return ret(PETE_Scalar< Sca<T1, Dim> >(l),                                \
00159     r.PETE_unwrap().MakeExpression());                                      \
00160 }                                                                           \
00161 template<class T1, class T2, unsigned Dim>                                  \
00162 inline PETE_TBTree<Op, typename T1::PETE_Expr_t,                            \
00163   PETE_Scalar< Sca<T2, Dim> > >                                             \
00164 Fun(const PETE_Expr<T1>& l, const Sca<T2, Dim> &r)                          \
00165 {                                                                           \
00166   typedef PETE_TBTree<Op, typename T1::PETE_Expr_t,                         \
00167     PETE_Scalar< Sca<T2, Dim> > > ret;                                      \
00168   return ret(l.PETE_unwrap().MakeExpression(),                              \
00169     PETE_Scalar< Sca<T2, Dim> >(r));                                        \
00170 }
00171 
00172 #define PETE_DefineTrinaryWithVSTScalars(Fun, Op, Sca)                      \
00173 template<class Cond_t, class True_t, class T, unsigned Dim>                 \
00174 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t,                        \
00175   typename True_t::PETE_Expr_t, PETE_Scalar< Sca<T, Dim> > >                \
00176 Fun(const PETE_Expr<Cond_t>& c, const PETE_Expr<True_t>& t,                 \
00177   const Sca<T, Dim> &f)                                                     \
00178 {                                                                           \
00179   typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t,                     \
00180     typename True_t::PETE_Expr_t, PETE_Scalar< Sca<T, Dim> > > ret;         \
00181   return ret(c.PETE_unwrap().MakeExpression(),                              \
00182     t.PETE_unwrap().MakeExpression(), PETE_Scalar< Sca<T, Dim> >(f));       \
00183 }                                                                           \
00184 template<class Cond_t, class T, unsigned Dim, class False_t>                \
00185 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t,                        \
00186   PETE_Scalar< Sca<T, Dim> >, typename False_t::PETE_Expr_t >               \
00187 Fun(const PETE_Expr<Cond_t>& c, const Sca<T, Dim> &t,                       \
00188   const PETE_Expr<False_t>& f)                                              \
00189 {                                                                           \
00190   typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t, PETE_Scalar< Sca<T, Dim> >,  \
00191     typename False_t::PETE_Expr_t > ret;                                    \
00192   return ret(c.PETE_unwrap().MakeExpression(),                              \
00193     PETE_Scalar< Sca<T, Dim> >(t), f.PETE_unwrap().MakeExpression());       \
00194 }                                                                           \
00195 template<class Cond_t, class T, unsigned Dim>                               \
00196 inline PETE_TTTree<Op, typename Cond_t::PETE_Expr_t,                        \
00197   PETE_Scalar< Sca<T, Dim> >, PETE_Scalar< Sca<T, Dim> > >                  \
00198 Fun(const PETE_Expr<Cond_t>& c, const Sca<T, Dim> &t, const Sca<T, Dim> &f) \
00199 {                                                                           \
00200   typedef PETE_TTTree<Op, typename Cond_t::PETE_Expr_t,                     \
00201     PETE_Scalar< Sca<T, Dim> >,  PETE_Scalar< Sca<T, Dim> > > ret;          \
00202   return ret(c.PETE_unwrap().MakeExpression(),                              \
00203     PETE_Scalar< Sca<T, Dim> >(t), PETE_Scalar< Sca<T, Dim> >(f));          \
00204 }
00205 
00206 
00207 //tjw: make sure kosher to have "cross" down there (added in)
00208 #define PETE_DefineVSTScalar(Sca)                                           \
00209 PETE_DefineBinaryWithVSTScalars(operator+, OpAdd, Sca)                      \
00210 PETE_DefineBinaryWithVSTScalars(operator-, OpSubtract, Sca)                 \
00211 PETE_DefineBinaryWithVSTScalars(operator*, OpMultipply, Sca)                 \
00212 PETE_DefineBinaryWithVSTScalars(operator/, OpDivide, Sca)                   \
00213 PETE_DefineBinaryWithVSTScalars(operator%, OpMod, Sca)                      \
00214 PETE_DefineBinaryWithVSTScalars(operator<, OpLT, Sca)                       \
00215 PETE_DefineBinaryWithVSTScalars(operator<=, OpLE, Sca)                      \
00216 PETE_DefineBinaryWithVSTScalars(operator>, OpGT, Sca)                       \
00217 PETE_DefineBinaryWithVSTScalars(operator>=, OpGE, Sca)                      \
00218 PETE_DefineBinaryWithVSTScalars(operator==, OpEQ, Sca)                      \
00219 PETE_DefineBinaryWithVSTScalars(operator!=, OpNE, Sca)                      \
00220 PETE_DefineBinaryWithVSTScalars(operator&&, OpAnd, Sca)                     \
00221 PETE_DefineBinaryWithVSTScalars(operator||, OpOr, Sca)                      \
00222 PETE_DefineBinaryWithVSTScalars(operator&, OpBitwiseAnd, Sca)               \
00223 PETE_DefineBinaryWithVSTScalars(operator|, OpBitwiseOr, Sca)                \
00224 PETE_DefineBinaryWithVSTScalars(operator^, OpBitwiseXor, Sca)               \
00225 PETE_DefineBinaryWithVSTScalars(copysign, FnCopysign, Sca)                  \
00226 PETE_DefineBinaryWithVSTScalars(ldexp, FnLdexp, Sca)                        \
00227 PETE_DefineBinaryWithVSTScalars(pow, FnPow, Sca)                            \
00228 PETE_DefineBinaryWithVSTScalars(fmod, FnFmod, Sca)                          \
00229 PETE_DefineBinaryWithVSTScalars(atan2, FnArcTan2, Sca)                      \
00230 PETE_DefineTrinaryWithVSTScalars(where, OpWhere, Sca)                       \
00231 PETE_DefineBinaryWithVSTScalars(Min, FnMin, Sca)                            \
00232 PETE_DefineBinaryWithVSTScalars(Max, FnMax, Sca)                            \
00233 PETE_DefineBinaryWithVSTScalars(dot, FnDot, Sca)                            \
00234 PETE_DefineBinaryWithVSTScalars(dotdot, FnDotDot, Sca)                      \
00235 PETE_DefineBinaryWithVSTScalars(outerProduct, FnOuterProduct, Sca)          \
00236 PETE_DefineBinaryWithVSTScalars(cross, FnCross, Sca)                        \
00237 PETE_DefineBinaryWithVSTScalars(lt, OpLT, Sca)                              \
00238 PETE_DefineBinaryWithVSTScalars(le, OpLE, Sca)                              \
00239 PETE_DefineBinaryWithVSTScalars(gt, OpGT, Sca)                              \
00240 PETE_DefineBinaryWithVSTScalars(ge, OpGE, Sca)                              \
00241 PETE_DefineBinaryWithVSTScalars(eq, OpEQ, Sca)                              \
00242 PETE_DefineBinaryWithVSTScalars(ne, OpNE, Sca)
00243 
00244 PETE_DefineVSTScalar(Vektor)
00245 PETE_DefineVSTScalar(SymTenzor)
00246 PETE_DefineVSTScalar(Tenzor)
00247 
00248 #undef PETE_DefineVSTScalar
00249 
00250 
00251 //=========================================================================
00252 //
00253 // ASSIGNMENT OPERATIONS
00254 //
00255 //=========================================================================
00256 
00257 PETE_DefineAssign((a = Min(a,b)),(a = Min(a,b.value)), OpMinAssign)
00258 PETE_DefineAssign((a = Max(a,b)),(a = Max(a,b.value)), OpMaxAssign)
00259 PETE_DefineAssign((a = (a&&b))   ,(a = (a&&b.value))   , OpAndAssign)
00260 PETE_DefineAssign((a = (a||b))   ,(a = (a||b.value))   , OpOrAssign)
00261 
00262 
00263 //=========================================================================
00264 //
00265 // MIN and MAX REDUCTIONS
00266 // 
00267 //=========================================================================
00268 
00269 #ifdef __MWERKS__
00270 // Workaround for CodeWarrior 4 bug
00271 // Funny "MMin" name is to avoid conflict with Min defined elsewhere in r1
00272 template<class T> 
00273 struct MMin {
00274   typedef typename T::PETE_Expr_t::PETE_Return_t type_t;
00275   static inline type_t apply(const PETE_Expr<T>& expr) {
00276     type_t val ;
00277     Reduction(val, Expressionize<typename T::PETE_Expr_t>::apply( expr.PETE_unwrap().MakeExpression() ), 
00278               OpAssign(), OpMinAssign());
00279     return val;
00280   }
00281 };
00282 
00283 template<class T> 
00284 inline typename MMin<T>::type_t 
00285 min(const PETE_Expr<T>& expr) {
00286   return MMin<T>::apply(expr);
00287 }
00288 #else
00289 template<class T> 
00290 typename T::PETE_Expr_t::PETE_Return_t
00291 min(const PETE_Expr<T>& expr)
00292 {
00293   typename T::PETE_Expr_t::PETE_Return_t val ;
00294   Reduction(val,
00295             Expressionize<typename T::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00296             OpAssign(), 
00297             OpMinAssign());
00298   return val;
00299 }
00300 #endif // __MWERKS__
00301 
00302 #ifdef __MWERKS__
00303 // Workaround for CodeWarrior 4 bug
00304 // Funny "MMax" name is to avoid conflict with Max defined elsewhere in r1
00305 template<class T> 
00306 struct MMax {
00307   typedef typename T::PETE_Expr_t::PETE_Return_t type_t;
00308   static inline type_t apply(const PETE_Expr<T>& expr) {
00309     type_t val ;
00310     Reduction(val, Expressionize<typename T::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00311               OpAssign(), OpMaxAssign());
00312     return val;
00313   }
00314 };
00315 
00316 template<class T> 
00317 inline typename MMax<T>::type_t 
00318 max(const PETE_Expr<T>& expr) {
00319   return MMax<T>::apply(expr);
00320 }
00321 #else
00322 template<class T> 
00323 typename T::PETE_Expr_t::PETE_Return_t
00324 max(const PETE_Expr<T>& expr)
00325 {
00326   typename T::PETE_Expr_t::PETE_Return_t val ;
00327   Reduction(val,
00328             Expressionize<typename T::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00329             OpAssign(), 
00330             OpMaxAssign());
00331   return val;
00332 }
00333 #endif // __MWERKS__
00334 
00335 
00336 //=========================================================================
00337 //
00338 // MINMAX REDUCTION
00339 // 
00340 //=========================================================================
00341 
00342 template<class T>
00343 struct MinMaxHolder {
00344   T a;
00345   T b;
00346   MinMaxHolder() { }
00347   MinMaxHolder(const MinMaxHolder<T>& rhs) : a(rhs.a), b(rhs.b) { }
00348   const MinMaxHolder<T>& operator=(const MinMaxHolder<T>& rhs) {
00349     a = rhs.a;
00350     b = rhs.b;
00351     return *this;
00352   }
00353   const MinMaxHolder<T>& operator=(const T& rhs) {
00354     T c = rhs;
00355     a = c;
00356     b = c;
00357     return *this;
00358   }
00359   const MinMaxHolder<T>& operator*=(const MinMaxHolder<T>& rhs) {
00360     a = (a < rhs.a ? a : rhs.a);
00361     b = (rhs.b < b ? b : rhs.b);
00362     return *this;
00363   }
00364   const MinMaxHolder<T>& operator*=(const T& rhs) {
00365     T c = rhs;
00366     a = (a < c ? a : c);
00367     b = (c < b ? b : c);
00368     return *this;
00369   }
00370   Message& putMessage(Message& m) {
00371     m.put(a);
00372     m.put(b);
00373     return m;
00374   }
00375   Message& getMessage(Message& m) {
00376     m.get(a);
00377     m.get(b);
00378     return m;
00379   }
00380 };
00381 
00382 template<class T1, class T2>
00383 void
00384 minmax(const PETE_Expr<T1>& expr, T2& minval, T2& maxval)
00385 {
00386   typedef typename T1::PETE_Expr_t::PETE_Return_t val_t;
00387   MinMaxHolder<val_t> ret;
00388   Reduction(ret,
00389             Expressionize<typename T1::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00390             OpAssign(),
00391             OpMultipplyAssign());
00392   minval = static_cast<T2>(ret.a);
00393   maxval = static_cast<T2>(ret.b);
00394 }
00395 
00396 
00398 //
00399 // The 'any' function finds if there is any location in the expression
00400 // where a condition is true.
00401 //
00403 
00404 template<class T, class OP>
00405 struct AnyHolder
00406 {
00407   bool Test;
00408   T Val;
00409   OP Op;
00410   AnyHolder() : Test(false), Val(T(0)), Op(OP()) {}
00411   AnyHolder(const T& t, OP op) : Test(false), Val(t), Op(op) {}
00412   AnyHolder(const AnyHolder<T,OP>& rhs)
00413     : Test(rhs.Test), Val(rhs.Val), Op(rhs.Op) { }
00414   const AnyHolder<T,OP>& operator=(const T& rhs)
00415   {
00416     if ( PETE_apply(Op,rhs,Val) )
00417       Test = true;
00418     return *this;
00419   }
00420   const AnyHolder<T,OP>& operator=(const AnyHolder<T,OP>& rhs)
00421   {
00422     Test = rhs.Test;
00423     Val = rhs.Val;
00424     Op = rhs.Op;
00425     return *this;
00426   }
00427   const AnyHolder<T,OP>& operator*=(const T& rhs)
00428   {
00429     if ( PETE_apply(Op,rhs,Val) )
00430       Test = true;
00431     return *this;
00432   }
00433   const AnyHolder<T,OP>& operator*=(const AnyHolder<T,OP>& rhs)
00434   {
00435     Test = (Test || rhs.Test);
00436     return *this;
00437   }
00438   Message& putMessage(Message& m) 
00439   {
00440     m.put(Test);
00441     return m;
00442   }
00443   Message& getMessage(Message& m)
00444   {
00445     m.get(Test);
00446     return m;
00447   }
00448 };
00449 
00450 template<class T1, class T2>
00451 bool
00452 any(const PETE_Expr<T1>& expr, T2 val)
00453 {
00454   AnyHolder<T2,OpEQ> ret(val,OpEQ());
00455   Reduction(ret,
00456             Expressionize<typename T1::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00457             OpAssign(),
00458             OpMultipplyAssign());
00459   return ret.Test;
00460 }
00461 
00462 template<class T1, class T2, class Op>
00463 bool
00464 any(const PETE_Expr<T1>& expr, T2 val, Op op)
00465 {
00466   AnyHolder<T2,Op> ret(val,op);
00467   Reduction(ret,
00468             Expressionize<typename T1::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00469             OpAssign(),
00470             OpMultipplyAssign());
00471   return ret.Test;
00472 }
00473 
00474 
00475 //=========================================================================
00476 //
00477 // BOUNDS REDUCTION - find bounding box of Vektor expression
00478 // for scalars, use minmax
00479 // for tensors, extend this code to include them as well
00480 // 
00481 //=========================================================================
00482 
00483 template<class T, unsigned int D>
00484 struct BoundsHolder {
00485   Vektor<T,D> a;
00486   Vektor<T,D> b;
00487   BoundsHolder() { }
00488   BoundsHolder(const BoundsHolder<T,D>& rhs) : a(rhs.a), b(rhs.b) { }
00489   const BoundsHolder<T,D>& operator=(const BoundsHolder<T,D>& rhs) {
00490     a = rhs.a;
00491     b = rhs.b;
00492     return *this;
00493   }
00494   const BoundsHolder<T,D>& operator=(const Vektor<T,D>& rhs) {
00495     Vektor<T,D> c(rhs);
00496     a = c;
00497     b = c;
00498     return *this;
00499   }
00500   const BoundsHolder<T,D>& operator=(const T& rhs) {
00501     Vektor<T,D> c(rhs);
00502     a = c;
00503     b = c;
00504     return *this;
00505   }
00506   const BoundsHolder<T,D>& operator*=(const BoundsHolder<T,D>& rhs) {
00507     for (unsigned int d=0; d < D; ++d) {
00508       a[d] = (a[d] < rhs.a[d] ? a[d] : rhs.a[d]);
00509       b[d] = (rhs.b[d] < b[d] ? b[d] : rhs.b[d]);
00510     }
00511     return *this;
00512   }
00513   const BoundsHolder<T,D>& operator*=(const Vektor<T,D>& rhs) {
00514     Vektor<T,D> c(rhs);
00515     for (unsigned int d=0; d < D; ++d) {
00516       a[d] = (a[d] < c[d] ? a[d] : c[d]);
00517       b[d] = (c[d] < b[d] ? b[d] : c[d]);
00518     }
00519     return *this;
00520   }
00521   const BoundsHolder<T,D>& operator*=(const T& rhs) {
00522     Vektor<T,D> c(rhs);
00523     for (unsigned int d=0; d < D; ++d) {
00524       a[d] = (a[d] < c[d] ? a[d] : c[d]);
00525       b[d] = (c[d] < b[d] ? b[d] : c[d]);
00526     }
00527     return *this;
00528   }
00529   Message& putMessage(Message& m) {
00530     m.put(a);
00531     m.put(b);
00532     return m;
00533   }
00534   Message& getMessage(Message& m) {
00535     m.get(a);
00536     m.get(b);
00537     return m;
00538   }
00539 };
00540 
00541 template<class T1, class T2, unsigned int D>
00542 void
00543 bounds(const PETE_Expr<T1>& expr, Vektor<T2,D>& minval, Vektor<T2,D>& maxval)
00544 {
00545   BoundsHolder<T2,D> ret;
00546   Reduction(ret,
00547             Expressionize<typename T1::PETE_Expr_t>::apply(expr.PETE_unwrap().MakeExpression()),
00548             OpAssign(),
00549             OpMultipplyAssign());
00550   minval = ret.a;
00551   maxval = ret.b;
00552 }
00553 
00554 
00555 //=========================================================================
00556 //
00557 // OPERATOR()
00558 // 
00559 //=========================================================================
00560 
00561 template<class T, class TP>
00562 inline typename PETEUnaryReturn<T,OpParens<TP> >::type
00563 PETE_apply(OpParens<TP> op, const T& a)
00564 {
00565   return a(op.Arg);
00566 }
00567 
00568 
00569 //=========================================================================
00570 //
00571 // MISCELLANEOUS
00572 // 
00573 //=========================================================================
00574 
00575 // When figuring out data dependencies you sometimes need to know
00576 // if the left hand side of an assignment needs to be read
00577 // before being it is written.
00578 // The following trait will set IsAssign to 1 for OpAssign
00579 // and to zero for all the other assignment functions.
00580 
00581 template<class Op> struct OperatorTraits { enum { IsAssign=0 }; };
00582 template<> struct OperatorTraits<OpAssign> { enum { IsAssign=1 }; };
00583 
00584 
00586 //
00587 // END OF FILE
00588 // 
00590 
00591 #endif // IPPL_EXPRESSIONS_H
00592 
00593 /***************************************************************************
00594  * $RCSfile: IpplExpressions.h,v $   $Author: adelmann $
00595  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:28 $
00596  * IPPL_VERSION_ID: $Id: IpplExpressions.h,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $ 
00597  ***************************************************************************/

Generated on Mon Jan 16 13:23:53 2006 for IPPL by  doxygen 1.4.6