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_ELRFAD_OPS_HPP
00055 #define SACADO_ELRFAD_OPS_HPP
00056
00057 #include "Sacado_ELRFad_Expression.hpp"
00058 #include <cmath>
00059 #include <algorithm>
00060 #include <ostream>
00061
00062 #define FAD_UNARYOP_MACRO(OPNAME,OP,VALUE,ADJOINT) \
00063 namespace Sacado { \
00064 namespace ELRFad { \
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 typedef typename ExprT::base_expr_type base_expr_type; \
00076 \
00077 static const int num_args = ExprT::num_args; \
00078 \
00079 Expr(const ExprT& expr_) : expr(expr_) {} \
00080 \
00081 int size() const { return expr.size(); } \
00082 \
00083 template <int Arg> \
00084 bool isActive() const { return expr.template isActive<Arg>(); } \
00085 \
00086 value_type val() const { \
00087 return VALUE; \
00088 } \
00089 \
00090 void computePartials(const value_type& bar, \
00091 value_type partials[]) const { \
00092 expr.computePartials(ADJOINT, partials); \
00093 } \
00094 \
00095 void getTangents(int i, value_type dots[]) const { \
00096 expr.getTangents(i, dots); } \
00097 \
00098 template <int Arg> \
00099 value_type getTangent(int i) const { \
00100 return expr.template getTangent<Arg>(i); \
00101 } \
00102 \
00103 protected: \
00104 \
00105 const ExprT& expr; \
00106 }; \
00107 \
00108 template <typename T> \
00109 inline Expr< OP< Expr<T> > > \
00110 OPNAME (const Expr<T>& expr) \
00111 { \
00112 typedef OP< Expr<T> > expr_t; \
00113 \
00114 return Expr<expr_t>(expr); \
00115 } \
00116 } \
00117 }
00118
00119 FAD_UNARYOP_MACRO(operator+,
00120 UnaryPlusOp,
00121 expr.val(),
00122 bar)
00123 FAD_UNARYOP_MACRO(operator-,
00124 UnaryMinusOp,
00125 -expr.val(),
00126 -bar)
00127 FAD_UNARYOP_MACRO(exp,
00128 ExpOp,
00129 std::exp(expr.val()),
00130 bar*std::exp(expr.val()))
00131 FAD_UNARYOP_MACRO(log,
00132 LogOp,
00133 std::log(expr.val()),
00134 bar/expr.val())
00135 FAD_UNARYOP_MACRO(log10,
00136 Log10Op,
00137 std::log10(expr.val()),
00138 bar/( std::log(value_type(10.))*expr.val() ))
00139 FAD_UNARYOP_MACRO(sqrt,
00140 SqrtOp,
00141 std::sqrt(expr.val()),
00142 value_type(0.5)*bar/std::sqrt(expr.val()))
00143 FAD_UNARYOP_MACRO(cos,
00144 CosOp,
00145 std::cos(expr.val()),
00146 -bar*std::sin(expr.val()))
00147 FAD_UNARYOP_MACRO(sin,
00148 SinOp,
00149 std::sin(expr.val()),
00150 bar*std::cos(expr.val()))
00151 FAD_UNARYOP_MACRO(tan,
00152 TanOp,
00153 std::tan(expr.val()),
00154 bar*(value_type(1.)+ std::tan(expr.val())*std::tan(expr.val())))
00155 FAD_UNARYOP_MACRO(acos,
00156 ACosOp,
00157 std::acos(expr.val()),
00158 -bar/std::sqrt(value_type(1.)-expr.val()*expr.val()))
00159 FAD_UNARYOP_MACRO(asin,
00160 ASinOp,
00161 std::asin(expr.val()),
00162 bar/std::sqrt(value_type(1.)-expr.val()*expr.val()))
00163 FAD_UNARYOP_MACRO(atan,
00164 ATanOp,
00165 std::atan(expr.val()),
00166 bar/(value_type(1.)+expr.val()*expr.val()))
00167 FAD_UNARYOP_MACRO(cosh,
00168 CoshOp,
00169 std::cosh(expr.val()),
00170 bar*std::sinh(expr.val()))
00171 FAD_UNARYOP_MACRO(sinh,
00172 SinhOp,
00173 std::sinh(expr.val()),
00174 bar*std::cosh(expr.val()))
00175 FAD_UNARYOP_MACRO(tanh,
00176 TanhOp,
00177 std::tanh(expr.val()),
00178 bar/(std::cosh(expr.val())*std::cosh(expr.val())))
00179 FAD_UNARYOP_MACRO(acosh,
00180 ACoshOp,
00181 acosh(expr.val()),
00182 bar/std::sqrt((expr.val()-value_type(1.)) *
00183 (expr.val()+value_type(1.))))
00184 FAD_UNARYOP_MACRO(asinh,
00185 ASinhOp,
00186 asinh(expr.val()),
00187 bar/std::sqrt(value_type(1.)+expr.val()*expr.val()))
00188 FAD_UNARYOP_MACRO(atanh,
00189 ATanhOp,
00190 atanh(expr.val()),
00191 bar/(value_type(1.)-expr.val()*expr.val()))
00192 FAD_UNARYOP_MACRO(abs,
00193 AbsOp,
00194 std::abs(expr.val()),
00195 (expr.val() >= value_type(0.)) ? bar : value_type(-bar))
00196 FAD_UNARYOP_MACRO(fabs,
00197 FAbsOp,
00198 std::fabs(expr.val()),
00199 (expr.val() >= value_type(0.)) ? bar : value_type(-bar))
00200
00201 #undef FAD_UNARYOP_MACRO
00202
00203 #define FAD_BINARYOP_MACRO(OPNAME,OP,VALUE,LADJOINT,RADJOINT) \
00204 namespace Sacado { \
00205 namespace ELRFad { \
00206 \
00207 template <typename ExprT1, typename ExprT2> \
00208 class OP {}; \
00209 \
00210 template <typename ExprT1, typename ExprT2> \
00211 class Expr< OP<ExprT1,ExprT2> > { \
00212 \
00213 public: \
00214 \
00215 typedef typename ExprT1::value_type value_type_1; \
00216 typedef typename ExprT2::value_type value_type_2; \
00217 typedef typename Sacado::Promote<value_type_1, \
00218 value_type_2>::type value_type; \
00219 \
00220 typedef typename ExprT1::base_expr_type base_expr_type_1; \
00221 typedef typename ExprT2::base_expr_type base_expr_type_2; \
00222 typedef typename ExprPromote<base_expr_type_1, \
00223 base_expr_type_2>::type base_expr_type; \
00224 \
00225 static const int num_args1 = ExprT1::num_args; \
00226 static const int num_args2 = ExprT2::num_args; \
00227 static const int num_args = num_args1 + num_args2; \
00228 \
00229 Expr(const ExprT1& expr1_, const ExprT2& expr2_) : \
00230 expr1(expr1_), expr2(expr2_) {} \
00231 \
00232 int size() const { \
00233 int sz1 = expr1.size(), sz2 = expr2.size(); \
00234 return sz1 > sz2 ? sz1 : sz2; \
00235 } \
00236 \
00237 template <int Arg> bool isActive() const { \
00238 if (Arg < num_args1) \
00239 return expr1.template isActive<Arg>(); \
00240 else \
00241 return expr2.template isActive<Arg-num_args1>(); \
00242 } \
00243 \
00244 value_type val() const { \
00245 return VALUE; \
00246 } \
00247 \
00248 void computePartials(const value_type& bar, \
00249 value_type partials[]) const { \
00250 if (num_args1 > 0) \
00251 expr1.computePartials(LADJOINT, partials); \
00252 if (num_args2 > 0) \
00253 expr2.computePartials(RADJOINT, partials+num_args1); \
00254 } \
00255 \
00256 void getTangents(int i, value_type dots[]) const { \
00257 expr1.getTangents(i, dots); \
00258 expr2.getTangents(i, dots+num_args1); \
00259 } \
00260 \
00261 template <int Arg> value_type getTangent(int i) const { \
00262 if (Arg < num_args1) \
00263 return expr1.template getTangent<Arg>(i); \
00264 else \
00265 return expr2.template getTangent<Arg-num_args1>(i); \
00266 } \
00267 \
00268 protected: \
00269 \
00270 typename ExprConstRef<ExprT1>::type expr1; \
00271 typename ExprConstRef<ExprT2>::type expr2; \
00272 \
00273 }; \
00274 \
00275 template <typename T1, typename T2> \
00276 inline Expr< OP< Expr<T1>, Expr<T2> > > \
00277 OPNAME (const Expr<T1>& expr1, const Expr<T2>& expr2) \
00278 { \
00279 typedef OP< Expr<T1>, Expr<T2> > expr_t; \
00280 \
00281 return Expr<expr_t>(expr1, expr2); \
00282 } \
00283 \
00284 template <typename T> \
00285 inline Expr< OP< Expr<T>, Expr<T> > > \
00286 OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
00287 { \
00288 typedef OP< Expr<T>, Expr<T> > expr_t; \
00289 \
00290 return Expr<expr_t>(expr1, expr2); \
00291 } \
00292 \
00293 template <typename T> \
00294 inline Expr< OP< ConstExpr<typename Expr<T>::value_type>, \
00295 Expr<T> > > \
00296 OPNAME (const typename Expr<T>::value_type& c, \
00297 const Expr<T>& expr) \
00298 { \
00299 typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
00300 typedef OP< ConstT, Expr<T> > expr_t; \
00301 \
00302 return Expr<expr_t>(ConstT(c), expr); \
00303 } \
00304 \
00305 template <typename T> \
00306 inline Expr< OP< Expr<T>, \
00307 ConstExpr<typename Expr<T>::value_type> > > \
00308 OPNAME (const Expr<T>& expr, \
00309 const typename Expr<T>::value_type& c) \
00310 { \
00311 typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
00312 typedef OP< Expr<T>, ConstT > expr_t; \
00313 \
00314 return Expr<expr_t>(expr, ConstT(c)); \
00315 } \
00316 } \
00317 }
00318
00319
00320 FAD_BINARYOP_MACRO(operator+,
00321 AdditionOp,
00322 expr1.val() + expr2.val(),
00323 bar,
00324 bar)
00325 FAD_BINARYOP_MACRO(operator-,
00326 SubtractionOp,
00327 expr1.val() - expr2.val(),
00328 bar,
00329 -bar)
00330 FAD_BINARYOP_MACRO(operator*,
00331 MultiplicationOp,
00332 expr1.val() * expr2.val(),
00333 bar*expr2.val(),
00334 bar*expr1.val())
00335 FAD_BINARYOP_MACRO(operator/,
00336 DivisionOp,
00337 expr1.val() / expr2.val(),
00338 bar/expr2.val(),
00339 -bar*expr1.val()/(expr2.val()*expr2.val()))
00340 FAD_BINARYOP_MACRO(atan2,
00341 Atan2Op,
00342 std::atan2(expr1.val(), expr2.val()),
00343 bar*expr2.val()/
00344 (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
00345 bar*expr1.val()/
00346 (expr1.val()*expr1.val() + expr2.val()*expr2.val()))
00347 FAD_BINARYOP_MACRO(pow,
00348 PowerOp,
00349 std::pow(expr1.val(), expr2.val()),
00350 bar*std::pow(expr1.val(),expr2.val())*expr2.val()/
00351 expr1.val(),
00352 bar*std::pow(expr1.val(),expr2.val())*std::log(expr1.val()))
00353 FAD_BINARYOP_MACRO(max,
00354 MaxOp,
00355 std::max(expr1.val(), expr2.val()),
00356 expr1.val() >= expr2.val() ? bar : value_type(0.),
00357 expr2.val() > expr1.val() ? bar : value_type(0.))
00358 FAD_BINARYOP_MACRO(min,
00359 MinOp,
00360 std::min(expr1.val(), expr2.val()),
00361 expr1.val() <= expr2.val() ? bar : value_type(0.),
00362 expr2.val() < expr1.val() ? bar : value_type(0.))
00363
00364 #undef FAD_BINARYOP_MACRO
00365
00366
00367
00368 #define FAD_RELOP_MACRO(OP) \
00369 namespace Sacado { \
00370 namespace ELRFad { \
00371 template <typename ExprT1, typename ExprT2> \
00372 inline bool \
00373 operator OP (const Expr<ExprT1>& expr1, \
00374 const Expr<ExprT2>& expr2) \
00375 { \
00376 return expr1.val() OP expr2.val(); \
00377 } \
00378 \
00379 template <typename ExprT2> \
00380 inline bool \
00381 operator OP (const typename Expr<ExprT2>::value_type& a, \
00382 const Expr<ExprT2>& expr2) \
00383 { \
00384 return a OP expr2.val(); \
00385 } \
00386 \
00387 template <typename ExprT1> \
00388 inline bool \
00389 operator OP (const Expr<ExprT1>& expr1, \
00390 const typename Expr<ExprT1>::value_type& b) \
00391 { \
00392 return expr1.val() OP b; \
00393 } \
00394 } \
00395 }
00396
00397 FAD_RELOP_MACRO(==)
00398 FAD_RELOP_MACRO(!=)
00399 FAD_RELOP_MACRO(<)
00400 FAD_RELOP_MACRO(>)
00401 FAD_RELOP_MACRO(<=)
00402 FAD_RELOP_MACRO(>=)
00403 FAD_RELOP_MACRO(<<=)
00404 FAD_RELOP_MACRO(>>=)
00405 FAD_RELOP_MACRO(&)
00406 FAD_RELOP_MACRO(|)
00407
00408 #undef FAD_RELOP_MACRO
00409
00410 namespace Sacado {
00411
00412 namespace ELRFad {
00413
00414 template <typename ExprT>
00415 inline bool operator ! (const Expr<ExprT>& expr)
00416 {
00417 return ! expr.val();
00418 }
00419
00420 }
00421
00422 }
00423
00424
00425
00426 namespace Sacado {
00427
00428 namespace ELRFad {
00429
00430 template <typename ExprT>
00431 std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
00432 typedef typename Expr<ExprT>::base_expr_type base_expr_type;
00433 return os << base_expr_type(x);
00434 }
00435
00436 }
00437
00438 }
00439
00440
00441 #endif // SACADO_FAD_OPS_HPP