00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifndef SACADO_FAD_OPS_HPP
00055 #define SACADO_FAD_OPS_HPP
00056
00057 #include "Sacado_Fad_Expression.hpp"
00058 #include <cmath>
00059 #include <algorithm>
00060 #include <ostream>
00061
00062 #define FAD_UNARYOP_MACRO(OPNAME,OP,VALUE,DX,FASTACCESSDX) \
00063 namespace Sacado { \
00064 namespace Fad { \
00065 \
00066 template <typename ExprT> \
00067 class OP {}; \
00068 \
00069 template <typename ExprT> \
00070 class Expr< OP<ExprT> > { \
00071 public: \
00072 \
00073 typedef typename ExprT::value_type value_type; \
00074 \
00075 Expr(const ExprT& expr_) : expr(expr_) {} \
00076 \
00077 int size() const { return expr.size(); } \
00078 \
00079 bool hasFastAccess() const { return expr.hasFastAccess(); } \
00080 \
00081 bool isPassive() const { return expr.isPassive();} \
00082 \
00083 value_type val() const { \
00084 return VALUE; \
00085 } \
00086 \
00087 value_type dx(int i) const { \
00088 return DX; \
00089 } \
00090 \
00091 value_type fastAccessDx(int i) const { \
00092 return FASTACCESSDX; \
00093 } \
00094 \
00095 protected: \
00096 \
00097 const ExprT& expr; \
00098 }; \
00099 \
00100 template <typename T> \
00101 inline Expr< OP< Expr<T> > > \
00102 OPNAME (const Expr<T>& expr) \
00103 { \
00104 typedef OP< Expr<T> > expr_t; \
00105 \
00106 return Expr<expr_t>(expr); \
00107 } \
00108 } \
00109 }
00110
00111 FAD_UNARYOP_MACRO(operator+,
00112 UnaryPlusOp,
00113 expr.val(),
00114 expr.dx(i),
00115 expr.fastAccessDx(i))
00116 FAD_UNARYOP_MACRO(operator-,
00117 UnaryMinusOp,
00118 -expr.val(),
00119 -expr.dx(i),
00120 -expr.fastAccessDx(i))
00121 FAD_UNARYOP_MACRO(exp,
00122 ExpOp,
00123 std::exp(expr.val()),
00124 std::exp(expr.val())*expr.dx(i),
00125 std::exp(expr.val())*expr.fastAccessDx(i))
00126 FAD_UNARYOP_MACRO(log,
00127 LogOp,
00128 std::log(expr.val()),
00129 expr.dx(i)/expr.val(),
00130 expr.fastAccessDx(i)/expr.val())
00131 FAD_UNARYOP_MACRO(log10,
00132 Log10Op,
00133 std::log10(expr.val()),
00134 expr.dx(i)/( std::log(value_type(10))*expr.val()),
00135 expr.fastAccessDx(i) / ( std::log(value_type(10))*expr.val()))
00136 FAD_UNARYOP_MACRO(sqrt,
00137 SqrtOp,
00138 std::sqrt(expr.val()),
00139 expr.dx(i)/(value_type(2)* std::sqrt(expr.val())),
00140 expr.fastAccessDx(i)/(value_type(2)* std::sqrt(expr.val())))
00141 FAD_UNARYOP_MACRO(cos,
00142 CosOp,
00143 std::cos(expr.val()),
00144 -expr.dx(i)* std::sin(expr.val()),
00145 -expr.fastAccessDx(i)* std::sin(expr.val()))
00146 FAD_UNARYOP_MACRO(sin,
00147 SinOp,
00148 std::sin(expr.val()),
00149 expr.dx(i)* std::cos(expr.val()),
00150 expr.fastAccessDx(i)* std::cos(expr.val()))
00151 FAD_UNARYOP_MACRO(tan,
00152 TanOp,
00153 std::tan(expr.val()),
00154 expr.dx(i)*
00155 (value_type(1)+ std::tan(expr.val())* std::tan(expr.val())),
00156 expr.fastAccessDx(i)*
00157 (value_type(1)+ std::tan(expr.val())* std::tan(expr.val())))
00158 FAD_UNARYOP_MACRO(acos,
00159 ACosOp,
00160 std::acos(expr.val()),
00161 -expr.dx(i)/ std::sqrt(value_type(1)-expr.val()*expr.val()),
00162 -expr.fastAccessDx(i) /
00163 std::sqrt(value_type(1)-expr.val()*expr.val()))
00164 FAD_UNARYOP_MACRO(asin,
00165 ASinOp,
00166 std::asin(expr.val()),
00167 expr.dx(i)/ std::sqrt(value_type(1)-expr.val()*expr.val()),
00168 expr.fastAccessDx(i) /
00169 std::sqrt(value_type(1)-expr.val()*expr.val()))
00170 FAD_UNARYOP_MACRO(atan,
00171 ATanOp,
00172 std::atan(expr.val()),
00173 expr.dx(i)/(value_type(1)+expr.val()*expr.val()),
00174 expr.fastAccessDx(i)/(value_type(1)+expr.val()*expr.val()))
00175 FAD_UNARYOP_MACRO(cosh,
00176 CoshOp,
00177 std::cosh(expr.val()),
00178 expr.dx(i)* std::sinh(expr.val()),
00179 expr.fastAccessDx(i)* std::sinh(expr.val()))
00180 FAD_UNARYOP_MACRO(sinh,
00181 SinhOp,
00182 std::sinh(expr.val()),
00183 expr.dx(i)* std::cosh(expr.val()),
00184 expr.fastAccessDx(i)* std::cosh(expr.val()))
00185 FAD_UNARYOP_MACRO(tanh,
00186 TanhOp,
00187 std::tanh(expr.val()),
00188 expr.dx(i)/( std::cosh(expr.val())* std::cosh(expr.val())),
00189 expr.fastAccessDx(i) /
00190 ( std::cosh(expr.val())* std::cosh(expr.val())))
00191 FAD_UNARYOP_MACRO(acosh,
00192 ACoshOp,
00193 acosh(expr.val()),
00194 expr.dx(i)/ std::sqrt((expr.val()-value_type(1)) *
00195 (expr.val()+value_type(1))),
00196 expr.fastAccessDx(i)/ std::sqrt((expr.val()-value_type(1)) *
00197 (expr.val()+value_type(1))))
00198 FAD_UNARYOP_MACRO(asinh,
00199 ASinhOp,
00200 asinh(expr.val()),
00201 expr.dx(i)/ std::sqrt(value_type(1)+expr.val()*expr.val()),
00202 expr.fastAccessDx(i)/ std::sqrt(value_type(1)+
00203 expr.val()*expr.val()))
00204 FAD_UNARYOP_MACRO(atanh,
00205 ATanhOp,
00206 atanh(expr.val()),
00207 expr.dx(i)/(value_type(1)-expr.val()*expr.val()),
00208 expr.fastAccessDx(i)/(value_type(1)-
00209 expr.val()*expr.val()))
00210 FAD_UNARYOP_MACRO(abs,
00211 AbsOp,
00212 std::abs(expr.val()),
00213 expr.val() >= 0 ? value_type(+expr.dx(i)) :
00214 value_type(-expr.dx(i)),
00215 expr.val() >= 0 ? value_type(+expr.fastAccessDx(i)) :
00216 value_type(-expr.fastAccessDx(i)))
00217 FAD_UNARYOP_MACRO(fabs,
00218 FAbsOp,
00219 std::fabs(expr.val()),
00220 expr.val() >= 0 ? value_type(+expr.dx(i)) :
00221 value_type(-expr.dx(i)),
00222 expr.val() >= 0 ? value_type(+expr.fastAccessDx(i)) :
00223 value_type(-expr.fastAccessDx(i)))
00224
00225 #undef FAD_UNARYOP_MACRO
00226
00227 #define FAD_BINARYOP_MACRO(OPNAME,OP,VALUE,DX,FASTACCESSDX,VAL_CONST_DX_1,VAL_CONST_DX_2,CONST_DX_1,CONST_DX_2,CONST_FASTACCESSDX_1,CONST_FASTACCESSDX_2) \
00228 namespace Sacado { \
00229 namespace Fad { \
00230 \
00231 template <typename ExprT1, typename ExprT2> \
00232 class OP {}; \
00233 \
00234 template <typename T1, typename T2> \
00235 class Expr< OP< Expr<T1>, Expr<T2> > > { \
00236 \
00237 public: \
00238 \
00239 typedef Expr<T1> ExprT1; \
00240 typedef Expr<T2> ExprT2; \
00241 typedef typename ExprT1::value_type value_type_1; \
00242 typedef typename ExprT2::value_type value_type_2; \
00243 typedef typename Sacado::Promote<value_type_1, \
00244 value_type_2>::type value_type; \
00245 \
00246 Expr(const ExprT1& expr1_, const ExprT2& expr2_) : \
00247 expr1(expr1_), expr2(expr2_) {} \
00248 \
00249 int size() const { \
00250 int sz1 = expr1.size(), sz2 = expr2.size(); \
00251 return sz1 > sz2 ? sz1 : sz2; \
00252 } \
00253 \
00254 bool hasFastAccess() const { \
00255 return expr1.hasFastAccess() && expr2.hasFastAccess(); \
00256 } \
00257 \
00258 bool isPassive() const { \
00259 return expr1.isPassive() && expr2.isPassive(); \
00260 } \
00261 \
00262 const value_type val() const { \
00263 return VALUE; \
00264 } \
00265 \
00266 const value_type dx(int i) const { \
00267 return DX; \
00268 } \
00269 \
00270 const value_type fastAccessDx(int i) const { \
00271 return FASTACCESSDX; \
00272 } \
00273 \
00274 protected: \
00275 \
00276 const ExprT1& expr1; \
00277 const ExprT2& expr2; \
00278 \
00279 }; \
00280 \
00281 template <typename T1> \
00282 class Expr< OP< Expr<T1>, typename Expr<T1>::value_type> > { \
00283 \
00284 public: \
00285 \
00286 typedef Expr<T1> ExprT1; \
00287 typedef typename ExprT1::value_type value_type; \
00288 typedef typename ExprT1::value_type ConstT; \
00289 \
00290 Expr(const ExprT1& expr1_, const ConstT& c_) : \
00291 expr1(expr1_), c(c_) {} \
00292 \
00293 int size() const { \
00294 return expr1.size(); \
00295 } \
00296 \
00297 bool hasFastAccess() const { \
00298 return expr1.hasFastAccess(); \
00299 } \
00300 \
00301 bool isPassive() const { \
00302 return expr1.isPassive(); \
00303 } \
00304 \
00305 const value_type val() const { \
00306 return VAL_CONST_DX_2; \
00307 } \
00308 \
00309 const value_type dx(int i) const { \
00310 return CONST_DX_2; \
00311 } \
00312 \
00313 const value_type fastAccessDx(int i) const { \
00314 return CONST_FASTACCESSDX_2; \
00315 } \
00316 \
00317 protected: \
00318 \
00319 const ExprT1& expr1; \
00320 const ConstT& c; \
00321 }; \
00322 \
00323 template <typename T2> \
00324 class Expr< OP< typename Expr<T2>::value_type, Expr<T2> > > { \
00325 \
00326 public: \
00327 \
00328 typedef Expr<T2> ExprT2; \
00329 typedef typename ExprT2::value_type value_type; \
00330 typedef typename ExprT2::value_type ConstT; \
00331 \
00332 Expr(const ConstT& c_, const ExprT2& expr2_) : \
00333 c(c_), expr2(expr2_) {} \
00334 \
00335 int size() const { \
00336 return expr2.size(); \
00337 } \
00338 \
00339 bool hasFastAccess() const { \
00340 return expr2.hasFastAccess(); \
00341 } \
00342 \
00343 bool isPassive() const { \
00344 return expr2.isPassive(); \
00345 } \
00346 \
00347 const value_type val() const { \
00348 return VAL_CONST_DX_1; \
00349 } \
00350 \
00351 const value_type dx(int i) const { \
00352 return CONST_DX_1; \
00353 } \
00354 \
00355 const value_type fastAccessDx(int i) const { \
00356 return CONST_FASTACCESSDX_1; \
00357 } \
00358 \
00359 protected: \
00360 \
00361 const ConstT& c; \
00362 const ExprT2& expr2; \
00363 }; \
00364 \
00365 template <typename T1, typename T2> \
00366 inline Expr< OP< Expr<T1>, Expr<T2> > > \
00367 OPNAME (const Expr<T1>& expr1, const Expr<T2>& expr2) \
00368 { \
00369 typedef OP< Expr<T1>, Expr<T2> > expr_t; \
00370 \
00371 return Expr<expr_t>(expr1, expr2); \
00372 } \
00373 \
00374 template <typename T> \
00375 inline Expr< OP< Expr<T>, Expr<T> > > \
00376 OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
00377 { \
00378 typedef OP< Expr<T>, Expr<T> > expr_t; \
00379 \
00380 return Expr<expr_t>(expr1, expr2); \
00381 } \
00382 \
00383 template <typename T> \
00384 inline Expr< OP< typename Expr<T>::value_type, Expr<T> > > \
00385 OPNAME (const typename Expr<T>::value_type& c, \
00386 const Expr<T>& expr) \
00387 { \
00388 typedef typename Expr<T>::value_type ConstT; \
00389 typedef OP< ConstT, Expr<T> > expr_t; \
00390 \
00391 return Expr<expr_t>(c, expr); \
00392 } \
00393 \
00394 template <typename T> \
00395 inline Expr< OP< Expr<T>, typename Expr<T>::value_type > > \
00396 OPNAME (const Expr<T>& expr, \
00397 const typename Expr<T>::value_type& c) \
00398 { \
00399 typedef typename Expr<T>::value_type ConstT; \
00400 typedef OP< Expr<T>, ConstT > expr_t; \
00401 \
00402 return Expr<expr_t>(expr, c); \
00403 } \
00404 } \
00405 }
00406
00407
00408 FAD_BINARYOP_MACRO(operator+,
00409 AdditionOp,
00410 expr1.val() + expr2.val(),
00411 expr1.dx(i) + expr2.dx(i),
00412 expr1.fastAccessDx(i) + expr2.fastAccessDx(i),
00413 c + expr2.val(),
00414 expr1.val() + c,
00415 expr2.dx(i),
00416 expr1.dx(i),
00417 expr2.fastAccessDx(i),
00418 expr1.fastAccessDx(i))
00419 FAD_BINARYOP_MACRO(operator-,
00420 SubtractionOp,
00421 expr1.val() - expr2.val(),
00422 expr1.dx(i) - expr2.dx(i),
00423 expr1.fastAccessDx(i) - expr2.fastAccessDx(i),
00424 c - expr2.val(),
00425 expr1.val() - c,
00426 -expr2.dx(i),
00427 expr1.dx(i),
00428 -expr2.fastAccessDx(i),
00429 expr1.fastAccessDx(i))
00430 FAD_BINARYOP_MACRO(operator*,
00431 MultiplicationOp,
00432 expr1.val() * expr2.val(),
00433 expr1.val()*expr2.dx(i) + expr1.dx(i)*expr2.val(),
00434 expr1.val()*expr2.fastAccessDx(i) +
00435 expr1.fastAccessDx(i)*expr2.val(),
00436 c * expr2.val(),
00437 expr1.val() * c,
00438 c*expr2.dx(i),
00439 expr1.dx(i)*c,
00440 c*expr2.fastAccessDx(i),
00441 expr1.fastAccessDx(i)*c)
00442 FAD_BINARYOP_MACRO(operator/,
00443 DivisionOp,
00444 expr1.val() / expr2.val(),
00445 (expr1.dx(i)*expr2.val() - expr2.dx(i)*expr1.val()) /
00446 (expr2.val()*expr2.val()),
00447 (expr1.fastAccessDx(i)*expr2.val() -
00448 expr2.fastAccessDx(i)*expr1.val()) /
00449 (expr2.val()*expr2.val()),
00450 c / expr2.val(),
00451 expr1.val() / c,
00452 -expr2.dx(i)*c / (expr2.val()*expr2.val()),
00453 expr1.dx(i)/c,
00454 -expr2.fastAccessDx(i)*c / (expr2.val()*expr2.val()),
00455 expr1.fastAccessDx(i)/c)
00456 FAD_BINARYOP_MACRO(atan2,
00457 Atan2Op,
00458 std::atan2(expr1.val(), expr2.val()),
00459 (expr2.val()*expr1.dx(i) - expr1.val()*expr2.dx(i))/
00460 (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
00461 (expr2.val()*expr1.fastAccessDx(i) - expr1.val()*expr2.fastAccessDx(i))/
00462 (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
00463 std::atan2(c, expr2.val()),
00464 std::atan2(expr1.val(), c),
00465 (-c*expr2.dx(i)) / (c*c + expr2.val()*expr2.val()),
00466 (c*expr1.dx(i))/ (expr1.val()*expr1.val() + c*c),
00467 (-c*expr2.fastAccessDx(i))/ (c*c + expr2.val()*expr2.val()),
00468 (c*expr1.fastAccessDx(i))/ (expr1.val()*expr1.val() + c*c))
00469 FAD_BINARYOP_MACRO(pow,
00470 PowerOp,
00471 std::pow(expr1.val(), expr2.val()),
00472 (expr2.dx(i)*std::log(expr1.val())+expr2.val()*expr1.dx(i)/
00473 expr1.val())*std::pow(expr1.val(),expr2.val()),
00474 (expr2.fastAccessDx(i)*std::log(expr1.val())+
00475 expr2.val()*expr1.fastAccessDx(i)/
00476 expr1.val())*std::pow(expr1.val(),expr2.val()),
00477 std::pow(c, expr2.val()),
00478 std::pow(expr1.val(), c),
00479 expr2.dx(i)*std::log(c)*std::pow(c,expr2.val()),
00480 c*expr1.dx(i)/expr1.val()*std::pow(expr1.val(),c),
00481 expr2.fastAccessDx(i)*std::log(c)*std::pow(c,expr2.val()),
00482 c*expr1.fastAccessDx(i)/expr1.val()*std::pow(expr1.val(),c))
00483 FAD_BINARYOP_MACRO(max,
00484 MaxOp,
00485 std::max(expr1.val(), expr2.val()),
00486 expr1.val() >= expr2.val() ? expr1.dx(i) : expr2.dx(i),
00487 expr1.val() >= expr2.val() ? expr1.fastAccessDx(i) :
00488 expr2.fastAccessDx(i),
00489 std::max(c, expr2.val()),
00490 std::max(expr1.val(), c),
00491 c >= expr2.val() ? value_type(0) : expr2.dx(i),
00492 expr1.val() >= c ? expr1.dx(i) : value_type(0),
00493 c >= expr2.val() ? value_type(0) : expr2.fastAccessDx(i),
00494 expr1.val() >= c ? expr1.fastAccessDx(i) : value_type(0))
00495 FAD_BINARYOP_MACRO(min,
00496 MinOp,
00497 std::min(expr1.val(), expr2.val()),
00498 expr1.val() <= expr2.val() ? expr1.dx(i) : expr2.dx(i),
00499 expr1.val() <= expr2.val() ? expr1.fastAccessDx(i) :
00500 expr2.fastAccessDx(i),
00501 std::min(c, expr2.val()),
00502 std::min(expr1.val(), c),
00503 c <= expr2.val() ? value_type(0) : expr2.dx(i),
00504 expr1.val() <= c ? expr1.dx(i) : value_type(0),
00505 c <= expr2.val() ? value_type(0) : expr2.fastAccessDx(i),
00506 expr1.val() <= c ? expr1.fastAccessDx(i) : value_type(0))
00507
00508 #undef FAD_BINARYOP_MACRO
00509
00510
00511
00512 #define FAD_RELOP_MACRO(OP) \
00513 namespace Sacado { \
00514 namespace Fad { \
00515 template <typename ExprT1, typename ExprT2> \
00516 inline bool \
00517 operator OP (const Expr<ExprT1>& expr1, \
00518 const Expr<ExprT2>& expr2) \
00519 { \
00520 return expr1.val() OP expr2.val(); \
00521 } \
00522 \
00523 template <typename ExprT2> \
00524 inline bool \
00525 operator OP (const typename Expr<ExprT2>::value_type& a, \
00526 const Expr<ExprT2>& expr2) \
00527 { \
00528 return a OP expr2.val(); \
00529 } \
00530 \
00531 template <typename ExprT1> \
00532 inline bool \
00533 operator OP (const Expr<ExprT1>& expr1, \
00534 const typename Expr<ExprT1>::value_type& b) \
00535 { \
00536 return expr1.val() OP b; \
00537 } \
00538 } \
00539 }
00540
00541 FAD_RELOP_MACRO(==)
00542 FAD_RELOP_MACRO(!=)
00543 FAD_RELOP_MACRO(<)
00544 FAD_RELOP_MACRO(>)
00545 FAD_RELOP_MACRO(<=)
00546 FAD_RELOP_MACRO(>=)
00547 FAD_RELOP_MACRO(<<=)
00548 FAD_RELOP_MACRO(>>=)
00549 FAD_RELOP_MACRO(&)
00550 FAD_RELOP_MACRO(|)
00551
00552 #undef FAD_RELOP_MACRO
00553
00554 namespace Sacado {
00555
00556 namespace Fad {
00557
00558 template <typename ExprT>
00559 inline bool operator ! (const Expr<ExprT>& expr)
00560 {
00561 return ! expr.val();
00562 }
00563
00564 }
00565
00566 }
00567
00568
00569
00570 namespace Sacado {
00571
00572 namespace Fad {
00573
00574 template <typename ExprT>
00575 std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
00576 os << x.val() << " [";
00577
00578 for (int i=0; i< x.size(); i++) {
00579 os << " " << x.dx(i);
00580 }
00581
00582 os << " ]\n";
00583 return os;
00584 }
00585
00586 }
00587
00588 }
00589
00590
00591 #endif // SACADO_FAD_OPS_HPP