Sacado Package Browser (Single Doxygen Collection) Version of the Day
Sacado_ELRCacheFad_Ops.hpp
Go to the documentation of this file.
00001 // $Id$ 
00002 // $Source$ 
00003 // @HEADER
00004 // ***********************************************************************
00005 // 
00006 //                           Sacado Package
00007 //                 Copyright (2006) Sandia Corporation
00008 // 
00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00010 // the U.S. Government retains certain rights in this software.
00011 // 
00012 // This library is free software; you can redistribute it and/or modify
00013 // it under the terms of the GNU Lesser General Public License as
00014 // published by the Free Software Foundation; either version 2.1 of the
00015 // License, or (at your option) any later version.
00016 //  
00017 // This library is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //  
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
00027 // (etphipp@sandia.gov).
00028 // 
00029 // ***********************************************************************
00030 //
00031 // The forward-mode AD classes in Sacado are a derivative work of the
00032 // expression template classes in the Fad package by Nicolas Di Cesare.  
00033 // The following banner is included in the original Fad source code:
00034 //
00035 // ************ DO NOT REMOVE THIS BANNER ****************
00036 //
00037 //  Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
00038 //  http://www.ann.jussieu.fr/~dicesare
00039 //
00040 //            CEMRACS 98 : C++ courses, 
00041 //         templates : new C++ techniques 
00042 //            for scientific computing 
00043 // 
00044 //********************************************************
00045 //
00046 //  A short implementation ( not all operators and 
00047 //  functions are overloaded ) of 1st order Automatic
00048 //  Differentiation in forward mode (FAD) using
00049 //  EXPRESSION TEMPLATES.
00050 //
00051 //********************************************************
00052 // @HEADER
00053 
00054 #ifndef SACADO_ELRCACHEFAD_OPS_HPP
00055 #define SACADO_ELRCACHEFAD_OPS_HPP
00056 
00057 #include "Sacado_ELRCacheFad_Expression.hpp"
00058 #include "Sacado_cmath.hpp"
00059 #include "Sacado_mpl_disable_if.hpp"
00060 #include "Sacado_mpl_is_same.hpp"
00061 #include <ostream>  // for std::ostream
00062 
00063 namespace Sacado {
00064   namespace ELRCacheFad {
00065 
00066     //
00067     // UnaryPlusOp
00068     //
00069 
00070     template <typename ExprT>
00071     class UnaryPlusOp {};
00072 
00073     template <typename ExprT>
00074     class Expr< UnaryPlusOp<ExprT> > {
00075     public:
00076 
00077       typedef typename ExprT::value_type value_type;
00078       typedef typename ExprT::scalar_type scalar_type;
00079 
00080       typedef typename ExprT::base_expr_type base_expr_type;
00081 
00082       static const int num_args = ExprT::num_args;
00083 
00084       static const bool is_linear = true;
00085 
00086       Expr(const ExprT& expr_) : expr(expr_)  {}
00087 
00088       int size() const { return expr.size(); }
00089 
00090       template <int Arg>
00091       bool isActive() const { return expr.template isActive<Arg>(); }
00092 
00093       bool updateValue() const { return expr.updateValue(); }
00094 
00095       void cache() const {
00096   expr.cache();
00097       }
00098 
00099       value_type val() const {
00100   return expr.val();
00101       }
00102 
00103       void computePartials(const value_type& bar,
00104          value_type partials[]) const {
00105   expr.computePartials(bar, partials);
00106       }
00107 
00108       void getTangents(int i, value_type dots[]) const {
00109   expr.getTangents(i, dots); }
00110 
00111       template <int Arg>
00112       value_type getTangent(int i) const {
00113   return expr.template getTangent<Arg>(i);
00114       }
00115 
00116       bool isLinear() const {
00117         return expr.isLinear();
00118       }
00119 
00120       bool hasFastAccess() const {
00121         return expr.hasFastAccess();
00122       }
00123 
00124       const value_type dx(int i) const {
00125         return expr.dx(i);
00126       }
00127  
00128       const value_type fastAccessDx(int i) const {
00129         return expr.fastAccessDx(i);
00130       }
00131 
00132       const base_expr_type& getArg(int j) const {
00133   return expr.getArg(j);
00134       }
00135 
00136     protected:
00137 
00138       const ExprT& expr;
00139     };
00140 
00141     template <typename T>
00142     inline Expr< UnaryPlusOp< Expr<T> > >
00143     operator+ (const Expr<T>& expr)
00144     {
00145       typedef UnaryPlusOp< Expr<T> > expr_t;
00146       
00147       return Expr<expr_t>(expr);
00148     }
00149 
00150     //
00151     // UnaryMinusOp
00152     //
00153     template <typename ExprT>
00154     class UnaryMinusOp {};
00155 
00156     template <typename ExprT>
00157     class Expr< UnaryMinusOp<ExprT> > {
00158     public:
00159 
00160       typedef typename ExprT::value_type value_type;
00161       typedef typename ExprT::scalar_type scalar_type;
00162 
00163       typedef typename ExprT::base_expr_type base_expr_type;
00164 
00165       static const int num_args = ExprT::num_args;
00166 
00167       static const bool is_linear = true;
00168 
00169       Expr(const ExprT& expr_) : expr(expr_)  {}
00170 
00171       int size() const { return expr.size(); }
00172 
00173       template <int Arg>
00174       bool isActive() const { return expr.template isActive<Arg>(); }
00175 
00176       bool updateValue() const { return expr.updateValue(); }
00177 
00178       void cache() const {
00179   expr.cache();
00180       }
00181 
00182       value_type val() const {
00183   return -expr.val();
00184       }
00185 
00186       void computePartials(const value_type& bar,
00187          value_type partials[]) const {
00188   expr.computePartials(-bar, partials);
00189       }
00190 
00191       void getTangents(int i, value_type dots[]) const {
00192   expr.getTangents(i, dots); }
00193 
00194       template <int Arg>
00195       value_type getTangent(int i) const {
00196   return expr.template getTangent<Arg>(i);
00197       }
00198 
00199       bool isLinear() const {
00200         return expr.isLinear();
00201       }
00202 
00203       bool hasFastAccess() const {
00204         return expr.hasFastAccess();
00205       }
00206 
00207       const value_type dx(int i) const {
00208         return -expr.dx(i);
00209       }
00210  
00211       const value_type fastAccessDx(int i) const {
00212         return -expr.fastAccessDx(i);
00213       }
00214 
00215       const base_expr_type& getArg(int j) const {
00216   return expr.getArg(j);
00217       }
00218 
00219     protected:
00220 
00221       const ExprT& expr;
00222     };
00223 
00224     template <typename T>
00225     inline Expr< UnaryMinusOp< Expr<T> > >
00226     operator- (const Expr<T>& expr)
00227     {
00228       typedef UnaryMinusOp< Expr<T> > expr_t;
00229       
00230       return Expr<expr_t>(expr);
00231     }
00232 
00233     //
00234     // AbsOp
00235     //
00236 
00237     template <typename ExprT>
00238     class AbsOp {};
00239 
00240     template <typename ExprT>
00241     class Expr< AbsOp<ExprT> > {
00242     public:
00243 
00244       typedef typename ExprT::value_type value_type;
00245       typedef typename ExprT::scalar_type scalar_type;
00246 
00247       typedef typename ExprT::base_expr_type base_expr_type;
00248 
00249       static const int num_args = ExprT::num_args;
00250 
00251       static const bool is_linear = false;
00252 
00253       Expr(const ExprT& expr_) : expr(expr_)  {}
00254 
00255       int size() const { return expr.size(); }
00256 
00257       template <int Arg>
00258       bool isActive() const { return expr.template isActive<Arg>(); }
00259 
00260       bool updateValue() const { return expr.updateValue(); }
00261 
00262       void cache() const {
00263   expr.cache();
00264   v = expr.val();
00265   v_pos = (v >= 0);
00266       }
00267 
00268       value_type val() const {
00269   return std::abs(v);
00270       }
00271 
00272       void computePartials(const value_type& bar,
00273          value_type partials[]) const {
00274   if (v_pos)
00275     expr.computePartials(bar, partials);
00276   else
00277     expr.computePartials(-bar, partials);
00278       }
00279 
00280       void getTangents(int i, value_type dots[]) const {
00281   expr.getTangents(i, dots); }
00282 
00283       template <int Arg>
00284       value_type getTangent(int i) const {
00285   return expr.template getTangent<Arg>(i);
00286       }
00287 
00288       bool isLinear() const {
00289         return false;
00290       }
00291 
00292       bool hasFastAccess() const {
00293         return expr.hasFastAccess();
00294       }
00295 
00296       const value_type dx(int i) const {
00297         if (v_pos) return expr.dx(i); 
00298   else return -expr.dx(i);
00299       }
00300  
00301       const value_type fastAccessDx(int i) const {
00302         if (v_pos) return expr.fastAccessDx(i);
00303   else return -expr.fastAccessDx(i);
00304       }
00305 
00306       const base_expr_type& getArg(int j) const {
00307   return expr.getArg(j);
00308       }
00309 
00310     protected:
00311 
00312       const ExprT& expr;
00313       mutable value_type v;
00314       mutable bool v_pos;
00315     };
00316 
00317     template <typename T>
00318     inline Expr< AbsOp< Expr<T> > >
00319     abs (const Expr<T>& expr)
00320     {
00321       typedef AbsOp< Expr<T> > expr_t;
00322       
00323       return Expr<expr_t>(expr);
00324     }
00325 
00326     //
00327     // FAbsOp
00328     //
00329 
00330     template <typename ExprT>
00331     class FAbsOp {};
00332 
00333     template <typename ExprT>
00334     class Expr< FAbsOp<ExprT> > {
00335     public:
00336 
00337       typedef typename ExprT::value_type value_type;
00338       typedef typename ExprT::scalar_type scalar_type;
00339 
00340       typedef typename ExprT::base_expr_type base_expr_type;
00341 
00342       static const int num_args = ExprT::num_args;
00343 
00344       static const bool is_linear = false;
00345 
00346       Expr(const ExprT& expr_) : expr(expr_)  {}
00347 
00348       int size() const { return expr.size(); }
00349 
00350       template <int Arg>
00351       bool isActive() const { return expr.template isActive<Arg>(); }
00352 
00353       bool updateValue() const { return expr.updateValue(); }
00354 
00355       void cache() const {
00356   expr.cache();
00357   v = expr.val();
00358   v_pos = (v >= 0);
00359       }
00360 
00361       value_type val() const {
00362   return std::fabs(v);
00363       }
00364 
00365       void computePartials(const value_type& bar,
00366          value_type partials[]) const {
00367   if (v_pos)
00368     expr.computePartials(bar, partials);
00369   else
00370     expr.computePartials(-bar, partials);
00371       }
00372 
00373       void getTangents(int i, value_type dots[]) const {
00374   expr.getTangents(i, dots); }
00375 
00376       template <int Arg>
00377       value_type getTangent(int i) const {
00378   return expr.template getTangent<Arg>(i);
00379       }
00380 
00381       bool isLinear() const {
00382         return false;
00383       }
00384 
00385       bool hasFastAccess() const {
00386         return expr.hasFastAccess();
00387       }
00388 
00389       const value_type dx(int i) const {
00390         if (v_pos) return expr.dx(i);
00391   else return -expr.dx(i);
00392       }
00393  
00394       const value_type fastAccessDx(int i) const {
00395         if (v_pos) return expr.fastAccessDx(i);
00396   else return -expr.fastAccessDx(i);
00397       }
00398 
00399       const base_expr_type& getArg(int j) const {
00400   return expr.getArg(j);
00401       }
00402 
00403     protected:
00404 
00405       const ExprT& expr;
00406       mutable value_type v;
00407       mutable bool v_pos;
00408     };
00409 
00410     template <typename T>
00411     inline Expr< FAbsOp< Expr<T> > >
00412     fabs (const Expr<T>& expr)
00413     {
00414       typedef FAbsOp< Expr<T> > expr_t;
00415       
00416       return Expr<expr_t>(expr);
00417     }
00418 
00419   }
00420 }
00421 
00422 #define FAD_UNARYOP_MACRO(OPNAME,OP,PARTIAL,VALUE)      \
00423 namespace Sacado {              \
00424   namespace ELRCacheFad {           \
00425                   \
00426     template <typename ExprT>           \
00427     class OP {};              \
00428                   \
00429     template <typename ExprT>           \
00430     class Expr< OP<ExprT> > {           \
00431     public:               \
00432                   \
00433       typedef typename ExprT::value_type value_type;      \
00434       typedef typename ExprT::scalar_type scalar_type;      \
00435                   \
00436       typedef typename ExprT::base_expr_type base_expr_type;    \
00437                   \
00438       static const int num_args = ExprT::num_args;      \
00439                   \
00440       static const bool is_linear = false;        \
00441                   \
00442       Expr(const ExprT& expr_) : expr(expr_)  {}      \
00443                   \
00444       int size() const { return expr.size(); }        \
00445                   \
00446       template <int Arg>            \
00447       bool isActive() const { return expr.template isActive<Arg>(); } \
00448                   \
00449       bool updateValue() const { return expr.updateValue(); }   \
00450                   \
00451       void cache() const {            \
00452   expr.cache();             \
00453         v = expr.val();             \
00454   PARTIAL;              \
00455       }                 \
00456                   \
00457       value_type val() const {            \
00458   return VALUE;             \
00459       }                 \
00460                   \
00461       void computePartials(const value_type& bar,     \
00462          value_type partials[]) const {   \
00463   expr.computePartials(bar*a, partials);        \
00464       }                 \
00465                   \
00466       void getTangents(int i, value_type dots[]) const {    \
00467   expr.getTangents(i, dots); }          \
00468                   \
00469       template <int Arg>            \
00470       value_type getTangent(int i) const {        \
00471   return expr.template getTangent<Arg>(i);      \
00472       }                 \
00473                   \
00474       bool isLinear() const {                                           \
00475         return false;             \
00476       }                                                                 \
00477                                                                         \
00478       bool hasFastAccess() const {                                      \
00479         return expr.hasFastAccess();                                    \
00480       }                                                                 \
00481                                                                         \
00482       const value_type dx(int i) const {                                \
00483         return expr.dx(i)*a;            \
00484       }                                                                 \
00485                                                                         \
00486       const value_type fastAccessDx(int i) const {                      \
00487         return expr.fastAccessDx(i)*a;          \
00488       }                                                                 \
00489                   \
00490       const base_expr_type& getArg(int j) const {     \
00491   return expr.getArg(j);            \
00492       }                 \
00493                   \
00494     protected:                \
00495                   \
00496       const ExprT& expr;            \
00497       mutable value_type v;           \
00498       mutable value_type a;           \
00499     };                  \
00500                   \
00501     template <typename T>           \
00502     inline Expr< OP< Expr<T> > >          \
00503     OPNAME (const Expr<T>& expr)          \
00504     {                 \
00505       typedef OP< Expr<T> > expr_t;         \
00506                         \
00507       return Expr<expr_t>(expr);          \
00508     }                 \
00509   }                 \
00510 }
00511 
00512 FAD_UNARYOP_MACRO(exp,
00513       ExpOp, 
00514       a = std::exp(v),
00515       a)
00516 FAD_UNARYOP_MACRO(log,
00517       LogOp, 
00518       a=scalar_type(1.0)/v,
00519       std::log(v))
00520 FAD_UNARYOP_MACRO(log10,
00521       Log10Op, 
00522       a = scalar_type(1.0)/(std::log(scalar_type(10.0))*v),
00523       std::log10(v))
00524 FAD_UNARYOP_MACRO(sqrt,
00525       SqrtOp, 
00526       a = scalar_type(1.0)/(scalar_type(2.0)*std::sqrt(v)),
00527       std::sqrt(v))
00528 FAD_UNARYOP_MACRO(cos,
00529       CosOp, 
00530       a = -std::sin(v),
00531       std::cos(v))
00532 FAD_UNARYOP_MACRO(sin,
00533       SinOp, 
00534       a = std::cos(v),
00535       std::sin(v))
00536 FAD_UNARYOP_MACRO(tan,
00537       TanOp, 
00538       a = scalar_type(1.0)+std::tan(v)*std::tan(v),
00539       std::tan(v))
00540 FAD_UNARYOP_MACRO(acos,
00541       ACosOp, 
00542       a = scalar_type(-1.0)/std::sqrt(scalar_type(1.0)-v*v),
00543       std::acos(v))
00544 FAD_UNARYOP_MACRO(asin,
00545       ASinOp, 
00546       a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)-v*v),
00547       std::asin(v))
00548 FAD_UNARYOP_MACRO(atan,
00549       ATanOp, 
00550       a = scalar_type(1.0)/(scalar_type(1.0)+v*v),
00551       std::atan(v))
00552 FAD_UNARYOP_MACRO(cosh,
00553       CoshOp, 
00554       a = std::sinh(v),
00555       std::cosh(v))
00556 FAD_UNARYOP_MACRO(sinh,
00557       SinhOp, 
00558       a = std::cosh(v),
00559       std::sinh(v))
00560 FAD_UNARYOP_MACRO(tanh,
00561       TanhOp, 
00562       a = scalar_type(1.0)/(std::cosh(v)*std::cosh(v)),
00563       std::tanh(v))
00564 FAD_UNARYOP_MACRO(acosh,
00565       ACoshOp, 
00566       a = scalar_type(1.0)/std::sqrt((v-scalar_type(1.0))*(v+scalar_type(1.0))),
00567       std::acosh(v))
00568 FAD_UNARYOP_MACRO(asinh,
00569       ASinhOp, 
00570       a = scalar_type(1.0)/std::sqrt(scalar_type(1.0)+v*v),
00571       std::asinh(v))
00572 FAD_UNARYOP_MACRO(atanh,
00573       ATanhOp, 
00574       a = scalar_type(1.0)/(scalar_type(1.0)-v*v),
00575       std::atanh(v))
00576 
00577 #undef FAD_UNARYOP_MACRO
00578 
00579 //
00580 // Binary operators
00581 //
00582 namespace Sacado {
00583   namespace ELRCacheFad {
00584 
00585     //
00586     // AdditionOp
00587     //
00588 
00589     template <typename ExprT1, typename ExprT2>
00590     class AdditionOp {};
00591 
00592     template <typename ExprT1, typename ExprT2>
00593     class Expr< AdditionOp<ExprT1,ExprT2> > {
00594 
00595     public:
00596 
00597       typedef typename ExprT1::value_type value_type_1;
00598       typedef typename ExprT2::value_type value_type_2;
00599       typedef typename Sacado::Promote<value_type_1,
00600                value_type_2>::type value_type;
00601       typedef typename ExprT1::scalar_type scalar_type_1;
00602       typedef typename ExprT2::scalar_type scalar_type_2;
00603       typedef typename Sacado::Promote<scalar_type_1,
00604                scalar_type_2>::type scalar_type;
00605 
00606       typedef typename ExprT1::base_expr_type base_expr_type_1;
00607       typedef typename ExprT2::base_expr_type base_expr_type_2;
00608       typedef typename ExprPromote<base_expr_type_1,
00609            base_expr_type_2>::type base_expr_type;
00610 
00611       static const int num_args1 = ExprT1::num_args;
00612       static const int num_args2 = ExprT2::num_args;
00613       static const int num_args = num_args1 + num_args2;
00614 
00615       static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
00616 
00617       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
00618   expr1(expr1_), expr2(expr2_) {}
00619 
00620       int size() const {
00621   int sz1 = expr1.size(), sz2 = expr2.size();
00622   return sz1 > sz2 ? sz1 : sz2;
00623       }
00624 
00625       template <int Arg> bool isActive() const {
00626   if (Arg < num_args1)
00627     return expr1.template isActive<Arg>();
00628   else
00629     return expr2.template isActive<Arg-num_args1>();
00630       }
00631 
00632       bool updateValue() const {
00633   return expr1.updateValue() && expr2.updateValue();
00634       }
00635 
00636       void cache() const {
00637   expr1.cache();
00638   expr2.cache();
00639       }
00640 
00641       value_type val() const {
00642   return expr1.val()+expr2.val();
00643       }
00644 
00645       void computePartials(const value_type& bar,
00646          value_type partials[]) const {
00647   if (num_args1 > 0)
00648     expr1.computePartials(bar, partials);
00649   if (num_args2 > 0)
00650     expr2.computePartials(bar, partials+num_args1);
00651       }
00652 
00653       void getTangents(int i, value_type dots[]) const {
00654   expr1.getTangents(i, dots);
00655   expr2.getTangents(i, dots+num_args1);
00656       }
00657 
00658       template <int Arg> value_type getTangent(int i) const {
00659   if (Arg < num_args1)
00660     return expr1.template getTangent<Arg>(i);
00661   else
00662     return expr2.template getTangent<Arg-num_args1>(i);
00663       }
00664 
00665       bool isLinear() const {
00666         return expr1.isLinear() && expr2.isLinear();
00667       }
00668 
00669       bool hasFastAccess() const {
00670         return expr1.hasFastAccess() && expr2.hasFastAccess();
00671       }
00672 
00673       const value_type dx(int i) const {
00674         return expr1.dx(i) + expr2.dx(i);
00675       }
00676 
00677       const value_type fastAccessDx(int i) const {
00678         return expr1.fastAccessDx(i) + expr2.fastAccessDx(i);
00679       }
00680 
00681       const base_expr_type& getArg(int j) const {
00682   if (j < num_args1)
00683     return expr1.getArg(j);
00684   else
00685     return expr2.getArg(j-num_args1);
00686       }
00687 
00688     protected:
00689 
00690       const ExprT1& expr1;
00691       const ExprT2& expr2;
00692 
00693     };
00694 
00695     template <typename ExprT1, typename T2>
00696     class Expr< AdditionOp<ExprT1, ConstExpr<T2> > > {
00697 
00698     public:
00699 
00700       typedef ConstExpr<T2> ExprT2;
00701       typedef typename ExprT1::value_type value_type_1;
00702       typedef typename ExprT2::value_type value_type_2;
00703       typedef typename Sacado::Promote<value_type_1,
00704                value_type_2>::type value_type;
00705       typedef typename ExprT1::scalar_type scalar_type_1;
00706       typedef typename ExprT2::scalar_type scalar_type_2;
00707       typedef typename Sacado::Promote<scalar_type_1,
00708                scalar_type_2>::type scalar_type;
00709 
00710       typedef typename ExprT1::base_expr_type base_expr_type_1;
00711       typedef typename ExprT2::base_expr_type base_expr_type_2;
00712       typedef typename ExprPromote<base_expr_type_1,
00713            base_expr_type_2>::type base_expr_type;
00714 
00715       static const int num_args = ExprT1::num_args;
00716 
00717       static const bool is_linear = ExprT1::is_linear;
00718 
00719       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
00720   expr1(expr1_), expr2(expr2_) {}
00721 
00722       int size() const {
00723   return expr1.size();
00724       }
00725 
00726       template <int Arg> bool isActive() const {
00727   return expr1.template isActive<Arg>();
00728       }
00729 
00730       bool updateValue() const {
00731   return expr1.updateValue();
00732       }
00733 
00734       void cache() const {
00735   expr1.cache();
00736       }
00737 
00738       value_type val() const {
00739   return expr1.val() + expr2.val();
00740       }
00741 
00742       void computePartials(const value_type& bar,
00743          value_type partials[]) const {
00744   expr1.computePartials(bar, partials);
00745       }
00746 
00747       void getTangents(int i, value_type dots[]) const {
00748   expr1.getTangents(i, dots);
00749       }
00750 
00751       template <int Arg> value_type getTangent(int i) const {
00752   return expr1.template getTangent<Arg>(i);
00753       }
00754 
00755       bool isLinear() const {
00756         return expr1.isLinear();
00757       }
00758 
00759       bool hasFastAccess() const {
00760         return expr1.hasFastAccess();
00761       }
00762 
00763       const value_type dx(int i) const {
00764         return expr1.dx(i);
00765       }
00766 
00767       const value_type fastAccessDx(int i) const {
00768         return expr1.fastAccessDx(i);
00769       }
00770 
00771       const base_expr_type& getArg(int j) const {
00772   return expr1.getArg(j);
00773       }
00774 
00775     protected:
00776 
00777       const ExprT1& expr1;
00778       ExprT2 expr2;
00779 
00780     };
00781 
00782     template <typename T1, typename ExprT2>
00783     class Expr< AdditionOp< ConstExpr<T1>,ExprT2> > {
00784 
00785     public:
00786 
00787       typedef ConstExpr<T1> ExprT1;
00788       typedef typename ExprT1::value_type value_type_1;
00789       typedef typename ExprT2::value_type value_type_2;
00790       typedef typename Sacado::Promote<value_type_1,
00791                value_type_2>::type value_type;
00792       typedef typename ExprT1::scalar_type scalar_type_1;
00793       typedef typename ExprT2::scalar_type scalar_type_2;
00794       typedef typename Sacado::Promote<scalar_type_1,
00795                scalar_type_2>::type scalar_type;
00796 
00797       typedef typename ExprT1::base_expr_type base_expr_type_1;
00798       typedef typename ExprT2::base_expr_type base_expr_type_2;
00799       typedef typename ExprPromote<base_expr_type_1,
00800            base_expr_type_2>::type base_expr_type;
00801 
00802       static const int num_args = ExprT2::num_args;
00803 
00804       static const bool is_linear = ExprT2::is_linear;
00805 
00806       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
00807   expr1(expr1_), expr2(expr2_) {}
00808 
00809       int size() const {
00810   return expr2.size();
00811       }
00812 
00813       template <int Arg> bool isActive() const {
00814   return expr2.template isActive<Arg>();
00815       }
00816 
00817       bool updateValue() const {
00818   return expr2.updateValue();
00819       }
00820 
00821       void cache() const {
00822   expr2.cache();
00823       }
00824 
00825       value_type val() const {
00826   return expr1.val() + expr2.val();
00827       }
00828 
00829       void computePartials(const value_type& bar,
00830          value_type partials[]) const {
00831   expr2.computePartials(bar, partials);
00832       }
00833 
00834       void getTangents(int i, value_type dots[]) const {
00835   expr2.getTangents(i, dots);
00836       }
00837 
00838       template <int Arg> value_type getTangent(int i) const {
00839   return expr2.template getTangent<Arg>(i);
00840       }
00841 
00842       bool isLinear() const {
00843         return expr2.isLinear();
00844       }
00845 
00846       bool hasFastAccess() const {
00847         return expr2.hasFastAccess();
00848       }
00849 
00850       const value_type dx(int i) const {
00851         return expr2.dx(i);
00852       }
00853 
00854       const value_type fastAccessDx(int i) const {
00855         return expr2.fastAccessDx(i);
00856       }
00857 
00858       const base_expr_type& getArg(int j) const {
00859   return expr2.getArg(j);
00860       }
00861 
00862     protected:
00863 
00864       ExprT1 expr1;
00865       const ExprT2& expr2;
00866 
00867     };
00868 
00869     //
00870     // SubtractionOp
00871     //
00872 
00873     template <typename ExprT1, typename ExprT2>
00874     class SubtractionOp {};
00875 
00876     template <typename ExprT1, typename ExprT2>
00877     class Expr< SubtractionOp<ExprT1,ExprT2> > {
00878 
00879     public:
00880 
00881       typedef typename ExprT1::value_type value_type_1;
00882       typedef typename ExprT2::value_type value_type_2;
00883       typedef typename Sacado::Promote<value_type_1,
00884                value_type_2>::type value_type;
00885       typedef typename ExprT1::scalar_type scalar_type_1;
00886       typedef typename ExprT2::scalar_type scalar_type_2;
00887       typedef typename Sacado::Promote<scalar_type_1,
00888                scalar_type_2>::type scalar_type;
00889 
00890       typedef typename ExprT1::base_expr_type base_expr_type_1;
00891       typedef typename ExprT2::base_expr_type base_expr_type_2;
00892       typedef typename ExprPromote<base_expr_type_1,
00893            base_expr_type_2>::type base_expr_type;
00894 
00895       static const int num_args1 = ExprT1::num_args;
00896       static const int num_args2 = ExprT2::num_args;
00897       static const int num_args = num_args1 + num_args2;
00898 
00899       static const bool is_linear = ExprT1::is_linear && ExprT2::is_linear;
00900 
00901       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
00902   expr1(expr1_), expr2(expr2_) {}
00903 
00904       int size() const {
00905   int sz1 = expr1.size(), sz2 = expr2.size();
00906   return sz1 > sz2 ? sz1 : sz2;
00907       }
00908 
00909       template <int Arg> bool isActive() const {
00910   if (Arg < num_args1)
00911     return expr1.template isActive<Arg>();
00912   else
00913     return expr2.template isActive<Arg-num_args1>();
00914       }
00915 
00916       bool updateValue() const {
00917   return expr1.updateValue() && expr2.updateValue();
00918       }
00919 
00920       void cache() const {
00921   expr1.cache();
00922   expr2.cache();
00923       }
00924 
00925       value_type val() const {
00926   return expr1.val()-expr2.val();
00927       }
00928 
00929       void computePartials(const value_type& bar,
00930          value_type partials[]) const {
00931   if (num_args1 > 0)
00932     expr1.computePartials(bar, partials);
00933   if (num_args2 > 0)
00934     expr2.computePartials(-bar, partials+num_args1);
00935       }
00936 
00937       void getTangents(int i, value_type dots[]) const {
00938   expr1.getTangents(i, dots);
00939   expr2.getTangents(i, dots+num_args1);
00940       }
00941 
00942       template <int Arg> value_type getTangent(int i) const {
00943   if (Arg < num_args1)
00944     return expr1.template getTangent<Arg>(i);
00945   else
00946     return expr2.template getTangent<Arg-num_args1>(i);
00947       }
00948 
00949       bool isLinear() const {
00950         return expr1.isLinear() && expr2.isLinear();
00951       }
00952 
00953       bool hasFastAccess() const {
00954         return expr1.hasFastAccess() && expr2.hasFastAccess();
00955       }
00956 
00957       const value_type dx(int i) const {
00958         return expr1.dx(i) - expr2.dx(i);
00959       }
00960 
00961       const value_type fastAccessDx(int i) const {
00962         return expr1.fastAccessDx(i) - expr2.fastAccessDx(i);
00963       }
00964 
00965       const base_expr_type& getArg(int j) const {
00966   if (j < num_args1)
00967     return expr1.getArg(j);
00968   else
00969     return expr2.getArg(j-num_args1);
00970       }
00971 
00972     protected:
00973 
00974       const ExprT1& expr1;
00975       const ExprT2& expr2;
00976 
00977     };
00978 
00979     template <typename ExprT1, typename T2>
00980     class Expr< SubtractionOp<ExprT1, ConstExpr<T2> > > {
00981 
00982     public:
00983 
00984       typedef ConstExpr<T2> ExprT2;
00985       typedef typename ExprT1::value_type value_type_1;
00986       typedef typename ExprT2::value_type value_type_2;
00987       typedef typename Sacado::Promote<value_type_1,
00988                value_type_2>::type value_type;
00989       typedef typename ExprT1::scalar_type scalar_type_1;
00990       typedef typename ExprT2::scalar_type scalar_type_2;
00991       typedef typename Sacado::Promote<scalar_type_1,
00992                scalar_type_2>::type scalar_type;
00993 
00994       typedef typename ExprT1::base_expr_type base_expr_type_1;
00995       typedef typename ExprT2::base_expr_type base_expr_type_2;
00996       typedef typename ExprPromote<base_expr_type_1,
00997            base_expr_type_2>::type base_expr_type;
00998 
00999       static const int num_args = ExprT1::num_args;
01000 
01001       static const bool is_linear = ExprT1::is_linear;
01002 
01003       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01004   expr1(expr1_), expr2(expr2_) {}
01005 
01006       int size() const {
01007   return expr1.size();
01008       }
01009 
01010       template <int Arg> bool isActive() const {
01011   return expr1.template isActive<Arg>();
01012       }
01013 
01014       bool updateValue() const {
01015   return expr1.updateValue();
01016       }
01017 
01018       void cache() const {
01019   expr1.cache();
01020       }
01021 
01022       value_type val() const {
01023   return expr1.val() - expr2.val();
01024       }
01025 
01026       void computePartials(const value_type& bar,
01027          value_type partials[]) const {
01028   expr1.computePartials(bar, partials);
01029       }
01030 
01031       void getTangents(int i, value_type dots[]) const {
01032   expr1.getTangents(i, dots);
01033       }
01034 
01035       template <int Arg> value_type getTangent(int i) const {
01036   return expr1.template getTangent<Arg>(i);
01037       }
01038 
01039       bool isLinear() const {
01040         return expr1.isLinear();
01041       }
01042 
01043       bool hasFastAccess() const {
01044         return expr1.hasFastAccess();
01045       }
01046 
01047       const value_type dx(int i) const {
01048         return expr1.dx(i);
01049       }
01050 
01051       const value_type fastAccessDx(int i) const {
01052         return expr1.fastAccessDx(i);
01053       }
01054 
01055       const base_expr_type& getArg(int j) const {
01056   return expr1.getArg(j);
01057       }
01058 
01059     protected:
01060 
01061       const ExprT1& expr1;
01062       ExprT2 expr2;
01063 
01064     };
01065 
01066     template <typename T1, typename ExprT2>
01067     class Expr< SubtractionOp< ConstExpr<T1>,ExprT2> > {
01068 
01069     public:
01070 
01071       typedef ConstExpr<T1> ExprT1;
01072       typedef typename ExprT1::value_type value_type_1;
01073       typedef typename ExprT2::value_type value_type_2;
01074       typedef typename Sacado::Promote<value_type_1,
01075                value_type_2>::type value_type;
01076       typedef typename ExprT1::scalar_type scalar_type_1;
01077       typedef typename ExprT2::scalar_type scalar_type_2;
01078       typedef typename Sacado::Promote<scalar_type_1,
01079                scalar_type_2>::type scalar_type;
01080 
01081       typedef typename ExprT1::base_expr_type base_expr_type_1;
01082       typedef typename ExprT2::base_expr_type base_expr_type_2;
01083       typedef typename ExprPromote<base_expr_type_1,
01084            base_expr_type_2>::type base_expr_type;
01085 
01086       static const int num_args = ExprT2::num_args;
01087 
01088       static const bool is_linear = ExprT2::is_linear;
01089 
01090       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01091   expr1(expr1_), expr2(expr2_) {}
01092 
01093       int size() const {
01094   return expr2.size();
01095       }
01096 
01097       template <int Arg> bool isActive() const {
01098   return expr2.template isActive<Arg>();
01099       }
01100 
01101       bool updateValue() const {
01102   return expr2.updateValue();
01103       }
01104 
01105       void cache() const {
01106   expr2.cache();
01107       }
01108 
01109       value_type val() const {
01110   return expr1.val() - expr2.val();
01111       }
01112 
01113       void computePartials(const value_type& bar,
01114          value_type partials[]) const {
01115   expr2.computePartials(-bar, partials);
01116       }
01117 
01118       void getTangents(int i, value_type dots[]) const {
01119   expr2.getTangents(i, dots);
01120       }
01121 
01122       template <int Arg> value_type getTangent(int i) const {
01123   return expr2.template getTangent<Arg>(i);
01124       }
01125 
01126       bool isLinear() const {
01127         return expr2.isLinear();
01128       }
01129 
01130       bool hasFastAccess() const {
01131         return expr2.hasFastAccess();
01132       }
01133 
01134       const value_type dx(int i) const {
01135         return -expr2.dx(i);
01136       }
01137 
01138       const value_type fastAccessDx(int i) const {
01139         return -expr2.fastAccessDx(i);
01140       }
01141 
01142       const base_expr_type& getArg(int j) const {
01143   return expr2.getArg(j);
01144       }
01145 
01146     protected:
01147 
01148       ExprT1 expr1;
01149       const ExprT2& expr2;
01150 
01151     };
01152 
01153     //
01154     // MultiplicationOp
01155     //
01156 
01157     template <typename ExprT1, typename ExprT2>
01158     class MultiplicationOp {};
01159 
01160     template <typename ExprT1, typename ExprT2>
01161     class Expr< MultiplicationOp<ExprT1,ExprT2> > {
01162 
01163     public:
01164 
01165       typedef typename ExprT1::value_type value_type_1;
01166       typedef typename ExprT2::value_type value_type_2;
01167       typedef typename Sacado::Promote<value_type_1,
01168                value_type_2>::type value_type;
01169       typedef typename ExprT1::scalar_type scalar_type_1;
01170       typedef typename ExprT2::scalar_type scalar_type_2;
01171       typedef typename Sacado::Promote<scalar_type_1,
01172                scalar_type_2>::type scalar_type;
01173 
01174       typedef typename ExprT1::base_expr_type base_expr_type_1;
01175       typedef typename ExprT2::base_expr_type base_expr_type_2;
01176       typedef typename ExprPromote<base_expr_type_1,
01177            base_expr_type_2>::type base_expr_type;
01178 
01179       static const int num_args1 = ExprT1::num_args;
01180       static const int num_args2 = ExprT2::num_args;
01181       static const int num_args = num_args1 + num_args2;
01182 
01183       static const bool is_linear = false;
01184 
01185       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01186   expr1(expr1_), expr2(expr2_) {}
01187 
01188       int size() const {
01189   int sz1 = expr1.size(), sz2 = expr2.size();
01190   return sz1 > sz2 ? sz1 : sz2;
01191       }
01192 
01193       template <int Arg> bool isActive() const {
01194   if (Arg < num_args1)
01195     return expr1.template isActive<Arg>();
01196   else
01197     return expr2.template isActive<Arg-num_args1>();
01198       }
01199 
01200       bool updateValue() const {
01201   return expr1.updateValue() && expr2.updateValue();
01202       }
01203 
01204       void cache() const {
01205   expr1.cache();
01206   expr2.cache();
01207         v1 = expr1.val();
01208   v2 = expr2.val();
01209       }
01210 
01211       value_type val() const {
01212   return v1*v2;
01213       }
01214 
01215       void computePartials(const value_type& bar,
01216          value_type partials[]) const {
01217   if (num_args1 > 0)
01218     expr1.computePartials(bar*v2, partials);
01219   if (num_args2 > 0)
01220     expr2.computePartials(bar*v1, partials+num_args1);
01221       }
01222 
01223       void getTangents(int i, value_type dots[]) const {
01224   expr1.getTangents(i, dots);
01225   expr2.getTangents(i, dots+num_args1);
01226       }
01227 
01228       template <int Arg> value_type getTangent(int i) const {
01229   if (Arg < num_args1)
01230     return expr1.template getTangent<Arg>(i);
01231   else
01232     return expr2.template getTangent<Arg-num_args1>(i);
01233       }
01234 
01235       bool isLinear() const {
01236         return false;
01237       }
01238 
01239       bool hasFastAccess() const {
01240         return expr1.hasFastAccess() && expr2.hasFastAccess();
01241       }
01242 
01243       const value_type dx(int i) const {
01244         if (expr1.size() > 0 && expr2.size() > 0)
01245     return v1*expr2.dx(i) + expr1.dx(i)*v2;
01246   else if (expr1.size() > 0)
01247     return expr1.dx(i)*v2;
01248   else
01249     return v1*expr2.dx(i);
01250       }
01251 
01252       const value_type fastAccessDx(int i) const {
01253         return v1*expr2.fastAccessDx(i) + expr1.fastAccessDx(i)*v2;
01254       }
01255 
01256       const base_expr_type& getArg(int j) const {
01257   if (j < num_args1)
01258     return expr1.getArg(j);
01259   else
01260     return expr2.getArg(j-num_args1);
01261       }
01262 
01263     protected:
01264 
01265       const ExprT1& expr1;
01266       const ExprT2& expr2;
01267       mutable value_type_1 v1;
01268       mutable value_type_2 v2;
01269 
01270     };
01271 
01272     template <typename ExprT1, typename T2>
01273     class Expr< MultiplicationOp<ExprT1, ConstExpr<T2> > > {
01274 
01275     public:
01276 
01277       typedef ConstExpr<T2> ExprT2;
01278       typedef typename ExprT1::value_type value_type_1;
01279       typedef typename ExprT2::value_type value_type_2;
01280       typedef typename Sacado::Promote<value_type_1,
01281                value_type_2>::type value_type;
01282       typedef typename ExprT1::scalar_type scalar_type_1;
01283       typedef typename ExprT2::scalar_type scalar_type_2;
01284       typedef typename Sacado::Promote<scalar_type_1,
01285                scalar_type_2>::type scalar_type;
01286 
01287       typedef typename ExprT1::base_expr_type base_expr_type_1;
01288       typedef typename ExprT2::base_expr_type base_expr_type_2;
01289       typedef typename ExprPromote<base_expr_type_1,
01290            base_expr_type_2>::type base_expr_type;
01291 
01292       static const int num_args = ExprT1::num_args;
01293 
01294       static const bool is_linear = ExprT1::is_linear;
01295 
01296       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01297   expr1(expr1_), expr2(expr2_) {}
01298 
01299       int size() const {
01300   return expr1.size();
01301       }
01302 
01303       template <int Arg> bool isActive() const {
01304   return expr1.template isActive<Arg>();
01305       }
01306 
01307       bool updateValue() const {
01308   return expr1.updateValue();
01309       }
01310 
01311       void cache() const {
01312   expr1.cache();
01313       }
01314 
01315       value_type val() const {
01316   return expr1.val()*expr2.val();
01317       }
01318 
01319       void computePartials(const value_type& bar,
01320          value_type partials[]) const {
01321   expr1.computePartials(bar*expr2.val(), partials);
01322       }
01323 
01324       void getTangents(int i, value_type dots[]) const {
01325   expr1.getTangents(i, dots);
01326       }
01327 
01328       template <int Arg> value_type getTangent(int i) const {
01329   return expr1.template getTangent<Arg>(i);
01330       }
01331 
01332       bool isLinear() const {
01333         return expr1.isLinear();
01334       }
01335 
01336       bool hasFastAccess() const {
01337         return expr1.hasFastAccess();
01338       }
01339 
01340       const value_type dx(int i) const {
01341         return expr1.dx(i)*expr2.val();
01342       }
01343 
01344       const value_type fastAccessDx(int i) const {
01345         return expr1.fastAccessDx(i)*expr2.val();
01346       }
01347 
01348       const base_expr_type& getArg(int j) const {
01349   return expr1.getArg(j);
01350       }
01351 
01352     protected:
01353 
01354       const ExprT1& expr1;
01355       ExprT2 expr2;
01356 
01357     };
01358 
01359     template <typename T1, typename ExprT2>
01360     class Expr< MultiplicationOp< ConstExpr<T1>,ExprT2> > {
01361 
01362     public:
01363 
01364       typedef ConstExpr<T1> ExprT1;
01365       typedef typename ExprT1::value_type value_type_1;
01366       typedef typename ExprT2::value_type value_type_2;
01367       typedef typename Sacado::Promote<value_type_1,
01368                value_type_2>::type value_type;
01369       typedef typename ExprT1::scalar_type scalar_type_1;
01370       typedef typename ExprT2::scalar_type scalar_type_2;
01371       typedef typename Sacado::Promote<scalar_type_1,
01372                scalar_type_2>::type scalar_type;
01373 
01374       typedef typename ExprT1::base_expr_type base_expr_type_1;
01375       typedef typename ExprT2::base_expr_type base_expr_type_2;
01376       typedef typename ExprPromote<base_expr_type_1,
01377            base_expr_type_2>::type base_expr_type;
01378 
01379       static const int num_args = ExprT2::num_args;
01380 
01381       static const bool is_linear = ExprT2::is_linear;
01382 
01383       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01384   expr1(expr1_), expr2(expr2_) {}
01385 
01386       int size() const {
01387   return expr2.size();
01388       }
01389 
01390       template <int Arg> bool isActive() const {
01391   return expr2.template isActive<Arg>();
01392       }
01393 
01394       bool updateValue() const {
01395   return expr2.updateValue();
01396       }
01397 
01398       void cache() const {
01399   expr2.cache();
01400       }
01401 
01402       value_type val() const {
01403   return expr1.val()*expr2.val();
01404       }
01405 
01406       void computePartials(const value_type& bar,
01407          value_type partials[]) const {
01408   expr2.computePartials(bar*expr1.val(), partials);
01409       }
01410 
01411       void getTangents(int i, value_type dots[]) const {
01412   expr2.getTangents(i, dots);
01413       }
01414 
01415       template <int Arg> value_type getTangent(int i) const {
01416   return expr2.template getTangent<Arg>(i);
01417       }
01418 
01419       bool isLinear() const {
01420         return expr2.isLinear();
01421       }
01422 
01423       bool hasFastAccess() const {
01424         return expr2.hasFastAccess();
01425       }
01426 
01427       const value_type dx(int i) const {
01428         return expr1.val()*expr2.dx(i);
01429       }
01430 
01431       const value_type fastAccessDx(int i) const {
01432         return expr1.val()*expr2.fastAccessDx(i);
01433       }
01434 
01435       const base_expr_type& getArg(int j) const {
01436   return expr2.getArg(j);
01437       }
01438 
01439     protected:
01440 
01441       ExprT1 expr1;
01442       const ExprT2& expr2;
01443 
01444     };
01445 
01446     //
01447     // DivisionOp
01448     //
01449 
01450     template <typename ExprT1, typename ExprT2>
01451     class DivisionOp {};
01452 
01453     template <typename ExprT1, typename ExprT2>
01454     class Expr< DivisionOp<ExprT1,ExprT2> > {
01455 
01456     public:
01457 
01458       typedef typename ExprT1::value_type value_type_1;
01459       typedef typename ExprT2::value_type value_type_2;
01460       typedef typename Sacado::Promote<value_type_1,
01461                value_type_2>::type value_type;
01462       typedef typename ExprT1::scalar_type scalar_type_1;
01463       typedef typename ExprT2::scalar_type scalar_type_2;
01464       typedef typename Sacado::Promote<scalar_type_1,
01465                scalar_type_2>::type scalar_type;
01466 
01467       typedef typename ExprT1::base_expr_type base_expr_type_1;
01468       typedef typename ExprT2::base_expr_type base_expr_type_2;
01469       typedef typename ExprPromote<base_expr_type_1,
01470            base_expr_type_2>::type base_expr_type;
01471 
01472       static const int num_args1 = ExprT1::num_args;
01473       static const int num_args2 = ExprT2::num_args;
01474       static const int num_args = num_args1 + num_args2;
01475 
01476       static const bool is_linear = false;
01477 
01478       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01479   expr1(expr1_), expr2(expr2_) {}
01480 
01481       int size() const {
01482   int sz1 = expr1.size(), sz2 = expr2.size();
01483   return sz1 > sz2 ? sz1 : sz2;
01484       }
01485 
01486       template <int Arg> bool isActive() const {
01487   if (Arg < num_args1)
01488     return expr1.template isActive<Arg>();
01489   else
01490     return expr2.template isActive<Arg-num_args1>();
01491       }
01492 
01493       bool updateValue() const {
01494   return expr1.updateValue() && expr2.updateValue();
01495       }
01496 
01497       void cache() const {
01498   expr1.cache();
01499   expr2.cache();
01500         const value_type_1 v1 = expr1.val();
01501   const value_type_2 v2 = expr2.val();
01502   a = scalar_type(1.0)/v2;
01503   v = v1*a;
01504   b = -v/v2;
01505       }
01506 
01507       value_type val() const {
01508   return v;
01509       }
01510 
01511       void computePartials(const value_type& bar,
01512          value_type partials[]) const {
01513   if (num_args1 > 0)
01514     expr1.computePartials(bar*a, partials);
01515   if (num_args2 > 0)
01516     expr2.computePartials(bar*b, partials+num_args1);
01517       }
01518 
01519       void getTangents(int i, value_type dots[]) const {
01520   expr1.getTangents(i, dots);
01521   expr2.getTangents(i, dots+num_args1);
01522       }
01523 
01524       template <int Arg> value_type getTangent(int i) const {
01525   if (Arg < num_args1)
01526     return expr1.template getTangent<Arg>(i);
01527   else
01528     return expr2.template getTangent<Arg-num_args1>(i);
01529       }
01530 
01531       bool isLinear() const {
01532         return false;
01533       }
01534 
01535       bool hasFastAccess() const {
01536         return expr1.hasFastAccess() && expr2.hasFastAccess();
01537       }
01538 
01539       const value_type dx(int i) const {
01540   if (expr1.size() > 0 && expr2.size() > 0)
01541     return expr1.dx(i)*a + expr2.dx(i)*b;
01542   else if (expr1.size() > 0)
01543     return expr1.dx(i)*a;
01544   else
01545     return expr1.val()*b;
01546       }
01547 
01548       const value_type fastAccessDx(int i) const {
01549         return  expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
01550       }
01551 
01552       const base_expr_type& getArg(int j) const {
01553   if (j < num_args1)
01554     return expr1.getArg(j);
01555   else
01556     return expr2.getArg(j-num_args1);
01557       }
01558 
01559     protected:
01560 
01561       const ExprT1& expr1;
01562       const ExprT2& expr2;
01563       mutable value_type v;
01564       mutable value_type a;
01565       mutable value_type b;
01566 
01567     };
01568 
01569     template <typename ExprT1, typename T2>
01570     class Expr< DivisionOp<ExprT1, ConstExpr<T2> > > {
01571 
01572     public:
01573 
01574       typedef ConstExpr<T2> ExprT2;
01575       typedef typename ExprT1::value_type value_type_1;
01576       typedef typename ExprT2::value_type value_type_2;
01577       typedef typename Sacado::Promote<value_type_1,
01578                value_type_2>::type value_type;
01579       typedef typename ExprT1::scalar_type scalar_type_1;
01580       typedef typename ExprT2::scalar_type scalar_type_2;
01581       typedef typename Sacado::Promote<scalar_type_1,
01582                scalar_type_2>::type scalar_type;
01583 
01584       typedef typename ExprT1::base_expr_type base_expr_type_1;
01585       typedef typename ExprT2::base_expr_type base_expr_type_2;
01586       typedef typename ExprPromote<base_expr_type_1,
01587            base_expr_type_2>::type base_expr_type;
01588 
01589       static const int num_args = ExprT1::num_args;
01590 
01591       static const bool is_linear = ExprT1::is_linear;
01592 
01593       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01594   expr1(expr1_), expr2(expr2_) {}
01595 
01596       int size() const {
01597   return expr1.size();
01598       }
01599 
01600       template <int Arg> bool isActive() const {
01601   return expr1.template isActive<Arg>();
01602       }
01603 
01604       bool updateValue() const {
01605   return expr1.updateValue();
01606       }
01607 
01608       void cache() const {
01609   expr1.cache();
01610   const value_type_1 v1 = expr1.val();
01611   a = scalar_type(1.0)/expr2.val();
01612   v = v1*a;
01613       }
01614 
01615       value_type val() const {
01616   return v;
01617       }
01618 
01619       void computePartials(const value_type& bar,
01620          value_type partials[]) const {
01621   expr1.computePartials(bar*a, partials);
01622       }
01623 
01624       void getTangents(int i, value_type dots[]) const {
01625   expr1.getTangents(i, dots);
01626       }
01627 
01628       template <int Arg> value_type getTangent(int i) const {
01629   return expr1.template getTangent<Arg>(i);
01630       }
01631 
01632       bool isLinear() const {
01633         return expr1.isLinear();
01634       }
01635 
01636       bool hasFastAccess() const {
01637         return expr1.hasFastAccess();
01638       }
01639 
01640       const value_type dx(int i) const {
01641         return expr1.dx(i)*a;
01642       }
01643 
01644       const value_type fastAccessDx(int i) const {
01645         return expr1.fastAccessDx(i)*a;
01646       }
01647 
01648       const base_expr_type& getArg(int j) const {
01649   return expr1.getArg(j);
01650       }
01651 
01652     protected:
01653 
01654       const ExprT1& expr1;
01655       ExprT2 expr2;
01656       mutable value_type v;
01657       mutable value_type a;
01658 
01659     };
01660 
01661     template <typename T1, typename ExprT2>
01662     class Expr< DivisionOp< ConstExpr<T1>,ExprT2> > {
01663 
01664     public:
01665 
01666       typedef ConstExpr<T1> ExprT1;
01667       typedef typename ExprT1::value_type value_type_1;
01668       typedef typename ExprT2::value_type value_type_2;
01669       typedef typename Sacado::Promote<value_type_1,
01670                value_type_2>::type value_type;
01671       typedef typename ExprT1::scalar_type scalar_type_1;
01672       typedef typename ExprT2::scalar_type scalar_type_2;
01673       typedef typename Sacado::Promote<scalar_type_1,
01674                scalar_type_2>::type scalar_type;
01675 
01676       typedef typename ExprT1::base_expr_type base_expr_type_1;
01677       typedef typename ExprT2::base_expr_type base_expr_type_2;
01678       typedef typename ExprPromote<base_expr_type_1,
01679            base_expr_type_2>::type base_expr_type;
01680 
01681       static const int num_args = ExprT2::num_args;
01682 
01683       static const bool is_linear = false;
01684 
01685       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01686   expr1(expr1_), expr2(expr2_) {}
01687 
01688       int size() const {
01689   return expr2.size();
01690       }
01691 
01692       template <int Arg> bool isActive() const {
01693   return expr2.template isActive<Arg>();
01694       }
01695 
01696       bool updateValue() const {
01697   return expr2.updateValue();
01698       }
01699 
01700       void cache() const {
01701   expr2.cache();
01702   const value_type_2 v2 = expr2.val();
01703   v = expr1.val()/v2;
01704   b = -v/v2;
01705       }
01706 
01707       value_type val() const {
01708   return v;
01709       }
01710 
01711       void computePartials(const value_type& bar,
01712          value_type partials[]) const {
01713   expr2.computePartials(bar*b, partials);
01714       }
01715 
01716       void getTangents(int i, value_type dots[]) const {
01717   expr2.getTangents(i, dots);
01718       }
01719 
01720       template <int Arg> value_type getTangent(int i) const {
01721   return expr2.template getTangent<Arg>(i);
01722       }
01723 
01724       bool isLinear() const {
01725         return false;
01726       }
01727 
01728       bool hasFastAccess() const {
01729         return expr2.hasFastAccess();
01730       }
01731 
01732       const value_type dx(int i) const {
01733         return expr2.dx(i)*b;
01734       }
01735 
01736       const value_type fastAccessDx(int i) const {
01737         return expr2.fastAccessDx(i)*b;
01738       }
01739 
01740       const base_expr_type& getArg(int j) const {
01741   return expr2.getArg(j);
01742       }
01743 
01744     protected:
01745 
01746       ExprT1 expr1;
01747       const ExprT2& expr2;
01748       mutable value_type v;
01749       mutable value_type b;
01750 
01751     };
01752 
01753     //
01754     // Atan2Op
01755     //
01756 
01757     template <typename ExprT1, typename ExprT2>
01758     class Atan2Op {};
01759 
01760     template <typename ExprT1, typename ExprT2>
01761     class Expr< Atan2Op<ExprT1,ExprT2> > {
01762 
01763     public:
01764 
01765       typedef typename ExprT1::value_type value_type_1;
01766       typedef typename ExprT2::value_type value_type_2;
01767       typedef typename Sacado::Promote<value_type_1,
01768                value_type_2>::type value_type;
01769       typedef typename ExprT1::scalar_type scalar_type_1;
01770       typedef typename ExprT2::scalar_type scalar_type_2;
01771       typedef typename Sacado::Promote<scalar_type_1,
01772                scalar_type_2>::type scalar_type;
01773 
01774       typedef typename ExprT1::base_expr_type base_expr_type_1;
01775       typedef typename ExprT2::base_expr_type base_expr_type_2;
01776       typedef typename ExprPromote<base_expr_type_1,
01777            base_expr_type_2>::type base_expr_type;
01778 
01779       static const int num_args1 = ExprT1::num_args;
01780       static const int num_args2 = ExprT2::num_args;
01781       static const int num_args = num_args1 + num_args2;
01782 
01783       static const bool is_linear = false;
01784 
01785       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01786   expr1(expr1_), expr2(expr2_) {}
01787 
01788       int size() const {
01789   int sz1 = expr1.size(), sz2 = expr2.size();
01790   return sz1 > sz2 ? sz1 : sz2;
01791       }
01792 
01793       template <int Arg> bool isActive() const {
01794   if (Arg < num_args1)
01795     return expr1.template isActive<Arg>();
01796   else
01797     return expr2.template isActive<Arg-num_args1>();
01798       }
01799 
01800       bool updateValue() const {
01801   return expr1.updateValue() && expr2.updateValue();
01802       }
01803 
01804       void cache() const {
01805   expr1.cache();
01806   expr2.cache();
01807         const value_type_1 v1 = expr1.val();
01808   const value_type_2 v2 = expr2.val();
01809   a = scalar_type(1.0)/(v1*v1 + v2*v2);
01810   b = -v1*a;
01811   a = v2*a;
01812   v = std::atan2(v1,v2);
01813       }
01814 
01815       value_type val() const {
01816   return v;
01817       }
01818 
01819       void computePartials(const value_type& bar,
01820          value_type partials[]) const {
01821   if (num_args1 > 0)
01822     expr1.computePartials(bar*a, partials);
01823   if (num_args2 > 0)
01824     expr2.computePartials(bar*b, partials+num_args1);
01825       }
01826 
01827       void getTangents(int i, value_type dots[]) const {
01828   expr1.getTangents(i, dots);
01829   expr2.getTangents(i, dots+num_args1);
01830       }
01831 
01832       template <int Arg> value_type getTangent(int i) const {
01833   if (Arg < num_args1)
01834     return expr1.template getTangent<Arg>(i);
01835   else
01836     return expr2.template getTangent<Arg-num_args1>(i);
01837       }
01838 
01839       bool isLinear() const {
01840         return false;
01841       }
01842 
01843       bool hasFastAccess() const {
01844         return expr1.hasFastAccess() && expr2.hasFastAccess();
01845       }
01846 
01847       const value_type dx(int i) const {
01848         if (expr1.size() > 0 && expr2.size() > 0)
01849     return expr1.dx(i)*a + expr2.dx(i)*b;
01850   else if (expr1.size() > 0)
01851     return expr1.dx(i)*a;
01852   else
01853     return expr1.val()*b;
01854       }
01855 
01856       const value_type fastAccessDx(int i) const {
01857         return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
01858       }
01859 
01860       const base_expr_type& getArg(int j) const {
01861   if (j < num_args1)
01862     return expr1.getArg(j);
01863   else
01864     return expr2.getArg(j-num_args1);
01865       }
01866 
01867     protected:
01868 
01869       const ExprT1& expr1;
01870       const ExprT2& expr2;
01871       mutable value_type v;
01872       mutable value_type a;
01873       mutable value_type b;
01874 
01875     };
01876 
01877     template <typename ExprT1, typename T2>
01878     class Expr< Atan2Op<ExprT1, ConstExpr<T2> > > {
01879 
01880     public:
01881 
01882       typedef ConstExpr<T2> ExprT2;
01883       typedef typename ExprT1::value_type value_type_1;
01884       typedef typename ExprT2::value_type value_type_2;
01885       typedef typename Sacado::Promote<value_type_1,
01886                value_type_2>::type value_type;
01887       typedef typename ExprT1::scalar_type scalar_type_1;
01888       typedef typename ExprT2::scalar_type scalar_type_2;
01889       typedef typename Sacado::Promote<scalar_type_1,
01890                scalar_type_2>::type scalar_type;
01891 
01892       typedef typename ExprT1::base_expr_type base_expr_type_1;
01893       typedef typename ExprT2::base_expr_type base_expr_type_2;
01894       typedef typename ExprPromote<base_expr_type_1,
01895            base_expr_type_2>::type base_expr_type;
01896 
01897       static const int num_args = ExprT1::num_args;
01898 
01899       static const bool is_linear = false;
01900 
01901       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01902   expr1(expr1_), expr2(expr2_) {}
01903 
01904       int size() const {
01905   return expr1.size();
01906       }
01907 
01908       template <int Arg> bool isActive() const {
01909   return expr1.template isActive<Arg>();
01910       }
01911 
01912       bool updateValue() const {
01913   return expr1.updateValue();
01914       }
01915 
01916       void cache() const {
01917   expr1.cache();
01918   const value_type_1 v1 = expr1.val();
01919   const value_type_2 v2 = expr2.val();
01920   a = v2/(v1*v1 + v2*v2);
01921   v = std::atan2(v1,v2);
01922       }
01923 
01924       value_type val() const {
01925   return v;
01926       }
01927 
01928       void computePartials(const value_type& bar,
01929          value_type partials[]) const {
01930   expr1.computePartials(bar*a, partials);
01931       }
01932 
01933       void getTangents(int i, value_type dots[]) const {
01934   expr1.getTangents(i, dots);
01935       }
01936 
01937       template <int Arg> value_type getTangent(int i) const {
01938   return expr1.template getTangent<Arg>(i);
01939       }
01940 
01941       bool isLinear() const {
01942         return false;
01943       }
01944 
01945       bool hasFastAccess() const {
01946         return expr1.hasFastAccess();
01947       }
01948 
01949       const value_type dx(int i) const {
01950         return expr1.dx(i)*a;
01951       }
01952 
01953       const value_type fastAccessDx(int i) const {
01954         return expr1.fastAccessDx(i)*a;
01955       }
01956 
01957       const base_expr_type& getArg(int j) const {
01958   return expr1.getArg(j);
01959       }
01960 
01961     protected:
01962 
01963       const ExprT1& expr1;
01964       ExprT2 expr2;
01965       mutable value_type v;
01966       mutable value_type a;
01967 
01968     };
01969 
01970     template <typename T1, typename ExprT2>
01971     class Expr< Atan2Op< ConstExpr<T1>,ExprT2> > {
01972 
01973     public:
01974 
01975       typedef ConstExpr<T1> ExprT1;
01976       typedef typename ExprT1::value_type value_type_1;
01977       typedef typename ExprT2::value_type value_type_2;
01978       typedef typename Sacado::Promote<value_type_1,
01979                value_type_2>::type value_type;
01980       typedef typename ExprT1::scalar_type scalar_type_1;
01981       typedef typename ExprT2::scalar_type scalar_type_2;
01982       typedef typename Sacado::Promote<scalar_type_1,
01983                scalar_type_2>::type scalar_type;
01984 
01985       typedef typename ExprT1::base_expr_type base_expr_type_1;
01986       typedef typename ExprT2::base_expr_type base_expr_type_2;
01987       typedef typename ExprPromote<base_expr_type_1,
01988            base_expr_type_2>::type base_expr_type;
01989 
01990       static const int num_args = ExprT2::num_args;
01991 
01992       static const bool is_linear = false;
01993 
01994       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
01995   expr1(expr1_), expr2(expr2_) {}
01996 
01997       int size() const {
01998   return expr2.size();
01999       }
02000 
02001       template <int Arg> bool isActive() const {
02002   return expr2.template isActive<Arg>();
02003       }
02004 
02005       bool updateValue() const {
02006   return expr2.updateValue();
02007       }
02008 
02009       void cache() const {
02010   expr2.cache();
02011   const value_type_1 v1 = expr1.val();
02012   const value_type_2 v2 = expr2.val();
02013   b = -v1/(v1*v1 + v2*v2);
02014   v = std::atan2(v1,v2);
02015       }
02016 
02017       value_type val() const {
02018   return v;
02019       }
02020 
02021       void computePartials(const value_type& bar,
02022          value_type partials[]) const {
02023   expr2.computePartials(bar*b, partials);
02024       }
02025 
02026       void getTangents(int i, value_type dots[]) const {
02027   expr2.getTangents(i, dots);
02028       }
02029 
02030       template <int Arg> value_type getTangent(int i) const {
02031   return expr2.template getTangent<Arg>(i);
02032       }
02033 
02034       bool isLinear() const {
02035         return false;
02036       }
02037 
02038       bool hasFastAccess() const {
02039         return expr2.hasFastAccess();
02040       }
02041 
02042       const value_type dx(int i) const {
02043         return expr2.dx(i)*b;
02044       }
02045 
02046       const value_type fastAccessDx(int i) const {
02047         return expr2.fastAccessDx(i)*b;
02048       }
02049 
02050       const base_expr_type& getArg(int j) const {
02051   return expr2.getArg(j);
02052       }
02053 
02054     protected:
02055 
02056       ExprT1 expr1;
02057       const ExprT2& expr2;
02058       mutable value_type v;
02059       mutable value_type b;
02060 
02061     };
02062 
02063     //
02064     // PowerOp
02065     //
02066 
02067     template <typename ExprT1, typename ExprT2>
02068     class PowerOp {};
02069 
02070     template <typename ExprT1, typename ExprT2>
02071     class Expr< PowerOp<ExprT1,ExprT2> > {
02072 
02073     public:
02074 
02075       typedef typename ExprT1::value_type value_type_1;
02076       typedef typename ExprT2::value_type value_type_2;
02077       typedef typename Sacado::Promote<value_type_1,
02078                value_type_2>::type value_type;
02079       typedef typename ExprT1::scalar_type scalar_type_1;
02080       typedef typename ExprT2::scalar_type scalar_type_2;
02081       typedef typename Sacado::Promote<scalar_type_1,
02082                scalar_type_2>::type scalar_type;
02083 
02084       typedef typename ExprT1::base_expr_type base_expr_type_1;
02085       typedef typename ExprT2::base_expr_type base_expr_type_2;
02086       typedef typename ExprPromote<base_expr_type_1,
02087            base_expr_type_2>::type base_expr_type;
02088 
02089       static const int num_args1 = ExprT1::num_args;
02090       static const int num_args2 = ExprT2::num_args;
02091       static const int num_args = num_args1 + num_args2;
02092 
02093       static const bool is_linear = false;
02094 
02095       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02096   expr1(expr1_), expr2(expr2_) {}
02097 
02098       int size() const {
02099   int sz1 = expr1.size(), sz2 = expr2.size();
02100   return sz1 > sz2 ? sz1 : sz2;
02101       }
02102 
02103       template <int Arg> bool isActive() const {
02104   if (Arg < num_args1)
02105     return expr1.template isActive<Arg>();
02106   else
02107     return expr2.template isActive<Arg-num_args1>();
02108       }
02109 
02110       bool updateValue() const {
02111   return expr1.updateValue() && expr2.updateValue();
02112       }
02113 
02114       void cache() const {
02115   expr1.cache();
02116   expr2.cache();
02117         const value_type_1 v1 = expr1.val();
02118   const value_type_2 v2 = expr2.val();
02119   v = std::pow(v1,v2);
02120   if (v1 == scalar_type(0.0)) {
02121     a = scalar_type(0.0);
02122     b = scalar_type(0.0);
02123   }
02124   else {
02125     a = v*v2/v1;
02126     b = v*std::log(v1);
02127   }
02128       }
02129 
02130       value_type val() const {
02131   return v;
02132       }
02133 
02134       void computePartials(const value_type& bar,
02135          value_type partials[]) const {
02136   if (num_args1 > 0)
02137     expr1.computePartials(bar*a, partials);
02138   if (num_args2 > 0)
02139     expr2.computePartials(bar*b, partials+num_args1);
02140       }
02141 
02142       void getTangents(int i, value_type dots[]) const {
02143   expr1.getTangents(i, dots);
02144   expr2.getTangents(i, dots+num_args1);
02145       }
02146 
02147       template <int Arg> value_type getTangent(int i) const {
02148   if (Arg < num_args1)
02149     return expr1.template getTangent<Arg>(i);
02150   else
02151     return expr2.template getTangent<Arg-num_args1>(i);
02152       }
02153 
02154       bool isLinear() const {
02155         return false;
02156       }
02157 
02158       bool hasFastAccess() const {
02159         return expr1.hasFastAccess() && expr2.hasFastAccess();
02160       }
02161 
02162       const value_type dx(int i) const {
02163         if (expr1.size() > 0 && expr2.size() > 0)
02164     return expr1.dx(i)*a + expr2.dx(i)*b;
02165   else if (expr1.size() > 0)
02166     return expr1.dx(i)*a;
02167   else
02168     return expr1.val()*b;
02169       }
02170 
02171       const value_type fastAccessDx(int i) const {
02172         return expr1.fastAccessDx(i)*a + expr2.fastAccessDx(i)*b;
02173       }
02174 
02175       const base_expr_type& getArg(int j) const {
02176   if (j < num_args1)
02177     return expr1.getArg(j);
02178   else
02179     return expr2.getArg(j-num_args1);
02180       }
02181 
02182     protected:
02183 
02184       const ExprT1& expr1;
02185       const ExprT2& expr2;
02186       mutable value_type v;
02187       mutable value_type a;
02188       mutable value_type b;
02189 
02190     };
02191 
02192     template <typename ExprT1, typename T2>
02193     class Expr< PowerOp<ExprT1, ConstExpr<T2> > > {
02194 
02195     public:
02196 
02197       typedef ConstExpr<T2> ExprT2;
02198       typedef typename ExprT1::value_type value_type_1;
02199       typedef typename ExprT2::value_type value_type_2;
02200       typedef typename Sacado::Promote<value_type_1,
02201                value_type_2>::type value_type;
02202       typedef typename ExprT1::scalar_type scalar_type_1;
02203       typedef typename ExprT2::scalar_type scalar_type_2;
02204       typedef typename Sacado::Promote<scalar_type_1,
02205                scalar_type_2>::type scalar_type;
02206 
02207       typedef typename ExprT1::base_expr_type base_expr_type_1;
02208       typedef typename ExprT2::base_expr_type base_expr_type_2;
02209       typedef typename ExprPromote<base_expr_type_1,
02210            base_expr_type_2>::type base_expr_type;
02211 
02212       static const int num_args = ExprT1::num_args;
02213 
02214       static const bool is_linear = false;
02215 
02216       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02217   expr1(expr1_), expr2(expr2_) {}
02218 
02219       int size() const {
02220   return expr1.size();
02221       }
02222 
02223       template <int Arg> bool isActive() const {
02224   return expr1.template isActive<Arg>();
02225       }
02226 
02227       bool updateValue() const {
02228   return expr1.updateValue();
02229       }
02230 
02231       void cache() const {
02232   expr1.cache();
02233   const value_type_1 v1 = expr1.val();
02234   const value_type_2 v2 = expr2.val();
02235   v = std::pow(v1,v2);
02236   if (v1 == scalar_type(0.0)) {
02237     a = scalar_type(0.0);
02238   }
02239   else {
02240     a = v*v2/v1;
02241   }
02242       }
02243 
02244       value_type val() const {
02245   return v;
02246       }
02247 
02248       void computePartials(const value_type& bar,
02249          value_type partials[]) const {
02250   expr1.computePartials(bar*a, partials);
02251       }
02252 
02253       void getTangents(int i, value_type dots[]) const {
02254   expr1.getTangents(i, dots);
02255       }
02256 
02257       template <int Arg> value_type getTangent(int i) const {
02258   return expr1.template getTangent<Arg>(i);
02259       }
02260 
02261       bool isLinear() const {
02262         return false;
02263       }
02264 
02265       bool hasFastAccess() const {
02266         return expr1.hasFastAccess();
02267       }
02268 
02269       const value_type dx(int i) const {
02270         return expr1.dx(i)*a;
02271       }
02272 
02273       const value_type fastAccessDx(int i) const {
02274         return expr1.fastAccessDx(i)*a;
02275       }
02276 
02277       const base_expr_type& getArg(int j) const {
02278   return expr1.getArg(j);
02279       }
02280 
02281     protected:
02282 
02283       const ExprT1& expr1;
02284       ExprT2 expr2;
02285       mutable value_type v;
02286       mutable value_type a;
02287 
02288     };
02289 
02290     template <typename T1, typename ExprT2>
02291     class Expr< PowerOp< ConstExpr<T1>,ExprT2> > {
02292 
02293     public:
02294 
02295       typedef ConstExpr<T1> ExprT1;
02296       typedef typename ExprT1::value_type value_type_1;
02297       typedef typename ExprT2::value_type value_type_2;
02298       typedef typename Sacado::Promote<value_type_1,
02299                value_type_2>::type value_type;
02300       typedef typename ExprT1::scalar_type scalar_type_1;
02301       typedef typename ExprT2::scalar_type scalar_type_2;
02302       typedef typename Sacado::Promote<scalar_type_1,
02303                scalar_type_2>::type scalar_type;
02304 
02305       typedef typename ExprT1::base_expr_type base_expr_type_1;
02306       typedef typename ExprT2::base_expr_type base_expr_type_2;
02307       typedef typename ExprPromote<base_expr_type_1,
02308            base_expr_type_2>::type base_expr_type;
02309 
02310       static const int num_args = ExprT2::num_args;
02311 
02312       static const bool is_linear = false;
02313 
02314       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02315   expr1(expr1_), expr2(expr2_) {}
02316 
02317       int size() const {
02318   return expr2.size();
02319       }
02320 
02321       template <int Arg> bool isActive() const {
02322   return expr2.template isActive<Arg>();
02323       }
02324 
02325       bool updateValue() const {
02326   return expr2.updateValue();
02327       }
02328 
02329       void cache() const {
02330   expr2.cache();
02331   const value_type_1 v1 = expr1.val();
02332   const value_type_2 v2 = expr2.val();
02333   v = std::pow(v1,v2);
02334   if (v1 == scalar_type(0.0)) {
02335     b = scalar_type(0.0);
02336   }
02337   else {
02338     b = v*std::log(v1);
02339   }
02340       }
02341 
02342       value_type val() const {
02343   return v;
02344       }
02345 
02346       void computePartials(const value_type& bar,
02347          value_type partials[]) const {
02348   expr2.computePartials(bar*b, partials);
02349       }
02350 
02351       void getTangents(int i, value_type dots[]) const {
02352   expr2.getTangents(i, dots);
02353       }
02354 
02355       template <int Arg> value_type getTangent(int i) const {
02356   return expr2.template getTangent<Arg>(i);
02357       }
02358 
02359       bool isLinear() const {
02360         return false;
02361       }
02362 
02363       bool hasFastAccess() const {
02364         return expr2.hasFastAccess();
02365       }
02366 
02367       const value_type dx(int i) const {
02368         return expr2.dx(i)*b;
02369       }
02370 
02371       const value_type fastAccessDx(int i) const {
02372         return expr2.fastAccessDx(i)*b;
02373       }
02374 
02375       const base_expr_type& getArg(int j) const {
02376   return expr2.getArg(j);
02377       }
02378 
02379     protected:
02380 
02381       ExprT1 expr1;
02382       const ExprT2& expr2;
02383       mutable value_type v;
02384       mutable value_type b;
02385 
02386     };
02387 
02388     //
02389     // MaxOp
02390     //
02391 
02392     template <typename ExprT1, typename ExprT2>
02393     class MaxOp {};
02394 
02395     template <typename ExprT1, typename ExprT2>
02396     class Expr< MaxOp<ExprT1,ExprT2> > {
02397 
02398     public:
02399 
02400       typedef typename ExprT1::value_type value_type_1;
02401       typedef typename ExprT2::value_type value_type_2;
02402       typedef typename Sacado::Promote<value_type_1,
02403                value_type_2>::type value_type;
02404       typedef typename ExprT1::scalar_type scalar_type_1;
02405       typedef typename ExprT2::scalar_type scalar_type_2;
02406       typedef typename Sacado::Promote<scalar_type_1,
02407                scalar_type_2>::type scalar_type;
02408 
02409       typedef typename ExprT1::base_expr_type base_expr_type_1;
02410       typedef typename ExprT2::base_expr_type base_expr_type_2;
02411       typedef typename ExprPromote<base_expr_type_1,
02412            base_expr_type_2>::type base_expr_type;
02413 
02414       static const int num_args1 = ExprT1::num_args;
02415       static const int num_args2 = ExprT2::num_args;
02416       static const int num_args = num_args1 + num_args2;
02417 
02418       static const bool is_linear = false;
02419 
02420       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02421   expr1(expr1_), expr2(expr2_) {}
02422 
02423       int size() const {
02424   int sz1 = expr1.size(), sz2 = expr2.size();
02425   return sz1 > sz2 ? sz1 : sz2;
02426       }
02427 
02428       template <int Arg> bool isActive() const {
02429   if (Arg < num_args1)
02430     return expr1.template isActive<Arg>();
02431   else
02432     return expr2.template isActive<Arg-num_args1>();
02433       }
02434 
02435       bool updateValue() const {
02436   return expr1.updateValue() && expr2.updateValue();
02437       }
02438 
02439       void cache() const {
02440   expr1.cache();
02441   expr2.cache();
02442         const value_type_1 v1 = expr1.val();
02443   const value_type_2 v2 = expr2.val();
02444   v = std::max(v1,v2);
02445   max_v1 = (v1 >= v2);
02446       }
02447 
02448       value_type val() const {
02449   return v;
02450       }
02451 
02452       void computePartials(const value_type& bar,
02453          value_type partials[]) const {
02454   if (num_args1 > 0) {
02455     if (max_v1)
02456       expr1.computePartials(bar, partials);
02457     else
02458       expr1.computePartials(value_type(0.0), partials);
02459   }
02460   if (num_args2 > 0) {
02461     if (max_v1)
02462       expr2.computePartials(value_type(0.0), partials+num_args1);
02463     else
02464       expr2.computePartials(bar, partials+num_args1);
02465   }
02466       }
02467 
02468       void getTangents(int i, value_type dots[]) const {
02469   expr1.getTangents(i, dots);
02470   expr2.getTangents(i, dots+num_args1);
02471       }
02472 
02473       template <int Arg> value_type getTangent(int i) const {
02474   if (Arg < num_args1)
02475     return expr1.template getTangent<Arg>(i);
02476   else
02477     return expr2.template getTangent<Arg-num_args1>(i);
02478       }
02479 
02480       bool isLinear() const {
02481         return false;
02482       }
02483 
02484       bool hasFastAccess() const {
02485         return expr1.hasFastAccess() && expr2.hasFastAccess();
02486       }
02487 
02488       const value_type dx(int i) const {
02489         return max_v1 ? expr1.dx(i) : expr2.dx(i);
02490       }
02491 
02492       const value_type fastAccessDx(int i) const {
02493         return max_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
02494       }
02495 
02496       const base_expr_type& getArg(int j) const {
02497   if (j < num_args1)
02498     return expr1.getArg(j);
02499   else
02500     return expr2.getArg(j-num_args1);
02501       }
02502 
02503     protected:
02504 
02505       const ExprT1& expr1;
02506       const ExprT2& expr2;
02507       mutable value_type v;
02508       mutable bool max_v1;
02509 
02510     };
02511 
02512     template <typename ExprT1, typename T2>
02513     class Expr< MaxOp<ExprT1, ConstExpr<T2> > > {
02514 
02515     public:
02516 
02517       typedef ConstExpr<T2> ExprT2;
02518       typedef typename ExprT1::value_type value_type_1;
02519       typedef typename ExprT2::value_type value_type_2;
02520       typedef typename Sacado::Promote<value_type_1,
02521                value_type_2>::type value_type;
02522       typedef typename ExprT1::scalar_type scalar_type_1;
02523       typedef typename ExprT2::scalar_type scalar_type_2;
02524       typedef typename Sacado::Promote<scalar_type_1,
02525                scalar_type_2>::type scalar_type;
02526 
02527       typedef typename ExprT1::base_expr_type base_expr_type_1;
02528       typedef typename ExprT2::base_expr_type base_expr_type_2;
02529       typedef typename ExprPromote<base_expr_type_1,
02530            base_expr_type_2>::type base_expr_type;
02531 
02532       static const int num_args = ExprT1::num_args;
02533 
02534       static const bool is_linear = false;
02535 
02536       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02537   expr1(expr1_), expr2(expr2_) {}
02538 
02539       int size() const {
02540   return expr1.size();
02541       }
02542 
02543       template <int Arg> bool isActive() const {
02544   return expr1.template isActive<Arg>();
02545       }
02546 
02547       bool updateValue() const {
02548   return expr1.updateValue();
02549       }
02550 
02551       void cache() const {
02552   expr1.cache();
02553   const value_type_1 v1 = expr1.val();
02554   const value_type_2 v2 = expr2.val();
02555   v = std::max(v1,v2);
02556   max_v1 = (v1 >= v2);
02557       }
02558 
02559       value_type val() const {
02560   return v;
02561       }
02562 
02563       void computePartials(const value_type& bar,
02564          value_type partials[]) const {
02565   if (max_v1)
02566     expr1.computePartials(bar, partials);
02567   else
02568     expr1.computePartials(value_type(0.0), partials);
02569       }
02570 
02571       void getTangents(int i, value_type dots[]) const {
02572   expr1.getTangents(i, dots);
02573       }
02574 
02575       template <int Arg> value_type getTangent(int i) const {
02576   return expr1.template getTangent<Arg>(i);
02577       }
02578 
02579       bool isLinear() const {
02580         return false;
02581       }
02582 
02583       bool hasFastAccess() const {
02584         return expr1.hasFastAccess();
02585       }
02586 
02587       const value_type dx(int i) const {
02588         return max_v1 ? expr1.dx(i) : value_type(0.0);
02589       }
02590 
02591       const value_type fastAccessDx(int i) const {
02592         return max_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
02593       }
02594 
02595       const base_expr_type& getArg(int j) const {
02596   return expr1.getArg(j);
02597       }
02598 
02599     protected:
02600 
02601       const ExprT1& expr1;
02602       ExprT2 expr2;
02603       mutable value_type v;
02604       mutable bool max_v1;
02605 
02606     };
02607 
02608     template <typename T1, typename ExprT2>
02609     class Expr< MaxOp< ConstExpr<T1>,ExprT2> > {
02610 
02611     public:
02612 
02613       typedef ConstExpr<T1> ExprT1;
02614       typedef typename ExprT1::value_type value_type_1;
02615       typedef typename ExprT2::value_type value_type_2;
02616       typedef typename Sacado::Promote<value_type_1,
02617                value_type_2>::type value_type;
02618       typedef typename ExprT1::scalar_type scalar_type_1;
02619       typedef typename ExprT2::scalar_type scalar_type_2;
02620       typedef typename Sacado::Promote<scalar_type_1,
02621                scalar_type_2>::type scalar_type;
02622 
02623       typedef typename ExprT1::base_expr_type base_expr_type_1;
02624       typedef typename ExprT2::base_expr_type base_expr_type_2;
02625       typedef typename ExprPromote<base_expr_type_1,
02626            base_expr_type_2>::type base_expr_type;
02627 
02628       static const int num_args = ExprT2::num_args;
02629 
02630       static const bool is_linear = false;
02631 
02632       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02633   expr1(expr1_), expr2(expr2_) {}
02634 
02635       int size() const {
02636   return expr2.size();
02637       }
02638 
02639       template <int Arg> bool isActive() const {
02640   return expr2.template isActive<Arg>();
02641       }
02642 
02643       bool updateValue() const {
02644   return expr2.updateValue();
02645       }
02646 
02647       void cache() const {
02648   expr2.cache();
02649   const value_type_1 v1 = expr1.val();
02650   const value_type_2 v2 = expr2.val();
02651   v = std::max(v1,v2);
02652   max_v1 = (v1 >= v2);
02653       }
02654 
02655       value_type val() const {
02656   return v;
02657       }
02658 
02659       void computePartials(const value_type& bar,
02660          value_type partials[]) const {
02661   if (max_v1)
02662     expr2.computePartials(value_type(0.0), partials);
02663   else
02664     expr2.computePartials(bar, partials);
02665       }
02666 
02667       void getTangents(int i, value_type dots[]) const {
02668   expr2.getTangents(i, dots);
02669       }
02670 
02671       template <int Arg> value_type getTangent(int i) const {
02672   return expr2.template getTangent<Arg>(i);
02673       }
02674 
02675       bool isLinear() const {
02676         return false;
02677       }
02678 
02679       bool hasFastAccess() const {
02680         return expr2.hasFastAccess();
02681       }
02682 
02683       const value_type dx(int i) const {
02684         return max_v1 ? value_type(0.0) : expr2.dx(i);
02685       }
02686 
02687       const value_type fastAccessDx(int i) const {
02688         return max_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
02689       }
02690 
02691       const base_expr_type& getArg(int j) const {
02692   return expr2.getArg(j);
02693       }
02694 
02695     protected:
02696 
02697       ExprT1 expr1;
02698       const ExprT2& expr2;
02699       mutable value_type v;
02700       mutable bool max_v1;
02701 
02702     };
02703 
02704     //
02705     // MinOp
02706     //
02707 
02708     template <typename ExprT1, typename ExprT2>
02709     class MinOp {};
02710 
02711     template <typename ExprT1, typename ExprT2>
02712     class Expr< MinOp<ExprT1,ExprT2> > {
02713 
02714     public:
02715 
02716       typedef typename ExprT1::value_type value_type_1;
02717       typedef typename ExprT2::value_type value_type_2;
02718       typedef typename Sacado::Promote<value_type_1,
02719                value_type_2>::type value_type;
02720       typedef typename ExprT1::scalar_type scalar_type_1;
02721       typedef typename ExprT2::scalar_type scalar_type_2;
02722       typedef typename Sacado::Promote<scalar_type_1,
02723                scalar_type_2>::type scalar_type;
02724 
02725       typedef typename ExprT1::base_expr_type base_expr_type_1;
02726       typedef typename ExprT2::base_expr_type base_expr_type_2;
02727       typedef typename ExprPromote<base_expr_type_1,
02728            base_expr_type_2>::type base_expr_type;
02729 
02730       static const int num_args1 = ExprT1::num_args;
02731       static const int num_args2 = ExprT2::num_args;
02732       static const int num_args = num_args1 + num_args2;
02733 
02734       static const bool is_linear = false;
02735 
02736       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02737   expr1(expr1_), expr2(expr2_) {}
02738 
02739       int size() const {
02740   int sz1 = expr1.size(), sz2 = expr2.size();
02741   return sz1 > sz2 ? sz1 : sz2;
02742       }
02743 
02744       template <int Arg> bool isActive() const {
02745   if (Arg < num_args1)
02746     return expr1.template isActive<Arg>();
02747   else
02748     return expr2.template isActive<Arg-num_args1>();
02749       }
02750 
02751       bool updateValue() const {
02752   return expr1.updateValue() && expr2.updateValue();
02753       }
02754 
02755       void cache() const {
02756   expr1.cache();
02757   expr2.cache();
02758         const value_type_1 v1 = expr1.val();
02759   const value_type_2 v2 = expr2.val();
02760   v = std::min(v1,v2);
02761   min_v1 = (v1 <= v2);
02762       }
02763 
02764       value_type val() const {
02765   return v;
02766       }
02767 
02768       void computePartials(const value_type& bar,
02769          value_type partials[]) const {
02770   if (num_args1 > 0) {
02771     if (min_v1)
02772       expr1.computePartials(bar, partials);
02773     else
02774       expr1.computePartials(value_type(0.0), partials);
02775   }
02776   if (num_args2 > 0) {
02777     if (min_v1)
02778       expr2.computePartials(value_type(0.0), partials+num_args1);
02779     else
02780       expr2.computePartials(bar, partials+num_args1);
02781   }
02782       }
02783 
02784       void getTangents(int i, value_type dots[]) const {
02785   expr1.getTangents(i, dots);
02786   expr2.getTangents(i, dots+num_args1);
02787       }
02788 
02789       template <int Arg> value_type getTangent(int i) const {
02790   if (Arg < num_args1)
02791     return expr1.template getTangent<Arg>(i);
02792   else
02793     return expr2.template getTangent<Arg-num_args1>(i);
02794       }
02795 
02796       bool isLinear() const {
02797         return false;
02798       }
02799 
02800       bool hasFastAccess() const {
02801         return expr1.hasFastAccess() && expr2.hasFastAccess();
02802       }
02803 
02804       const value_type dx(int i) const {
02805         return min_v1 ? expr1.dx(i) : expr2.dx(i);
02806       }
02807 
02808       const value_type fastAccessDx(int i) const {
02809         return min_v1 ? expr1.fastAccessDx(i) : expr2.fastAccessDx(i);
02810       }
02811 
02812       const base_expr_type& getArg(int j) const {
02813   if (j < num_args1)
02814     return expr1.getArg(j);
02815   else
02816     return expr2.getArg(j-num_args1);
02817       }
02818 
02819     protected:
02820 
02821       const ExprT1& expr1;
02822       const ExprT2& expr2;
02823       mutable value_type v;
02824       mutable bool min_v1;
02825 
02826     };
02827 
02828     template <typename ExprT1, typename T2>
02829     class Expr< MinOp<ExprT1, ConstExpr<T2> > > {
02830 
02831     public:
02832 
02833       typedef ConstExpr<T2> ExprT2;
02834       typedef typename ExprT1::value_type value_type_1;
02835       typedef typename ExprT2::value_type value_type_2;
02836       typedef typename Sacado::Promote<value_type_1,
02837                value_type_2>::type value_type;
02838       typedef typename ExprT1::scalar_type scalar_type_1;
02839       typedef typename ExprT2::scalar_type scalar_type_2;
02840       typedef typename Sacado::Promote<scalar_type_1,
02841                scalar_type_2>::type scalar_type;
02842 
02843       typedef typename ExprT1::base_expr_type base_expr_type_1;
02844       typedef typename ExprT2::base_expr_type base_expr_type_2;
02845       typedef typename ExprPromote<base_expr_type_1,
02846            base_expr_type_2>::type base_expr_type;
02847 
02848       static const int num_args = ExprT1::num_args;
02849 
02850       static const bool is_linear = false;
02851 
02852       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02853   expr1(expr1_), expr2(expr2_) {}
02854 
02855       int size() const {
02856   return expr1.size();
02857       }
02858 
02859       template <int Arg> bool isActive() const {
02860   return expr1.template isActive<Arg>();
02861       }
02862 
02863       bool updateValue() const {
02864   return expr1.updateValue();
02865       }
02866 
02867       void cache() const {
02868   expr1.cache();
02869   const value_type_1 v1 = expr1.val();
02870   const value_type_2 v2 = expr2.val();
02871   v = std::min(v1,v2);
02872   min_v1 = (v1 <= v2);
02873       }
02874 
02875       value_type val() const {
02876   return v;
02877       }
02878 
02879       void computePartials(const value_type& bar,
02880          value_type partials[]) const {
02881   if (min_v1)
02882     expr1.computePartials(bar, partials);
02883   else
02884     expr1.computePartials(value_type(0.0), partials);
02885       }
02886 
02887       void getTangents(int i, value_type dots[]) const {
02888   expr1.getTangents(i, dots);
02889       }
02890 
02891       template <int Arg> value_type getTangent(int i) const {
02892   return expr1.template getTangent<Arg>(i);
02893       }
02894 
02895       bool isLinear() const {
02896         return false;
02897       }
02898 
02899       bool hasFastAccess() const {
02900         return expr1.hasFastAccess();
02901       }
02902 
02903       const value_type dx(int i) const {
02904         return min_v1 ? expr1.dx(i) : value_type(0.0);
02905       }
02906 
02907       const value_type fastAccessDx(int i) const {
02908         return min_v1 ? expr1.fastAccessDx(i) : value_type(0.0);
02909       }
02910       
02911       const base_expr_type& getArg(int j) const {
02912   return expr1.getArg(j);
02913       }
02914 
02915     protected:
02916 
02917       const ExprT1& expr1;
02918       ExprT2 expr2;
02919       mutable value_type v;
02920       mutable bool min_v1;
02921 
02922     };
02923 
02924     template <typename T1, typename ExprT2>
02925     class Expr< MinOp< ConstExpr<T1>,ExprT2> > {
02926 
02927     public:
02928 
02929       typedef ConstExpr<T1> ExprT1;
02930       typedef typename ExprT1::value_type value_type_1;
02931       typedef typename ExprT2::value_type value_type_2;
02932       typedef typename Sacado::Promote<value_type_1,
02933                value_type_2>::type value_type;
02934       typedef typename ExprT1::scalar_type scalar_type_1;
02935       typedef typename ExprT2::scalar_type scalar_type_2;
02936       typedef typename Sacado::Promote<scalar_type_1,
02937                scalar_type_2>::type scalar_type;
02938 
02939       typedef typename ExprT1::base_expr_type base_expr_type_1;
02940       typedef typename ExprT2::base_expr_type base_expr_type_2;
02941       typedef typename ExprPromote<base_expr_type_1,
02942            base_expr_type_2>::type base_expr_type;
02943 
02944       static const int num_args = ExprT2::num_args;
02945 
02946       static const bool is_linear = false;
02947 
02948       Expr(const ExprT1& expr1_, const ExprT2& expr2_) :
02949   expr1(expr1_), expr2(expr2_) {}
02950 
02951       int size() const {
02952   return expr2.size();
02953       }
02954 
02955       template <int Arg> bool isActive() const {
02956   return expr2.template isActive<Arg>();
02957       }
02958 
02959       bool updateValue() const {
02960   return expr2.updateValue();
02961       }
02962 
02963       void cache() const {
02964   expr2.cache();
02965   const value_type_1 v1 = expr1.val();
02966   const value_type_2 v2 = expr2.val();
02967   v = std::min(v1,v2);
02968   min_v1 = (v1 <= v2);
02969       }
02970 
02971       value_type val() const {
02972   return v;
02973       }
02974 
02975       void computePartials(const value_type& bar,
02976          value_type partials[]) const {
02977   if (min_v1)
02978     expr2.computePartials(value_type(0.0), partials);
02979   else
02980     expr2.computePartials(bar, partials);
02981       }
02982 
02983       void getTangents(int i, value_type dots[]) const {
02984   expr2.getTangents(i, dots);
02985       }
02986 
02987       template <int Arg> value_type getTangent(int i) const {
02988   return expr2.template getTangent<Arg>(i);
02989       }
02990 
02991       bool isLinear() const {
02992         return false;
02993       }
02994 
02995       bool hasFastAccess() const {
02996         return expr2.hasFastAccess();
02997       }
02998 
02999       const value_type dx(int i) const {
03000         return min_v1 ? value_type(0.0) : expr2.dx(i);
03001       }
03002 
03003       const value_type fastAccessDx(int i) const {
03004         return min_v1 ? value_type(0.0) : expr2.fastAccessDx(i);
03005       }
03006 
03007       const base_expr_type& getArg(int j) const {
03008   return expr2.getArg(j);
03009       }
03010 
03011     protected:
03012 
03013       ExprT1 expr1;
03014       const ExprT2& expr2;
03015       mutable value_type v;
03016       mutable bool min_v1;
03017 
03018     };
03019 
03020   }
03021 
03022 }
03023 
03024 #define FAD_BINARYOP_MACRO(OPNAME,OP)         \
03025 namespace Sacado {              \
03026   namespace ELRCacheFad {           \
03027                   \
03028     template <typename T1, typename T2>         \
03029     inline Expr< OP< Expr<T1>, Expr<T2> > >       \
03030     OPNAME (const Expr<T1>& expr1, const Expr<T2>& expr2)   \
03031     {                 \
03032       typedef OP< Expr<T1>, Expr<T2> > expr_t;        \
03033                       \
03034       return Expr<expr_t>(expr1, expr2);        \
03035     }                 \
03036                   \
03037     template <typename T>           \
03038     inline Expr< OP< Expr<T>, Expr<T> > >       \
03039     OPNAME (const Expr<T>& expr1, const Expr<T>& expr2)     \
03040     {                 \
03041       typedef OP< Expr<T>, Expr<T> > expr_t;        \
03042                       \
03043       return Expr<expr_t>(expr1, expr2);        \
03044     }                 \
03045                   \
03046     template <typename T>           \
03047     inline Expr< OP< ConstExpr<typename Expr<T>::value_type>,   \
03048          Expr<T> > >          \
03049     OPNAME (const typename Expr<T>::value_type& c,      \
03050       const Expr<T>& expr)          \
03051     {                 \
03052       typedef ConstExpr<typename Expr<T>::value_type> ConstT;   \
03053       typedef OP< ConstT, Expr<T> > expr_t;       \
03054                   \
03055       return Expr<expr_t>(ConstT(c), expr);       \
03056     }                 \
03057                   \
03058     template <typename T>           \
03059     inline Expr< OP< Expr<T>,           \
03060          ConstExpr<typename Expr<T>::value_type> > >  \
03061     OPNAME (const Expr<T>& expr,          \
03062       const typename Expr<T>::value_type& c)      \
03063     {                 \
03064       typedef ConstExpr<typename Expr<T>::value_type> ConstT;   \
03065       typedef OP< Expr<T>, ConstT > expr_t;       \
03066                   \
03067       return Expr<expr_t>(expr, ConstT(c));       \
03068     }                 \
03069                   \
03070     template <typename T>           \
03071     inline typename             \
03072     mpl::disable_if<mpl::is_same<typename Expr<T>::value_type,    \
03073          typename Expr<T>::scalar_type>,  \
03074         Expr< OP< ConstExpr<typename Expr<T>::scalar_type>, \
03075             Expr<T> > >       \
03076         >::type           \
03077     OPNAME (const typename Expr<T>::scalar_type& c,     \
03078       const Expr<T>& expr)          \
03079     {                 \
03080       typedef ConstExpr<typename Expr<T>::scalar_type> ConstT;    \
03081       typedef OP< ConstT, Expr<T> > expr_t;       \
03082                   \
03083       return Expr<expr_t>(ConstT(c), expr);       \
03084     }                 \
03085                   \
03086     template <typename T>           \
03087     inline typename             \
03088     mpl::disable_if<mpl::is_same<typename Expr<T>::value_type,    \
03089          typename Expr<T>::scalar_type>,  \
03090         Expr< OP< Expr<T>,          \
03091             ConstExpr<typename Expr<T>::scalar_type> > > \
03092         >::type           \
03093     OPNAME (const Expr<T>& expr,          \
03094       const typename Expr<T>::scalar_type& c)     \
03095     {                 \
03096       typedef ConstExpr<typename Expr<T>::scalar_type> ConstT;    \
03097       typedef OP< Expr<T>, ConstT > expr_t;       \
03098                   \
03099       return Expr<expr_t>(expr, ConstT(c));       \
03100     }                 \
03101   }                 \
03102 }
03103 
03104 
03105 FAD_BINARYOP_MACRO(operator+, AdditionOp)
03106 FAD_BINARYOP_MACRO(operator-, SubtractionOp)
03107 FAD_BINARYOP_MACRO(operator*, MultiplicationOp)
03108 FAD_BINARYOP_MACRO(operator/, DivisionOp)
03109 FAD_BINARYOP_MACRO(atan2, Atan2Op)
03110 FAD_BINARYOP_MACRO(pow, PowerOp)
03111 FAD_BINARYOP_MACRO(max, MaxOp)
03112 FAD_BINARYOP_MACRO(min, MinOp)
03113 
03114 #undef FAD_BINARYOP_MACRO
03115 
03116 //-------------------------- Relational Operators -----------------------
03117 
03118 #define FAD_RELOP_MACRO(OP)           \
03119 namespace Sacado {              \
03120   namespace ELRCacheFad {           \
03121     template <typename ExprT1, typename ExprT2>       \
03122     inline bool               \
03123     operator OP (const Expr<ExprT1>& expr1,       \
03124      const Expr<ExprT2>& expr2)       \
03125     {                 \
03126       return expr1.val() OP expr2.val();        \
03127     }                 \
03128                   \
03129     template <typename ExprT2>            \
03130     inline bool               \
03131     operator OP (const typename Expr<ExprT2>::value_type& a,    \
03132      const Expr<ExprT2>& expr2)       \
03133     {                 \
03134       return a OP expr2.val();            \
03135     }                 \
03136                   \
03137     template <typename ExprT1>            \
03138     inline bool               \
03139     operator OP (const Expr<ExprT1>& expr1,       \
03140      const typename Expr<ExprT1>::value_type& b)    \
03141     {                 \
03142       return expr1.val() OP b;            \
03143     }                 \
03144   }                 \
03145 }
03146 
03147 FAD_RELOP_MACRO(==)
03148 FAD_RELOP_MACRO(!=)
03149 FAD_RELOP_MACRO(<)
03150 FAD_RELOP_MACRO(>)
03151 FAD_RELOP_MACRO(<=)
03152 FAD_RELOP_MACRO(>=)
03153 FAD_RELOP_MACRO(<<=)
03154 FAD_RELOP_MACRO(>>=)
03155 FAD_RELOP_MACRO(&)
03156 FAD_RELOP_MACRO(|)
03157 
03158 #undef FAD_RELOP_MACRO
03159 
03160 namespace Sacado {
03161 
03162   namespace ELRCacheFad {
03163 
03164     template <typename ExprT>
03165     inline bool operator ! (const Expr<ExprT>& expr) 
03166     {
03167       return ! expr.val();
03168     }
03169 
03170   } // namespace ELRCacheFad
03171 
03172 } // namespace Sacado
03173 
03174 //-------------------------- Boolean Operators -----------------------
03175 namespace Sacado {
03176 
03177   namespace ELRCacheFad {
03178 
03179     template <typename ExprT>
03180     bool toBool(const Expr<ExprT>& x) {
03181       bool is_zero = (x.val() == 0.0);
03182       for (int i=0; i<x.size(); i++)
03183   is_zero = is_zero && (x.dx(i) == 0.0);
03184       return !is_zero;
03185     }
03186 
03187   } // namespace Fad
03188 
03189 } // namespace Sacado
03190 
03191 #define FAD_BOOL_MACRO(OP)            \
03192 namespace Sacado {              \
03193   namespace ELRCacheFad {           \
03194     template <typename ExprT1, typename ExprT2>       \
03195     inline bool               \
03196     operator OP (const Expr<ExprT1>& expr1,       \
03197      const Expr<ExprT2>& expr2)       \
03198     {                 \
03199       return toBool(expr1) OP toBool(expr2);        \
03200     }                 \
03201                   \
03202     template <typename ExprT2>            \
03203     inline bool               \
03204     operator OP (const typename Expr<ExprT2>::value_type& a,    \
03205      const Expr<ExprT2>& expr2)       \
03206     {                 \
03207       return a OP toBool(expr2);          \
03208     }                 \
03209                   \
03210     template <typename ExprT1>            \
03211     inline bool               \
03212     operator OP (const Expr<ExprT1>& expr1,       \
03213      const typename Expr<ExprT1>::value_type& b)    \
03214     {                 \
03215       return toBool(expr1) OP b;          \
03216     }                 \
03217   }                 \
03218 }
03219 
03220 FAD_BOOL_MACRO(&&)
03221 FAD_BOOL_MACRO(||)
03222 
03223 #undef FAD_BOOL_MACRO
03224 
03225 //-------------------------- I/O Operators -----------------------
03226 
03227 namespace Sacado {
03228 
03229   namespace ELRCacheFad {
03230 
03231     template <typename ExprT>
03232     std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
03233       typedef typename Expr<ExprT>::base_expr_type base_expr_type;
03234       return os << base_expr_type(x);
03235     }
03236 
03237   } // namespace Fad
03238 
03239 } // namespace Sacado
03240 
03241 
03242 #endif // SACADO_CACHEFAD_OPS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines