|
Sacado Package Browser (Single Doxygen Collection) Version of the Day
|
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
1.7.4