877 template <
typename T1,
typename T2,
878 bool is_const_T1,
bool is_const_T2,
879 typename ExprSpec,
typename Impl >
885 template <
typename T1,
typename T2>
888 public Expr< PowerOp< T1, T2, false, false, ExprSpecDefault,
889 PowerImpl::Simd > > {
892 typedef typename std::remove_cv<T1>::type ExprT1;
893 typedef typename std::remove_cv<T2>::type ExprT2;
894 typedef typename ExprT1::value_type value_type_1;
895 typedef typename ExprT2::value_type value_type_2;
897 value_type_2>::type value_type;
899 typedef typename ExprT1::scalar_type scalar_type_1;
900 typedef typename ExprT2::scalar_type scalar_type_2;
902 scalar_type_2>::type scalar_type;
904 typedef ExprSpecDefault expr_spec_type;
908 expr1(expr1_), expr2(expr2_) {}
912 const int sz1 = expr1.size(), sz2 = expr2.size();
913 return sz1 > sz2 ? sz1 : sz2;
917 bool hasFastAccess()
const {
918 return expr1.hasFastAccess() && expr2.hasFastAccess();
922 value_type
val()
const {
924 return pow(expr1.val(), expr2.val());
928 value_type
dx(
int i)
const {
930 const int sz1 = expr1.size(), sz2 = expr2.size();
931 if (sz1 > 0 && sz2 > 0)
932 return if_then_else( expr1.val() == scalar_type(0.0), value_type(0.0), value_type((expr2.dx(
i)*log(expr1.val())+expr2.val()*expr1.dx(
i)/expr1.val())*pow(expr1.val(),expr2.val())) );
936 return if_then_else( expr2.val() == scalar_type(1.0), expr1.dx(
i), if_then_else(expr1.val() == scalar_type(0.0), value_type(0.0), value_type(expr2.val()*expr1.dx(
i)/expr1.val()*pow(expr1.val(),expr2.val())) ));
938 return if_then_else( expr1.val() == scalar_type(0.0), value_type(0.0), value_type(expr2.dx(
i)*log(expr1.val())*pow(expr1.val(),expr2.val())) );
944 return if_then_else( expr1.val() == scalar_type(0.0), value_type(0.0), value_type((expr2.fastAccessDx(
i)*log(expr1.val())+expr2.val()*expr1.fastAccessDx(
i)/expr1.val())*pow(expr1.val(),expr2.val())));
954 template <
typename T1,
typename T2>
957 public Expr< PowerOp< T1, T2, false, true, ExprSpecDefault,
958 PowerImpl::Simd > > {
961 typedef typename std::remove_cv<T1>::type ExprT1;
963 typedef typename ExprT1::value_type value_type;
964 typedef typename ExprT1::scalar_type scalar_type;
966 typedef ExprSpecDefault expr_spec_type;
970 expr1(expr1_),
c(
c_) {}
978 bool hasFastAccess()
const {
979 return expr1.hasFastAccess();
983 value_type
val()
const {
985 return pow(expr1.val(),
c);
989 value_type
dx(
int i)
const {
993 return if_then_else(
c == scalar_type(1.0), expr1.dx(
i), if_then_else( expr1.val() == scalar_type(0.0), value_type(0.0), value_type(
c*expr1.dx(
i)/expr1.val()*pow(expr1.val(),
c)) ));
1001 return if_then_else(
c == scalar_type(1.0), expr1.fastAccessDx(
i), if_then_else( expr1.val() == scalar_type(0.0), value_type(0.0), value_type(
c*expr1.fastAccessDx(
i)/expr1.val()*pow(expr1.val(),
c)) ));
1010 template <
typename T1,
typename T2>
1013 public Expr< PowerOp< T1, T2, true, false, ExprSpecDefault,
1014 PowerImpl::Simd > > {
1017 typedef typename std::remove_cv<T2>::type ExprT2;
1019 typedef typename ExprT2::value_type value_type;
1020 typedef typename ExprT2::scalar_type scalar_type;
1022 typedef ExprSpecDefault expr_spec_type;
1026 c(
c_), expr2(expr2_) {}
1030 return expr2.size();
1034 bool hasFastAccess()
const {
1035 return expr2.hasFastAccess();
1039 value_type
val()
const {
1041 return pow(
c, expr2.val());
1045 value_type
dx(
int i)
const {
1047 return if_then_else(
c == scalar_type(0.0), value_type(0.0), value_type(expr2.dx(
i)*log(
c)*pow(
c,expr2.val())) );
1053 return if_then_else(
c == scalar_type(0.0), value_type(0.0), value_type(expr2.fastAccessDx(
i)*log(
c)*pow(
c,expr2.val())) );
1066 template <
typename T1,
typename T2>
1068 PowerImpl::Scalar > :
1069 public Expr< PowerOp< T1, T2, false, false, ExprSpecDefault,
1070 PowerImpl::Scalar > > {
1073 typedef typename std::remove_cv<T1>::type ExprT1;
1074 typedef typename std::remove_cv<T2>::type ExprT2;
1075 typedef typename ExprT1::value_type value_type_1;
1076 typedef typename ExprT2::value_type value_type_2;
1078 value_type_2>::type value_type;
1080 typedef typename ExprT1::scalar_type scalar_type_1;
1081 typedef typename ExprT2::scalar_type scalar_type_2;
1083 scalar_type_2>::type scalar_type;
1085 typedef ExprSpecDefault expr_spec_type;
1089 expr1(expr1_), expr2(expr2_) {}
1093 const int sz1 = expr1.size(), sz2 = expr2.size();
1094 return sz1 > sz2 ? sz1 : sz2;
1098 bool hasFastAccess()
const {
1099 return expr1.hasFastAccess() && expr2.hasFastAccess();
1103 value_type
val()
const {
1105 return pow(expr1.val(), expr2.val());
1109 value_type
dx(
int i)
const {
1110 using std::pow;
using std::log;
1111 const int sz1 = expr1.size(), sz2 = expr2.size();
1112 if (sz1 > 0 && sz2 > 0)
1113 return expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type((expr2.dx(
i)*log(expr1.val())+expr2.val()*expr1.dx(
i)/expr1.val())*pow(expr1.val(),expr2.val()));
1117 return expr2.val() == scalar_type(1.0) ? expr1.dx(
i) : expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type(expr2.val()*expr1.dx(
i)/expr1.val()*pow(expr1.val(),expr2.val()));
1119 return expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type(expr2.dx(
i)*log(expr1.val())*pow(expr1.val(),expr2.val()));
1124 using std::pow;
using std::log;
1125 return expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type((expr2.fastAccessDx(
i)*log(expr1.val())+expr2.val()*expr1.fastAccessDx(
i)/expr1.val())*pow(expr1.val(),expr2.val()));
1135 template <
typename T1,
typename T2>
1137 PowerImpl::Scalar > :
1138 public Expr< PowerOp< T1, T2, false, true, ExprSpecDefault,
1139 PowerImpl::Scalar > > {
1142 typedef typename std::remove_cv<T1>::type ExprT1;
1144 typedef typename ExprT1::value_type value_type;
1145 typedef typename ExprT1::scalar_type scalar_type;
1147 typedef ExprSpecDefault expr_spec_type;
1151 expr1(expr1_),
c(
c_) {}
1155 return expr1.size();
1159 bool hasFastAccess()
const {
1160 return expr1.hasFastAccess();
1164 value_type
val()
const {
1166 return pow(expr1.val(),
c);
1170 value_type
dx(
int i)
const {
1174 return c == scalar_type(1.0) ? expr1.dx(
i) : expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type(
c*expr1.dx(
i)/expr1.val()*pow(expr1.val(),
c));
1182 return c == scalar_type(1.0) ? expr1.fastAccessDx(
i) : expr1.val() == scalar_type(0.0) ? value_type(0.0) : value_type(
c*expr1.fastAccessDx(
i)/expr1.val()*pow(expr1.val(),
c));
1191 template <
typename T1,
typename T2>
1193 PowerImpl::Scalar > :
1194 public Expr< PowerOp< T1, T2, true, false, ExprSpecDefault,
1195 PowerImpl::Scalar > > {
1198 typedef typename std::remove_cv<T2>::type ExprT2;
1200 typedef typename ExprT2::value_type value_type;
1201 typedef typename ExprT2::scalar_type scalar_type;
1203 typedef ExprSpecDefault expr_spec_type;
1207 c(
c_), expr2(expr2_) {}
1211 return expr2.size();
1215 bool hasFastAccess()
const {
1216 return expr2.hasFastAccess();
1220 value_type
val()
const {
1222 return pow(
c, expr2.val());
1226 value_type
dx(
int i)
const {
1227 using std::pow;
using std::log;
1228 return c == scalar_type(0.0) ? value_type(0.0) : value_type(expr2.dx(
i)*log(
c)*pow(
c,expr2.val()));
1233 using std::pow;
using std::log;
1234 return c == scalar_type(0.0) ? value_type(0.0) : value_type(expr2.fastAccessDx(
i)*log(
c)*pow(
c,expr2.val()));
1248 template <
typename T1,
typename T2>
1250 PowerImpl::Nested > :
1251 public Expr< PowerOp< T1, T2, false, false, ExprSpecDefault,
1252 PowerImpl::Nested > > {
1255 typedef typename std::remove_cv<T1>::type ExprT1;
1256 typedef typename std::remove_cv<T2>::type ExprT2;
1257 typedef typename ExprT1::value_type value_type_1;
1258 typedef typename ExprT2::value_type value_type_2;
1260 value_type_2>::type value_type;
1262 typedef typename ExprT1::scalar_type scalar_type_1;
1263 typedef typename ExprT2::scalar_type scalar_type_2;
1265 scalar_type_2>::type scalar_type;
1267 typedef ExprSpecDefault expr_spec_type;
1271 expr1(expr1_), expr2(expr2_) {}
1275 const int sz1 = expr1.size(), sz2 = expr2.size();
1276 return sz1 > sz2 ? sz1 : sz2;
1280 bool hasFastAccess()
const {
1281 return expr1.hasFastAccess() && expr2.hasFastAccess();
1285 value_type
val()
const {
1287 return pow(expr1.val(), expr2.val());
1291 value_type
dx(
int i)
const {
1292 using std::pow;
using std::log;
1293 const int sz1 = expr1.size(), sz2 = expr2.size();
1294 if (sz1 > 0 && sz2 > 0)
1295 return (expr2.dx(
i)*log(expr1.val())+expr2.val()*expr1.dx(
i)/expr1.val())*pow(expr1.val(),expr2.val());
1297 return expr2.val() == scalar_type(0.0) ? value_type(0.0) : value_type((expr2.val()*expr1.dx(
i))*pow(expr1.val(),expr2.val()-scalar_type(1.0)));
1299 return expr2.dx(
i)*
log(expr1.val())*pow(expr1.val(),expr2.val());
1304 using std::pow;
using std::log;
1305 return (expr2.fastAccessDx(
i)*log(expr1.val())+expr2.val()*expr1.fastAccessDx(
i)/expr1.val())*pow(expr1.val(),expr2.val());
1315 template <
typename T1,
typename T2>
1317 PowerImpl::Nested > :
1318 public Expr< PowerOp< T1, T2, false, true, ExprSpecDefault,
1319 PowerImpl::Nested > > {
1322 typedef typename std::remove_cv<T1>::type ExprT1;
1324 typedef typename ExprT1::value_type value_type;
1325 typedef typename ExprT1::scalar_type scalar_type;
1327 typedef ExprSpecDefault expr_spec_type;
1331 expr1(expr1_),
c(
c_) {}
1335 return expr1.size();
1339 bool hasFastAccess()
const {
1340 return expr1.hasFastAccess();
1344 value_type
val()
const {
1346 return pow(expr1.val(),
c);
1350 value_type
dx(
int i)
const {
1352 return c == scalar_type(0.0) ? value_type(0.0) : value_type(
c*expr1.dx(
i)*pow(expr1.val(),
c-scalar_type(1.0)));
1358 return c == scalar_type(0.0) ? value_type(0.0) : value_type(
c*expr1.fastAccessDx(
i)*pow(expr1.val(),
c-scalar_type(1.0)));
1367 template <
typename T1,
typename T2>
1369 PowerImpl::Nested > :
1370 public Expr< PowerOp< T1, T2, true, false, ExprSpecDefault,
1371 PowerImpl::Nested > > {
1374 typedef typename std::remove_cv<T2>::type ExprT2;
1376 typedef typename ExprT2::value_type value_type;
1377 typedef typename ExprT2::scalar_type scalar_type;
1379 typedef ExprSpecDefault expr_spec_type;
1383 c(
c_), expr2(expr2_) {}
1387 return expr2.size();
1391 bool hasFastAccess()
const {
1392 return expr2.hasFastAccess();
1396 value_type
val()
const {
1398 return pow(
c, expr2.val());
1402 value_type
dx(
int i)
const {
1403 using std::pow;
using std::log;
1404 return expr2.dx(
i)*
log(
c)*pow(
c,expr2.val());
1409 using std::pow;
using std::log;
1410 return expr2.fastAccessDx(
i)*
log(
c)*pow(
c,expr2.val());
1424 template <
typename T1,
typename T2>
1426 PowerImpl::NestedSimd > :
1427 public Expr< PowerOp< T1, T2, false, false, ExprSpecDefault,
1428 PowerImpl::NestedSimd > > {
1431 typedef typename std::remove_cv<T1>::type ExprT1;
1432 typedef typename std::remove_cv<T2>::type ExprT2;
1433 typedef typename ExprT1::value_type value_type_1;
1434 typedef typename ExprT2::value_type value_type_2;
1436 value_type_2>::type value_type;
1438 typedef typename ExprT1::scalar_type scalar_type_1;
1439 typedef typename ExprT2::scalar_type scalar_type_2;
1441 scalar_type_2>::type scalar_type;
1443 typedef ExprSpecDefault expr_spec_type;
1447 expr1(expr1_), expr2(expr2_) {}
1451 const int sz1 = expr1.size(), sz2 = expr2.size();
1452 return sz1 > sz2 ? sz1 : sz2;
1456 bool hasFastAccess()
const {
1457 return expr1.hasFastAccess() && expr2.hasFastAccess();
1461 value_type
val()
const {
1463 return pow(expr1.val(), expr2.val());
1467 value_type
dx(
int i)
const {
1469 const int sz1 = expr1.size(), sz2 = expr2.size();
1470 if (sz1 > 0 && sz2 > 0)
1471 return (expr2.dx(
i)*log(expr1.val())+expr2.val()*expr1.dx(
i)/expr1.val())*pow(expr1.val(),expr2.val());
1473 return if_then_else( expr2.val() == scalar_type(0.0), value_type(0.0), value_type((expr2.val()*expr1.dx(
i))*pow(expr1.val(),expr2.val()-scalar_type(1.0))));
1475 return expr2.dx(
i)*
log(expr1.val())*pow(expr1.val(),expr2.val());
1481 return (expr2.fastAccessDx(
i)*log(expr1.val())+expr2.val()*expr1.fastAccessDx(
i)/expr1.val())*pow(expr1.val(),expr2.val());
1491 template <
typename T1,
typename T2>
1493 PowerImpl::NestedSimd > :
1494 public Expr< PowerOp< T1, T2, false, true, ExprSpecDefault,
1495 PowerImpl::NestedSimd > > {
1498 typedef typename std::remove_cv<T1>::type ExprT1;
1500 typedef typename ExprT1::value_type value_type;
1501 typedef typename ExprT1::scalar_type scalar_type;
1503 typedef ExprSpecDefault expr_spec_type;
1507 expr1(expr1_),
c(
c_) {}
1511 return expr1.size();
1515 bool hasFastAccess()
const {
1516 return expr1.hasFastAccess();
1520 value_type
val()
const {
1522 return pow(expr1.val(),
c);
1526 value_type
dx(
int i)
const {
1528 return if_then_else(
c == scalar_type(0.0), value_type(0.0), value_type(
c*expr1.dx(
i)*pow(expr1.val(),
c-scalar_type(1.0))));
1534 return if_then_else(
c == scalar_type(0.0), value_type(0.0), value_type(
c*expr1.fastAccessDx(
i)*pow(expr1.val(),
c-scalar_type(1.0))));
1543 template <
typename T1,
typename T2>
1545 PowerImpl::NestedSimd > :
1546 public Expr< PowerOp< T1, T2, true, false, ExprSpecDefault,
1547 PowerImpl::NestedSimd > > {
1550 typedef typename std::remove_cv<T2>::type ExprT2;
1552 typedef typename ExprT2::value_type value_type;
1553 typedef typename ExprT2::scalar_type scalar_type;
1555 typedef ExprSpecDefault expr_spec_type;
1559 c(
c_), expr2(expr2_) {}
1563 return expr2.size();
1567 bool hasFastAccess()
const {
1568 return expr2.hasFastAccess();
1572 value_type
val()
const {
1574 return pow(
c, expr2.val());
1578 value_type
dx(
int i)
const {
1579 using std::pow;
using std::log;
1580 return expr2.dx(
i)*
log(
c)*pow(
c,expr2.val());
1585 using std::pow;
using std::log;
1586 return expr2.fastAccessDx(
i)*
log(
c)*pow(
c,expr2.val());
1595 template <
typename T1,
typename T2>
1598 pow (
const T1& expr1,
const T2& expr2)
1600 typedef PowerOp< typename Expr<T1>::derived_type,
1601 typename Expr<T2>::derived_type,
1602 false,
false,
typename T1::expr_spec_type > expr_t;
1604 return expr_t(expr1.derived(), expr2.derived());
1607 template <
typename T>
1609 PowerOp< typename T::value_type, typename Expr<T>::derived_type,
1610 true,
false,
typename T::expr_spec_type >
1611 pow (
const typename T::value_type&
c,
1612 const Expr<T>& expr)
1614 typedef typename T::value_type ConstT;
1615 typedef PowerOp< ConstT, typename Expr<T>::derived_type,
1616 true,
false,
typename T::expr_spec_type > expr_t;
1618 return expr_t(
c, expr.derived());
1621 template <
typename T>
1623 PowerOp< typename Expr<T>::derived_type,
typename T::value_type,
1624 false,
true,
typename T::expr_spec_type >
1625 pow (
const Expr<T>& expr,
1626 const typename T::value_type&
c)
1628 typedef typename T::value_type ConstT;
1629 typedef PowerOp< typename Expr<T>::derived_type, ConstT,
1630 false,
true,
typename T::expr_spec_type > expr_t;
1632 return expr_t(expr.derived(),
c);
1635 template <
typename T>
1638 pow (
const typename T::scalar_type&
c,
1639 const Expr<T>& expr)
1641 typedef typename T::scalar_type ConstT;
1642 typedef PowerOp< ConstT, typename Expr<T>::derived_type,
1643 true,
false,
typename T::expr_spec_type > expr_t;
1645 return expr_t(
c, expr.derived());
1648 template <
typename T>
1651 pow (
const Expr<T>& expr,
1652 const typename T::scalar_type&
c)
1654 typedef typename T::scalar_type ConstT;
1655 typedef PowerOp< typename Expr<T>::derived_type, ConstT,
1656 false,
true,
typename T::expr_spec_type > expr_t;
1658 return expr_t(expr.derived(),
c);
1661 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1662 struct ExprLevel<
PowerOp<
T1,
T2, c1, c2, E > > {
1663 static constexpr unsigned value_1 = ExprLevel<T1>::value;
1664 static constexpr unsigned value_2 = ExprLevel<T2>::value;
1665 static constexpr unsigned value =
1666 value_1 >= value_2 ? value_1 : value_2;
1669 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1670 struct IsFadExpr<
PowerOp<
T1,
T2, c1, c2, E > > {
1671 static constexpr unsigned value =
true;
1677 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1678 struct IsExpr< Fad::Exp::PowerOp< T1, T2, c1, c2, E > > {
1679 static constexpr bool value =
true;
1682 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1683 struct BaseExprType< Fad::Exp::PowerOp< T1, T2, c1, c2, E > > {
1684 typedef typename BaseExprType<T1>::type base_expr_1;
1685 typedef typename BaseExprType<T2>::type base_expr_2;
1687 base_expr_2>::type type;
1690 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1691 struct IsSimdType< Fad::Exp::PowerOp< T1, T2, c1, c2, E > > {
1692 static const bool value =
1693 IsSimdType< typename Fad::Exp::PowerOp< T1, T2, c1, c2, E >::value_type >
::value;
1696 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1697 struct ValueType< Fad::Exp::PowerOp< T1, T2, c1, c2, E > > {
1698 typedef typename Fad::Exp::PowerOp< T1, T2, c1, c2, E >::value_type type;
1701 template <
typename T1,
typename T2,
bool c1,
bool c2,
typename E>
1702 struct ScalarType< Fad::Exp::PowerOp< T1, T2, c1, c2, E > > {
1703 typedef typename Fad::Exp::PowerOp< T1, T2, c1, c2, E >::scalar_type type;