PHengLEI-NCCR/phenglei/3rdparty/Sacado/include/Sacado_ELRFad_Ops.hpp

1090 lines
64 KiB
C++

// @HEADER
// ***********************************************************************
//
// Sacado Package
// Copyright (2006) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
// USA
// Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
// (etphipp@sandia.gov).
//
// ***********************************************************************
//
// The forward-mode AD classes in Sacado are a derivative work of the
// expression template classes in the Fad package by Nicolas Di Cesare.
// The following banner is included in the original Fad source code:
//
// ************ DO NOT REMOVE THIS BANNER ****************
//
// Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
// http://www.ann.jussieu.fr/~dicesare
//
// CEMRACS 98 : C++ courses,
// templates : new C++ techniques
// for scientific computing
//
//********************************************************
//
// A short implementation ( not all operators and
// functions are overloaded ) of 1st order Automatic
// Differentiation in forward mode (FAD) using
// EXPRESSION TEMPLATES.
//
//********************************************************
// @HEADER
#ifndef SACADO_ELRFAD_OPS_HPP
#define SACADO_ELRFAD_OPS_HPP
#include "Sacado_ELRFad_Expression.hpp"
#include "Sacado_cmath.hpp"
#include <ostream> // for std::ostream
#define FAD_UNARYOP_MACRO(OPNAME,OP,VALUE,ADJOINT, \
LINEAR,DX,FASTACCESSDX) \
namespace Sacado { \
namespace ELRFad { \
\
template <typename ExprT> \
class OP {}; \
\
template <typename ExprT> \
class Expr< OP<ExprT> > { \
public: \
\
typedef typename ExprT::value_type value_type; \
typedef typename ExprT::scalar_type scalar_type; \
typedef typename ExprT::base_expr_type base_expr_type; \
\
static const int num_args = ExprT::num_args; \
\
static const bool is_linear = LINEAR; \
\
SACADO_INLINE_FUNCTION \
explicit Expr(const ExprT& expr_) : expr(expr_) {} \
\
SACADO_INLINE_FUNCTION \
int size() const { return expr.size(); } \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
bool isActive() const { return expr.template isActive<Arg>(); } \
\
SACADO_INLINE_FUNCTION \
bool isActive2(int j) const { return expr.isActive2(j); } \
\
SACADO_INLINE_FUNCTION \
bool updateValue() const { return expr.updateValue(); } \
\
SACADO_INLINE_FUNCTION \
void cache() const {} \
\
SACADO_INLINE_FUNCTION \
value_type val() const { \
return VALUE; \
} \
\
SACADO_INLINE_FUNCTION \
void computePartials(const value_type& bar, \
value_type partials[]) const { \
expr.computePartials(ADJOINT, partials); \
} \
\
SACADO_INLINE_FUNCTION \
void getTangents(int i, value_type dots[]) const { \
expr.getTangents(i, dots); } \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
const value_type& getTangent(int i) const { \
return expr.template getTangent<Arg>(i); \
} \
\
SACADO_INLINE_FUNCTION \
bool isLinear() const { \
return LINEAR; \
} \
\
SACADO_INLINE_FUNCTION \
bool hasFastAccess() const { \
return expr.hasFastAccess(); \
} \
\
SACADO_INLINE_FUNCTION \
const value_type dx(int i) const { \
return DX; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type fastAccessDx(int i) const { \
return FASTACCESSDX; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type* getDx(int j) const { \
return expr.getDx(j); \
} \
\
SACADO_INLINE_FUNCTION \
int numActiveArgs() const { \
return expr.numActiveArgs(); \
} \
\
SACADO_INLINE_FUNCTION \
void computeActivePartials(const value_type& bar, \
value_type *partials) const { \
expr.computePartials(ADJOINT, partials); \
} \
\
protected: \
\
const ExprT& expr; \
}; \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
Expr< OP< Expr<T> > > \
OPNAME (const Expr<T>& expr) \
{ \
typedef OP< Expr<T> > expr_t; \
\
return Expr<expr_t>(expr); \
} \
} \
}
FAD_UNARYOP_MACRO(operator+,
UnaryPlusOp,
expr.val(),
bar,
true,
expr.dx(i),
expr.fastAccessDx(i))
FAD_UNARYOP_MACRO(operator-,
UnaryMinusOp,
-expr.val(),
-bar,
true,
-expr.dx(i),
-expr.fastAccessDx(i))
FAD_UNARYOP_MACRO(exp,
ExpOp,
std::exp(expr.val()),
bar*std::exp(expr.val()),
false,
std::exp(expr.val())*expr.dx(i),
std::exp(expr.val())*expr.fastAccessDx(i))
FAD_UNARYOP_MACRO(log,
LogOp,
std::log(expr.val()),
bar/expr.val(),
false,
expr.dx(i)/expr.val(),
expr.fastAccessDx(i)/expr.val())
FAD_UNARYOP_MACRO(log10,
Log10Op,
std::log10(expr.val()),
bar/( std::log(value_type(10.))*expr.val() ),
false,
expr.dx(i)/( std::log(value_type(10))*expr.val()),
expr.fastAccessDx(i) / ( std::log(value_type(10))*expr.val()))
FAD_UNARYOP_MACRO(sqrt,
SqrtOp,
std::sqrt(expr.val()),
value_type(0.5)*bar/std::sqrt(expr.val()),
false,
expr.dx(i)/(value_type(2)* std::sqrt(expr.val())),
expr.fastAccessDx(i)/(value_type(2)* std::sqrt(expr.val())))
FAD_UNARYOP_MACRO(safe_sqrt,
SafeSqrtOp,
std::sqrt(expr.val()),
expr.val() == value_type(0.0) ? value_type(0.0) : value_type(value_type(0.5)*bar/std::sqrt(expr.val())),
false,
expr.val() == value_type(0.0) ? value_type(0.0) : value_type(expr.dx(i)/(value_type(2)*std::sqrt(expr.val()))),
expr.val() == value_type(0.0) ? value_type(0.0) : value_type(expr.fastAccessDx(i)/(value_type(2)*std::sqrt(expr.val()))))
FAD_UNARYOP_MACRO(cos,
CosOp,
std::cos(expr.val()),
-bar*std::sin(expr.val()),
false,
-expr.dx(i)* std::sin(expr.val()),
-expr.fastAccessDx(i)* std::sin(expr.val()))
FAD_UNARYOP_MACRO(sin,
SinOp,
std::sin(expr.val()),
bar*std::cos(expr.val()),
false,
expr.dx(i)* std::cos(expr.val()),
expr.fastAccessDx(i)* std::cos(expr.val()))
FAD_UNARYOP_MACRO(tan,
TanOp,
std::tan(expr.val()),
bar*(value_type(1.)+ std::tan(expr.val())*std::tan(expr.val())),
false,
expr.dx(i)*
(value_type(1)+ std::tan(expr.val())* std::tan(expr.val())),
expr.fastAccessDx(i)*
(value_type(1)+ std::tan(expr.val())* std::tan(expr.val())))
FAD_UNARYOP_MACRO(acos,
ACosOp,
std::acos(expr.val()),
-bar/std::sqrt(value_type(1.)-expr.val()*expr.val()),
false,
-expr.dx(i)/ std::sqrt(value_type(1)-expr.val()*expr.val()),
-expr.fastAccessDx(i) /
std::sqrt(value_type(1)-expr.val()*expr.val()))
FAD_UNARYOP_MACRO(asin,
ASinOp,
std::asin(expr.val()),
bar/std::sqrt(value_type(1.)-expr.val()*expr.val()),
false,
expr.dx(i)/ std::sqrt(value_type(1)-expr.val()*expr.val()),
expr.fastAccessDx(i) /
std::sqrt(value_type(1)-expr.val()*expr.val()))
FAD_UNARYOP_MACRO(atan,
ATanOp,
std::atan(expr.val()),
bar/(value_type(1.)+expr.val()*expr.val()),
false,
expr.dx(i)/(value_type(1)+expr.val()*expr.val()),
expr.fastAccessDx(i)/(value_type(1)+expr.val()*expr.val()))
FAD_UNARYOP_MACRO(cosh,
CoshOp,
std::cosh(expr.val()),
bar*std::sinh(expr.val()),
false,
expr.dx(i)* std::sinh(expr.val()),
expr.fastAccessDx(i)* std::sinh(expr.val()))
FAD_UNARYOP_MACRO(sinh,
SinhOp,
std::sinh(expr.val()),
bar*std::cosh(expr.val()),
false,
expr.dx(i)* std::cosh(expr.val()),
expr.fastAccessDx(i)* std::cosh(expr.val()))
FAD_UNARYOP_MACRO(tanh,
TanhOp,
std::tanh(expr.val()),
bar*(value_type(1)-std::tanh(expr.val())*std::tanh(expr.val())),
false,
expr.dx(i)*(value_type(1)-std::tanh(expr.val())*std::tanh(expr.val())),
expr.fastAccessDx(i)*(value_type(1)-std::tanh(expr.val())*std::tanh(expr.val())))
FAD_UNARYOP_MACRO(acosh,
ACoshOp,
std::acosh(expr.val()),
bar/std::sqrt((expr.val()-value_type(1.)) *
(expr.val()+value_type(1.))),
false,
expr.dx(i)/ std::sqrt((expr.val()-value_type(1)) *
(expr.val()+value_type(1))),
expr.fastAccessDx(i)/ std::sqrt((expr.val()-value_type(1)) *
(expr.val()+value_type(1))))
FAD_UNARYOP_MACRO(asinh,
ASinhOp,
std::asinh(expr.val()),
bar/std::sqrt(value_type(1.)+expr.val()*expr.val()),
false,
expr.dx(i)/ std::sqrt(value_type(1)+expr.val()*expr.val()),
expr.fastAccessDx(i)/ std::sqrt(value_type(1)+
expr.val()*expr.val()))
FAD_UNARYOP_MACRO(atanh,
ATanhOp,
std::atanh(expr.val()),
bar/(value_type(1.)-expr.val()*expr.val()),
false,
expr.dx(i)/(value_type(1)-expr.val()*expr.val()),
expr.fastAccessDx(i)/(value_type(1)-
expr.val()*expr.val()))
FAD_UNARYOP_MACRO(abs,
AbsOp,
std::abs(expr.val()),
(expr.val() >= value_type(0.)) ? bar : value_type(-bar),
false,
expr.val() >= 0 ? value_type(+expr.dx(i)) :
value_type(-expr.dx(i)),
expr.val() >= 0 ? value_type(+expr.fastAccessDx(i)) :
value_type(-expr.fastAccessDx(i)))
FAD_UNARYOP_MACRO(fabs,
FAbsOp,
std::fabs(expr.val()),
(expr.val() >= value_type(0.)) ? bar : value_type(-bar),
false,
expr.val() >= 0 ? value_type(+expr.dx(i)) :
value_type(-expr.dx(i)),
expr.val() >= 0 ? value_type(+expr.fastAccessDx(i)) :
value_type(-expr.fastAccessDx(i)))
#ifdef HAVE_SACADO_CXX11
FAD_UNARYOP_MACRO(cbrt,
CbrtOp,
std::cbrt(expr.val()),
bar/(value_type(3)*std::cbrt(expr.val()*expr.val())),
false,
expr.dx(i)/(value_type(3)*std::cbrt(expr.val()*expr.val())),
expr.fastAccessDx(i)/(value_type(3)*std::cbrt(expr.val()*expr.val())))
#endif
#undef FAD_UNARYOP_MACRO
#define FAD_BINARYOP_MACRO( \
OPNAME,OP,VALUE,LADJOINT,RADJOINT, \
LINEAR,CONST_LINEAR_1, CONST_LINEAR_2, \
LINEAR_2,CONST_LINEAR_1_2, CONST_LINEAR_2_2, \
DX,FASTACCESSDX,CONST_DX_1,CONST_DX_2, \
CONST_FASTACCESSDX_1,CONST_FASTACCESSDX_2) \
namespace Sacado { \
namespace ELRFad { \
\
template <typename ExprT1, typename ExprT2> \
class OP {}; \
\
template <typename ExprT1, typename ExprT2> \
class Expr< OP<ExprT1,ExprT2> > { \
\
public: \
\
typedef typename ExprT1::value_type value_type_1; \
typedef typename ExprT2::value_type value_type_2; \
typedef typename Sacado::Promote<value_type_1, \
value_type_2>::type value_type; \
\
typedef typename ExprT1::scalar_type scalar_type_1; \
typedef typename ExprT2::scalar_type scalar_type_2; \
typedef typename Sacado::Promote<scalar_type_1, \
scalar_type_2>::type scalar_type; \
\
typedef typename ExprT1::base_expr_type base_expr_type_1; \
typedef typename ExprT2::base_expr_type base_expr_type_2; \
typedef typename Sacado::Promote<base_expr_type_1, \
base_expr_type_2>::type base_expr_type; \
\
static const int num_args1 = ExprT1::num_args; \
static const int num_args2 = ExprT2::num_args; \
static const int num_args = num_args1 + num_args2; \
\
static const bool is_linear = LINEAR_2; \
\
SACADO_INLINE_FUNCTION \
Expr(const ExprT1& expr1_, const ExprT2& expr2_) : \
expr1(expr1_), expr2(expr2_) {} \
\
SACADO_INLINE_FUNCTION \
int size() const { \
int sz1 = expr1.size(), sz2 = expr2.size(); \
return sz1 > sz2 ? sz1 : sz2; \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
bool isActive() const { \
if (Arg < num_args1) \
return expr1.template isActive<Arg>(); \
else \
return expr2.template isActive<Arg-num_args1>(); \
} \
\
SACADO_INLINE_FUNCTION \
bool isActive2(int j) const { \
if (j < num_args1) \
return expr1.isActive2(j); \
else \
return expr2.isActive2(j); \
} \
\
SACADO_INLINE_FUNCTION \
bool updateValue() const { \
return expr1.updateValue() && expr2.updateValue(); \
} \
\
SACADO_INLINE_FUNCTION \
void cache() const {} \
\
SACADO_INLINE_FUNCTION \
value_type val() const { \
return VALUE; \
} \
\
SACADO_INLINE_FUNCTION \
void computePartials(const value_type& bar, \
value_type partials[]) const { \
if (num_args1 > 0) \
expr1.computePartials(LADJOINT, partials); \
if (num_args2 > 0) \
expr2.computePartials(RADJOINT, partials+num_args1); \
} \
\
SACADO_INLINE_FUNCTION \
void getTangents(int i, value_type dots[]) const { \
expr1.getTangents(i, dots); \
expr2.getTangents(i, dots+num_args1); \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
const value_type& getTangent(int i) const { \
if (Arg < num_args1) \
return expr1.template getTangent<Arg>(i); \
else \
return expr2.template getTangent<Arg-num_args1>(i); \
} \
\
SACADO_INLINE_FUNCTION \
bool isLinear() const { \
return LINEAR; \
} \
\
SACADO_INLINE_FUNCTION \
bool hasFastAccess() const { \
return expr1.hasFastAccess() && expr2.hasFastAccess(); \
} \
\
SACADO_INLINE_FUNCTION \
const value_type dx(int i) const { \
return DX; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type fastAccessDx(int i) const { \
return FASTACCESSDX; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type* getDx(int j) const { \
if (j < num_args1) \
return expr1.getDx(j); \
else \
return expr2.getDx(j-num_args1); \
} \
\
SACADO_INLINE_FUNCTION \
int numActiveArgs() const { \
return expr1.numActiveArgs() + expr2.numActiveArgs(); \
} \
\
SACADO_INLINE_FUNCTION \
void computeActivePartials(const value_type& bar, \
value_type *partials) const { \
if (expr1.numActiveArgs() > 0) \
expr1.computePartials(LADJOINT, partials); \
if (expr2.numActiveArgs() > 0) \
expr2.computePartials(RADJOINT, partials+expr2.numActiveArgs()); \
} \
protected: \
\
typename ExprConstRef<ExprT1>::type expr1; \
typename ExprConstRef<ExprT2>::type expr2; \
\
}; \
\
template <typename ExprT1, typename T2> \
class Expr< OP<ExprT1, ConstExpr<T2> > > { \
\
public: \
\
typedef ConstExpr<T2> ExprT2; \
typedef typename ExprT1::value_type value_type_1; \
typedef typename ExprT2::value_type value_type_2; \
typedef typename Sacado::Promote<value_type_1, \
value_type_2>::type value_type; \
\
typedef typename ExprT1::scalar_type scalar_type_1; \
typedef typename ExprT2::scalar_type scalar_type_2; \
typedef typename Sacado::Promote<scalar_type_1, \
scalar_type_2>::type scalar_type; \
\
typedef typename ExprT1::base_expr_type base_expr_type_1; \
typedef typename ExprT2::base_expr_type base_expr_type_2; \
typedef typename Sacado::Promote<base_expr_type_1, \
base_expr_type_2>::type base_expr_type; \
\
static const int num_args = ExprT1::num_args; \
\
static const bool is_linear = CONST_LINEAR_2_2; \
\
SACADO_INLINE_FUNCTION \
Expr(const ExprT1& expr1_, const ExprT2& expr2_) : \
expr1(expr1_), expr2(expr2_) {} \
\
SACADO_INLINE_FUNCTION \
int size() const { \
return expr1.size(); \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
bool isActive() const { \
return expr1.template isActive<Arg>(); \
} \
\
SACADO_INLINE_FUNCTION \
bool isActive2(int j) const { return expr1.isActive2(j); } \
\
SACADO_INLINE_FUNCTION \
bool updateValue() const { \
return expr1.updateValue(); \
} \
\
SACADO_INLINE_FUNCTION \
void cache() const {} \
\
SACADO_INLINE_FUNCTION \
value_type val() const { \
return VALUE; \
} \
\
SACADO_INLINE_FUNCTION \
void computePartials(const value_type& bar, \
value_type partials[]) const { \
expr1.computePartials(LADJOINT, partials); \
} \
\
SACADO_INLINE_FUNCTION \
void getTangents(int i, value_type dots[]) const { \
expr1.getTangents(i, dots); \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
const value_type& getTangent(int i) const { \
return expr1.template getTangent<Arg>(i); \
} \
\
SACADO_INLINE_FUNCTION \
bool isLinear() const { \
return CONST_LINEAR_2; \
} \
\
SACADO_INLINE_FUNCTION \
bool hasFastAccess() const { \
return expr1.hasFastAccess(); \
} \
\
SACADO_INLINE_FUNCTION \
const value_type dx(int i) const { \
return CONST_DX_2; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type fastAccessDx(int i) const { \
return CONST_FASTACCESSDX_2; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type* getDx(int j) const { \
return expr1.getDx(j); \
} \
\
SACADO_INLINE_FUNCTION \
int numActiveArgs() const { \
return expr1.numActiveArgs(); \
} \
\
SACADO_INLINE_FUNCTION \
void computeActivePartials(const value_type& bar, \
value_type *partials) const { \
expr1.computePartials(LADJOINT, partials); \
} \
\
protected: \
\
typename ExprConstRef<ExprT1>::type expr1; \
typename ExprConstRef<ExprT2>::type expr2; \
\
}; \
\
template <typename T1, typename ExprT2> \
class Expr< OP<ConstExpr<T1>,ExprT2> > { \
\
public: \
\
typedef ConstExpr<T1> ExprT1; \
typedef typename ExprT1::value_type value_type_1; \
typedef typename ExprT2::value_type value_type_2; \
typedef typename Sacado::Promote<value_type_1, \
value_type_2>::type value_type; \
\
typedef typename ExprT1::scalar_type scalar_type_1; \
typedef typename ExprT2::scalar_type scalar_type_2; \
typedef typename Sacado::Promote<scalar_type_1, \
scalar_type_2>::type scalar_type; \
\
typedef typename ExprT1::base_expr_type base_expr_type_1; \
typedef typename ExprT2::base_expr_type base_expr_type_2; \
typedef typename Sacado::Promote<base_expr_type_1, \
base_expr_type_2>::type base_expr_type; \
\
static const int num_args = ExprT2::num_args; \
\
static const bool is_linear = CONST_LINEAR_1_2; \
\
SACADO_INLINE_FUNCTION \
Expr(const ExprT1& expr1_, const ExprT2& expr2_) : \
expr1(expr1_), expr2(expr2_) {} \
\
SACADO_INLINE_FUNCTION \
int size() const { \
return expr2.size(); \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
bool isActive() const { \
return expr2.template isActive<Arg>(); \
} \
\
SACADO_INLINE_FUNCTION \
bool isActive2(int j) const { return expr2.isActive2(j); } \
\
SACADO_INLINE_FUNCTION \
bool updateValue() const { \
return expr2.updateValue(); \
} \
\
SACADO_INLINE_FUNCTION \
void cache() const {} \
\
SACADO_INLINE_FUNCTION \
value_type val() const { \
return VALUE; \
} \
\
SACADO_INLINE_FUNCTION \
void computePartials(const value_type& bar, \
value_type partials[]) const { \
expr2.computePartials(RADJOINT, partials); \
} \
\
SACADO_INLINE_FUNCTION \
void getTangents(int i, value_type dots[]) const { \
expr2.getTangents(i, dots); \
} \
\
template <int Arg> \
SACADO_INLINE_FUNCTION \
const value_type& getTangent(int i) const { \
return expr2.template getTangent<Arg>(i); \
} \
\
SACADO_INLINE_FUNCTION \
bool isLinear() const { \
return CONST_LINEAR_1; \
} \
\
SACADO_INLINE_FUNCTION \
bool hasFastAccess() const { \
return expr2.hasFastAccess(); \
} \
\
SACADO_INLINE_FUNCTION \
const value_type dx(int i) const { \
return CONST_DX_1; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type fastAccessDx(int i) const { \
return CONST_FASTACCESSDX_1; \
} \
\
SACADO_INLINE_FUNCTION \
const value_type* getDx(int j) const { \
return expr2.getDx(j); \
} \
\
SACADO_INLINE_FUNCTION \
int numActiveArgs() const { \
return expr2.numActiveArgs(); \
} \
\
SACADO_INLINE_FUNCTION \
void computeActivePartials(const value_type& bar, \
value_type *partials) const { \
expr2.computePartials(RADJOINT, partials); \
} \
protected: \
\
typename ExprConstRef<ExprT1>::type expr1; \
typename ExprConstRef<ExprT2>::type expr2; \
\
}; \
\
template <typename T1, typename T2> \
SACADO_INLINE_FUNCTION \
SACADO_FAD_OP_ENABLE_EXPR_EXPR(OP) \
OPNAME (const T1& expr1, const T2& expr2) \
{ \
typedef OP< T1, T2 > expr_t; \
\
return Expr<expr_t>(expr1, expr2); \
} \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
Expr< OP< Expr<T>, Expr<T> > > \
OPNAME (const Expr<T>& expr1, const Expr<T>& expr2) \
{ \
typedef OP< Expr<T>, Expr<T> > expr_t; \
\
return Expr<expr_t>(expr1, expr2); \
} \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
Expr< OP< ConstExpr<typename Expr<T>::value_type>, \
Expr<T> > > \
OPNAME (const typename Expr<T>::value_type& c, \
const Expr<T>& expr) \
{ \
typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
typedef OP< ConstT, Expr<T> > expr_t; \
\
return Expr<expr_t>(ConstT(c), expr); \
} \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
Expr< OP< Expr<T>, \
ConstExpr<typename Expr<T>::value_type> > > \
OPNAME (const Expr<T>& expr, \
const typename Expr<T>::value_type& c) \
{ \
typedef ConstExpr<typename Expr<T>::value_type> ConstT; \
typedef OP< Expr<T>, ConstT > expr_t; \
\
return Expr<expr_t>(expr, ConstT(c)); \
} \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
SACADO_FAD_OP_ENABLE_SCALAR_EXPR(OP) \
OPNAME (const typename Expr<T>::scalar_type& c, \
const Expr<T>& expr) \
{ \
typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
typedef OP< ConstT, Expr<T> > expr_t; \
\
return Expr<expr_t>(ConstT(c), expr); \
} \
\
template <typename T> \
SACADO_INLINE_FUNCTION \
SACADO_FAD_OP_ENABLE_EXPR_SCALAR(OP) \
OPNAME (const Expr<T>& expr, \
const typename Expr<T>::scalar_type& c) \
{ \
typedef ConstExpr<typename Expr<T>::scalar_type> ConstT; \
typedef OP< Expr<T>, ConstT > expr_t; \
\
return Expr<expr_t>(expr, ConstT(c)); \
} \
} \
}
FAD_BINARYOP_MACRO(operator+,
AdditionOp,
expr1.val() + expr2.val(),
bar,
bar,
expr1.isLinear() && expr2.isLinear(),
expr2.isLinear(),
expr1.isLinear(),
ExprT1::is_linear && ExprT2::is_linear,
ExprT2::is_linear,
ExprT1::is_linear,
expr1.dx(i) + expr2.dx(i),
expr1.fastAccessDx(i) + expr2.fastAccessDx(i),
expr2.dx(i),
expr1.dx(i),
expr2.fastAccessDx(i),
expr1.fastAccessDx(i))
FAD_BINARYOP_MACRO(operator-,
SubtractionOp,
expr1.val() - expr2.val(),
bar,
-bar,
expr1.isLinear() && expr2.isLinear(),
expr2.isLinear(),
expr1.isLinear(),
ExprT1::is_linear && ExprT2::is_linear,
ExprT2::is_linear,
ExprT1::is_linear,
expr1.dx(i) - expr2.dx(i),
expr1.fastAccessDx(i) - expr2.fastAccessDx(i),
-expr2.dx(i),
expr1.dx(i),
-expr2.fastAccessDx(i),
expr1.fastAccessDx(i))
FAD_BINARYOP_MACRO(operator*,
MultiplicationOp,
expr1.val() * expr2.val(),
bar*expr2.val(),
bar*expr1.val(),
false,
expr2.isLinear(),
expr1.isLinear(),
false,
ExprT2::is_linear,
ExprT1::is_linear,
expr1.val()*expr2.dx(i) + expr1.dx(i)*expr2.val(),
expr1.val()*expr2.fastAccessDx(i) +
expr1.fastAccessDx(i)*expr2.val(),
expr1.val()*expr2.dx(i),
expr1.dx(i)*expr2.val(),
expr1.val()*expr2.fastAccessDx(i),
expr1.fastAccessDx(i)*expr2.val())
FAD_BINARYOP_MACRO(operator/,
DivisionOp,
expr1.val() / expr2.val(),
bar/expr2.val(),
-bar*expr1.val()/(expr2.val()*expr2.val()),
false,
false,
expr1.isLinear(),
false,
false,
ExprT1::is_linear,
(expr1.dx(i)*expr2.val() - expr2.dx(i)*expr1.val()) /
(expr2.val()*expr2.val()),
(expr1.fastAccessDx(i)*expr2.val() -
expr2.fastAccessDx(i)*expr1.val()) /
(expr2.val()*expr2.val()),
-expr2.dx(i)*expr1.val() / (expr2.val()*expr2.val()),
expr1.dx(i)/expr2.val(),
-expr2.fastAccessDx(i)*expr1.val() / (expr2.val()*expr2.val()),
expr1.fastAccessDx(i)/expr2.val())
FAD_BINARYOP_MACRO(atan2,
Atan2Op,
std::atan2(expr1.val(), expr2.val()),
bar*expr2.val()/
(expr1.val()*expr1.val() + expr2.val()*expr2.val()),
-bar*expr1.val()/
(expr1.val()*expr1.val() + expr2.val()*expr2.val()),
false,
false,
false,
false,
false,
false,
(expr2.val()*expr1.dx(i) - expr1.val()*expr2.dx(i))/ (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
(expr2.val()*expr1.fastAccessDx(i) - expr1.val()*expr2.fastAccessDx(i))/
(expr1.val()*expr1.val() + expr2.val()*expr2.val()),
(-expr1.val()*expr2.dx(i)) / (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
(expr2.val()*expr1.dx(i))/ (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
(-expr1.val()*expr2.fastAccessDx(i))/ (expr1.val()*expr1.val() + expr2.val()*expr2.val()),
(expr2.val()*expr1.fastAccessDx(i))/ (expr1.val()*expr1.val() + expr2.val()*expr2.val()))
FAD_BINARYOP_MACRO(pow,
PowerOp,
std::pow(expr1.val(), expr2.val()),
expr2.size() == 0 && expr2.val() == value_type(1) ? bar : expr1.val() == value_type(0) ? value_type(0) : value_type(bar*std::pow(expr1.val(),expr2.val())*expr2.val()/expr1.val()),
expr1.val() == value_type(0) ? value_type(0) : value_type(bar*std::pow(expr1.val(),expr2.val())*std::log(expr1.val())),
false,
false,
false,
false,
false,
false,
expr1.val() == value_type(0) ? value_type(0) : value_type((expr2.dx(i)*std::log(expr1.val())+expr2.val()*expr1.dx(i)/expr1.val())*std::pow(expr1.val(),expr2.val())),
expr1.val() == value_type(0) ? value_type(0) : value_type((expr2.fastAccessDx(i)*std::log(expr1.val())+expr2.val()*expr1.fastAccessDx(i)/expr1.val())*std::pow(expr1.val(),expr2.val())),
expr1.val() == value_type(0) ? value_type(0) : value_type(expr2.dx(i)*std::log(expr1.val())*std::pow(expr1.val(),expr2.val())),
expr2.val() == value_type(1) ? expr1.dx(i) : expr1.val() == value_type(0) ? value_type(0) : value_type(expr2.val()*expr1.dx(i)/expr1.val()*std::pow(expr1.val(),expr2.val())),
expr1.val() == value_type(0) ? value_type(0) : value_type(expr2.fastAccessDx(i)*std::log(expr1.val())*std::pow(expr1.val(),expr2.val())),
expr2.val() == value_type(1) ? expr1.fastAccessDx(i) : expr1.val() == value_type(0) ? value_type(0) : value_type(expr2.val()*expr1.fastAccessDx(i)/expr1.val()*std::pow(expr1.val(),expr2.val())))
FAD_BINARYOP_MACRO(max,
MaxOp,
expr1.val() >= expr2.val() ? expr1.val() : expr2.val(),
expr1.val() >= expr2.val() ? bar : value_type(0.),
expr2.val() > expr1.val() ? bar : value_type(0.),
expr1.isLinear() && expr2.isLinear(),
expr2.isLinear(),
expr1.isLinear(),
ExprT1::is_linear && ExprT2::is_linear,
ExprT2::is_linear,
ExprT1::is_linear,
expr1.val() >= expr2.val() ? expr1.dx(i) : expr2.dx(i),
expr1.val() >= expr2.val() ? expr1.fastAccessDx(i) :
expr2.fastAccessDx(i),
expr1.val() >= expr2.val() ? value_type(0) : expr2.dx(i),
expr1.val() >= expr2.val() ? expr1.dx(i) : value_type(0),
expr1.val() >= expr2.val() ? value_type(0) :
expr2.fastAccessDx(i),
expr1.val() >= expr2.val() ? expr1.fastAccessDx(i) :
value_type(0))
FAD_BINARYOP_MACRO(min,
MinOp,
expr1.val() <= expr2.val() ? expr1.val() : expr2.val(),
expr1.val() <= expr2.val() ? bar : value_type(0.),
expr2.val() < expr1.val() ? bar : value_type(0.),
expr1.isLinear() && expr2.isLinear(),
expr2.isLinear(),
expr1.isLinear(),
ExprT1::is_linear && ExprT2::is_linear,
ExprT2::is_linear,
ExprT1::is_linear,
expr1.val() <= expr2.val() ? expr1.dx(i) : expr2.dx(i),
expr1.val() <= expr2.val() ? expr1.fastAccessDx(i) :
expr2.fastAccessDx(i),
expr1.val() <= expr2.val() ? value_type(0) : expr2.dx(i),
expr1.val() <= expr2.val() ? expr1.dx(i) : value_type(0),
expr1.val() <= expr2.val() ? value_type(0) :
expr2.fastAccessDx(i),
expr1.val() <= expr2.val() ? expr1.fastAccessDx(i) :
value_type(0))
#undef FAD_BINARYOP_MACRO
//-------------------------- Relational Operators -----------------------
#define FAD_RELOP_MACRO(OP) \
namespace Sacado { \
namespace ELRFad { \
template <typename ExprT1, typename ExprT2> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const Expr<ExprT1>& expr1, \
const Expr<ExprT2>& expr2) \
{ \
return expr1.val() OP expr2.val(); \
} \
\
template <typename ExprT2> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const typename Expr<ExprT2>::value_type& a, \
const Expr<ExprT2>& expr2) \
{ \
return a OP expr2.val(); \
} \
\
template <typename ExprT1> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const Expr<ExprT1>& expr1, \
const typename Expr<ExprT1>::value_type& b) \
{ \
return expr1.val() OP b; \
} \
} \
}
FAD_RELOP_MACRO(==)
FAD_RELOP_MACRO(!=)
FAD_RELOP_MACRO(<)
FAD_RELOP_MACRO(>)
FAD_RELOP_MACRO(<=)
FAD_RELOP_MACRO(>=)
FAD_RELOP_MACRO(<<=)
FAD_RELOP_MACRO(>>=)
FAD_RELOP_MACRO(&)
FAD_RELOP_MACRO(|)
#undef FAD_RELOP_MACRO
namespace Sacado {
namespace ELRFad {
template <typename ExprT>
SACADO_INLINE_FUNCTION
bool operator ! (const Expr<ExprT>& expr)
{
return ! expr.val();
}
} // namespace ELRFad
} // namespace Sacado
//-------------------------- Boolean Operators -----------------------
namespace Sacado {
namespace ELRFad {
template <typename ExprT>
SACADO_INLINE_FUNCTION
bool toBool(const Expr<ExprT>& x) {
bool is_zero = (x.val() == 0.0);
for (int i=0; i<x.size(); i++)
is_zero = is_zero && (x.dx(i) == 0.0);
return !is_zero;
}
} // namespace Fad
} // namespace Sacado
#define FAD_BOOL_MACRO(OP) \
namespace Sacado { \
namespace ELRFad { \
template <typename ExprT1, typename ExprT2> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const Expr<ExprT1>& expr1, \
const Expr<ExprT2>& expr2) \
{ \
return toBool(expr1) OP toBool(expr2); \
} \
\
template <typename ExprT2> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const typename Expr<ExprT2>::value_type& a, \
const Expr<ExprT2>& expr2) \
{ \
return a OP toBool(expr2); \
} \
\
template <typename ExprT1> \
SACADO_INLINE_FUNCTION \
bool \
operator OP (const Expr<ExprT1>& expr1, \
const typename Expr<ExprT1>::value_type& b) \
{ \
return toBool(expr1) OP b; \
} \
} \
}
FAD_BOOL_MACRO(&&)
FAD_BOOL_MACRO(||)
#undef FAD_BOOL_MACRO
//-------------------------- I/O Operators -----------------------
namespace Sacado {
namespace ELRFad {
template <typename ExprT>
std::ostream& operator << (std::ostream& os, const Expr<ExprT>& x) {
os << x.val() << " [";
for (int i=0; i< x.size(); i++) {
os << " " << x.dx(i);
}
os << " ]";
return os;
}
} // namespace Fad
} // namespace Sacado
#endif // SACADO_FAD_OPS_HPP