29 #ifndef PIRANHA_MATH_HPP 30 #define PIRANHA_MATH_HPP 33 #include <boost/numeric/conversion/cast.hpp> 37 #include <initializer_list> 41 #include <type_traits> 42 #include <unordered_set> 46 #include <piranha/detail/sfinae_types.hpp> 48 #include <piranha/is_key.hpp> 49 #include <piranha/symbol_utils.hpp> 68 template <
typename T,
typename =
void>
93 template <
typename U, enabler<U> = 0>
105 template <
typename T>
106 using math_is_zero_enabler =
typename std::enable_if<
107 std::is_convertible<decltype(math::is_zero_impl<T>{}(std::declval<const T &>())),
bool>::value,
int>::type;
132 template <
typename T, detail::math_is_zero_enabler<T> = 0>
143 template <
typename T>
144 using math_is_zero_std_complex_enabler =
145 typename std::enable_if<std::is_same<T, std::complex<float>>::value || std::is_same<T, std::complex<double>>::value
146 || std::is_same<T, std::complex<long double>>::value>::type;
156 template <
typename T>
178 template <
typename T,
typename =
void>
181 template <
typename U>
201 template <
typename U, enabler<U> = 0>
213 template <
typename T>
214 using math_is_unitary_enabler =
typename std::enable_if<
215 std::is_convertible<decltype(math::is_unitary_impl<T>{}(std::declval<const T &>())),
bool>::value,
int>::type;
241 template <
typename T, detail::math_is_unitary_enabler<T> = 0>
252 template <
typename T,
typename =
void>
256 template <
typename U>
257 using generic_enabler =
258 typename std::enable_if<!std::is_integral<U>::value
259 && detail::true_tt<decltype(std::declval<U &>() = -std::declval<U &>())>::value,
261 template <
typename U>
262 using integral_enabler =
typename std::enable_if<std::is_integral<U>::value,
int>::type;
281 template <
typename U,
generic_enabler<U> = 0>
290 template <
typename U,
integral_enabler<U> = 0>
295 x =
static_cast<U
>(-x);
304 template <
typename T>
305 using math_negate_enabler =
typename std::enable_if<
306 !std::is_const<T>::value && true_tt<decltype(math::negate_impl<T>{}(std::declval<T &>()))>::value,
int>::type;
328 template <
typename T, detail::math_negate_enabler<T> = 0>
338 template <
typename T,
typename =
void>
342 template <
typename U>
343 using addmul_t = decltype(std::declval<U &>() += std::declval<const U &>() * std::declval<const U &>());
344 template <
typename U>
345 using enabler = enable_if_t<is_detected<addmul_t, U>::value,
int>;
365 template <
typename U, enabler<U> = 0>
372 #if defined(FP_FAST_FMA) && defined(FP_FAST_FMAF) && defined(FP_FAST_FMAL) 374 inline namespace impl
378 template <
typename T>
379 using math_multiply_accumulate_float_enabler = enable_if_t<std::is_floating_point<T>::value>;
386 template <
typename T>
387 struct multiply_accumulate_impl<T, math_multiply_accumulate_float_enabler<T>> {
396 void operator()(T &x,
const T &y,
const T &z)
const 398 x = std::fma(y, z, x);
405 inline namespace impl
409 template <
typename T>
410 using math_multiply_accumulate_t = decltype(
411 math::multiply_accumulate_impl<T>{}(std::declval<T &>(), std::declval<const T &>(), std::declval<const T &>()));
413 template <
typename T>
414 using math_multiply_accumulate_enabler = enable_if_t<is_detected<math_multiply_accumulate_t, T>::value,
int>;
437 template <
typename T, math_multiply_accumulate_enabler<T> = 0>
448 template <
typename T,
typename Enable =
void>
457 template <
typename T>
458 struct cos_impl<T, typename
std::enable_if<std::is_floating_point<T>::value>::type> {
477 template <
typename T>
478 struct cos_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
492 piranha_throw(std::invalid_argument,
"cannot compute the cosine of a non-zero integral");
501 template <
typename T>
502 using math_cos_type_ = decltype(math::cos_impl<T>{}(std::declval<const T &>()));
504 template <
typename T>
505 using math_cos_type =
typename std::enable_if<is_returnable<math_cos_type_<T>>::value, math_cos_type_<T>>::type;
529 template <
typename T>
530 inline detail::math_cos_type<T>
cos(
const T &x)
540 template <
typename T,
typename Enable =
void>
549 template <
typename T>
550 struct sin_impl<T, typename
std::enable_if<std::is_floating_point<T>::value>::type> {
569 template <
typename T>
570 struct sin_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
584 piranha_throw(std::invalid_argument,
"cannot compute the sine of a non-zero integral");
593 template <
typename T>
594 using math_sin_type_ = decltype(math::sin_impl<T>{}(std::declval<const T &>()));
596 template <
typename T>
597 using math_sin_type =
typename std::enable_if<is_returnable<math_sin_type_<T>>::value, math_sin_type_<T>>::type;
621 template <
typename T>
622 inline detail::math_sin_type<T>
sin(
const T &x)
632 template <
typename T,
typename Enable =
void>
641 template <
typename T>
658 template <
typename T>
659 using math_partial_type_
660 = decltype(math::partial_impl<T>{}(std::declval<const T &>(), std::declval<const std::string &>()));
662 template <
typename T>
663 using math_partial_type =
664 typename std::enable_if<is_returnable<math_partial_type_<T>>::value, math_partial_type_<T>>::type;
690 template <
typename T>
691 inline detail::math_partial_type<T>
partial(
const T &x,
const std::string &str)
701 template <
typename T,
typename Enable =
void>
710 template <
typename T>
711 using math_integrate_type_
714 template <
typename T>
715 using math_integrate_type =
716 typename std::enable_if<is_returnable<math_integrate_type_<T>>::value, math_integrate_type_<T>>::type;
742 template <
typename T>
743 inline detail::math_integrate_type<T>
integrate(
const T &x,
const std::string &str)
752 template <
typename T,
typename U,
typename =
void>
755 template <
typename T1,
typename U1>
756 using ret_t =
typename std::conditional<is_detected<add_t, T1, U1>::value, detected_t<add_t, T1, U1>, T1>::type;
757 template <
typename T1,
typename U1>
758 using ret_type = enable_if_t<
759 conjunction<is_returnable<ret_t<T1, U1>>, std::is_constructible<ret_t<T1, U1>,
const T1 &>>::value,
786 template <
typename T1,
typename U1>
789 return ret_type<T1, U1>(x);
794 inline namespace impl
798 template <
typename T,
typename U>
799 using math_evaluate_t_
800 = decltype(math::evaluate_impl<T, U>{}(std::declval<const T &>(), std::declval<
const symbol_fmap<U> &>()));
802 template <
typename T,
typename U>
803 using math_evaluate_t = enable_if_t<is_returnable<math_evaluate_t_<T, U>>::value, math_evaluate_t_<T, U>>;
830 template <
typename U,
typename T>
841 template <
typename T,
typename U,
typename Enable =
void>
850 template <
typename T,
typename U>
851 using math_subs_type_
852 = decltype(
math::subs_impl<T, U>{}(std::declval<const T &>(), std::declval<
const symbol_fmap<U> &>()));
854 template <
typename T,
typename U>
855 using math_subs_type = enable_if_t<is_returnable<math_subs_type_<T, U>>::value, math_subs_type_<T, U>>;
880 template <
typename U,
typename T>
891 template <
typename T,
typename U,
typename V,
typename =
void>
900 template <
typename T,
typename U,
typename V>
901 using math_t_subs_type_
903 std::declval<const U &>(), std::declval<const V &>()));
905 template <
typename T,
typename U,
typename V>
906 using math_t_subs_type =
907 typename std::enable_if<is_returnable<math_t_subs_type_<T, U, V>>::value, math_t_subs_type_<T, U, V>>::type;
935 template <
typename T,
typename U,
typename V>
936 inline detail::math_t_subs_type<T, U, V>
t_subs(
const T &x,
const std::string &name,
const U &c,
const V &s)
946 template <
typename T,
typename Enable =
void>
954 template <
typename T>
955 using abs_arith_enabler =
typename std::enable_if<(std::is_signed<T>::value && std::is_integral<T>::value)
956 || (std::is_unsigned<T>::value && std::is_integral<T>::value)
957 || std::is_floating_point<T>::value>::type;
969 template <
typename T>
972 template <
typename U>
973 static U impl(
const U &x,
typename std::enable_if<std::is_floating_point<U>::value>::type * =
nullptr)
979 template <
typename U>
980 static auto impl(
const U &x,
981 typename std::enable_if<std::is_integral<U>::value && std::is_signed<U>::value>::type * =
nullptr)
982 -> decltype(static_cast<U>(std::abs(static_cast<long long>(x))))
985 return static_cast<U
>(std::abs(static_cast<long long>(x)));
987 template <
typename U>
988 static U impl(
const U &x,
989 typename std::enable_if<std::is_integral<U>::value && std::is_unsigned<U>::value>::type * =
nullptr)
1017 template <
typename T>
1028 template <
typename T>
1031 template <
typename U>
1032 using abs_t = decltype(
math::abs(std::declval<const U &>()));
1033 static const bool implementation_defined = is_detected<abs_t, T>::value;
1037 static const bool value = implementation_defined;
1041 template <
typename T>
1048 template <
typename T>
1051 template <
typename U>
1052 using is_zero_t = decltype(
math::is_zero(std::declval<const U &>()));
1053 static const bool implementation_defined = is_detected<is_zero_t, T>::value;
1057 static const bool value = implementation_defined;
1061 template <
typename T>
1069 template <
typename T>
1072 template <
typename U>
1073 using negate_t = decltype(
math::negate(std::declval<U &>()));
1074 static const bool implementation_defined = is_detected<negate_t, T>::value;
1078 static const bool value = implementation_defined;
1081 template <
typename T>
1087 #if !defined(PIRANHA_DOXYGEN_INVOKED) 1090 template <
typename T>
1091 using pbracket_type_tmp = decltype(
math::partial(std::declval<const T &>(), std::string())
1094 template <
typename T,
typename =
void>
1095 struct pbracket_type_ {
1098 template <
typename T>
1099 struct pbracket_type_<
1100 T, typename
std::enable_if<std::is_same<decltype(std::declval<const pbracket_type_tmp<T> &>()
1101 + std::declval<const pbracket_type_tmp<T> &>()),
1102 pbracket_type_tmp<T>>::value
1103 && std::is_same<decltype(std::declval<const pbracket_type_tmp<T> &>()
1104 - std::declval<const pbracket_type_tmp<T> &>()),
1105 pbracket_type_tmp<T>>::value
1106 && std::is_constructible<pbracket_type_tmp<T>, int>::value
1107 && std::is_assignable<pbracket_type_tmp<T> &, pbracket_type_tmp<T>>::value>::type> {
1108 using type = pbracket_type_tmp<T>;
1112 template <
typename T>
1113 using pbracket_type =
typename pbracket_type_<T>::type;
1151 template <
typename T>
1152 inline detail::pbracket_type<T>
pbracket(
const T &f,
const T &g,
const std::vector<std::string> &p_list,
1153 const std::vector<std::string> &q_list)
1155 using return_type = detail::pbracket_type<T>;
1156 if (p_list.size() != q_list.size()) {
1157 piranha_throw(std::invalid_argument,
"the number of coordinates is different from the number of momenta");
1159 if (std::unordered_set<std::string>(p_list.begin(), p_list.end()).size() != p_list.size()) {
1160 piranha_throw(std::invalid_argument,
"the list of momenta contains duplicate entries");
1162 if (std::unordered_set<std::string>(q_list.begin(), q_list.end()).size() != q_list.size()) {
1163 piranha_throw(std::invalid_argument,
"the list of coordinates contains duplicate entries");
1165 return_type retval = return_type(0);
1166 for (decltype(p_list.size()) i = 0u; i < p_list.size(); ++i) {
1180 template <
typename T>
1183 using v_string = std::vector<std::string>;
1184 template <
typename T1>
1185 static auto test(
const T1 &x)
1186 -> decltype(
math::pbracket(x, x, std::declval<v_string const &>(), std::declval<v_string const &>()),
void(),
1188 static no test(...);
1192 static const bool value = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
1195 template <
typename T>
1201 template <
typename T>
1203 && std::is_constructible<pbracket_type<T>,
int>::value
1207 template <
typename T>
1208 inline bool is_canonical_impl(
const std::vector<T const *> &new_p,
const std::vector<T const *> &new_q,
1209 const std::vector<std::string> &p_list,
const std::vector<std::string> &q_list)
1211 using p_type = decltype(
math::pbracket(*new_q[0], *new_p[0], p_list, q_list));
1212 if (p_list.size() != q_list.size()) {
1213 piranha_throw(std::invalid_argument,
"the number of coordinates is different from the number of momenta");
1215 if (new_p.size() != new_q.size()) {
1217 "the number of new coordinates is different from the number of new momenta");
1219 if (p_list.size() != new_p.size()) {
1220 piranha_throw(std::invalid_argument,
"the number of new momenta is different from the number of momenta");
1222 if (std::unordered_set<std::string>(p_list.begin(), p_list.end()).size() != p_list.size()) {
1223 piranha_throw(std::invalid_argument,
"the list of momenta contains duplicate entries");
1225 if (std::unordered_set<std::string>(q_list.begin(), q_list.end()).size() != q_list.size()) {
1226 piranha_throw(std::invalid_argument,
"the list of coordinates contains duplicate entries");
1228 const auto size = new_p.size();
1229 for (decltype(new_p.size()) i = 0u; i < size; ++i) {
1230 for (decltype(new_p.size()) j = 0u; j < size; ++j) {
1240 if (
math::pbracket(*new_q[i], *new_p[j], p_list, q_list) != p_type(static_cast<int>(i == j))) {
1282 template <
typename T, detail::is_canonical_enabler<T> = 0>
1284 const std::vector<std::string> &p_list,
const std::vector<std::string> &q_list)
1286 std::vector<T const *> pv, qv;
1287 std::transform(new_p.begin(), new_p.end(), std::back_inserter(pv), [](
const T &p) {
return &p; });
1288 std::transform(new_q.begin(), new_q.end(), std::back_inserter(qv), [](
const T &q) {
return &q; });
1289 return detail::is_canonical_impl(pv, qv, p_list, q_list);
1305 template <
typename T, detail::is_canonical_enabler<T> = 0>
1307 const std::vector<std::string> &p_list,
const std::vector<std::string> &q_list)
1309 std::vector<T const *> pv, qv;
1310 std::transform(new_p.begin(), new_p.end(), std::back_inserter(pv), [](
const T &p) {
return &p; });
1311 std::transform(new_q.begin(), new_q.end(), std::back_inserter(qv), [](
const T &q) {
return &q; });
1312 return detail::is_canonical_impl(pv, qv, p_list, q_list);
1324 template <
typename T,
typename Enable =
void>
1340 template <
typename T>
1361 template <
typename T>
1376 template <
typename T,
typename Enable =
void>
1392 template <
typename T>
1413 template <
typename T>
1428 template <
typename T,
typename Enable =
void>
1449 template <
typename T>
1452 return t_degree_impl<T>{}(x);
1469 template <
typename T>
1472 return t_degree_impl<T>{}(x, names);
1484 template <
typename T,
typename Enable =
void>
1505 template <
typename T>
1508 return t_ldegree_impl<T>{}(x);
1525 template <
typename T>
1528 return t_ldegree_impl<T>{}(x, names);
1540 template <
typename T,
typename Enable =
void>
1563 template <
typename T>
1566 return t_order_impl<T>{}(x);
1583 template <
typename T>
1586 return t_order_impl<T>{}(x, names);
1598 template <
typename T,
typename Enable =
void>
1621 template <
typename T>
1624 return t_lorder_impl<T>{}(x);
1641 template <
typename T>
1644 return t_lorder_impl<T>{}(x, names);
1651 template <
typename T,
typename U,
typename =
void>
1660 template <
typename T,
typename U>
1661 using truncate_degree_enabler =
typename std::enable_if<
1662 std::is_same<decltype(math::truncate_degree_impl<T, U>()(std::declval<const T &>(), std::declval<const U &>())),
1666 template <
typename T,
typename U>
1667 using truncate_pdegree_enabler =
typename std::enable_if<
1668 std::is_same<decltype(math::truncate_degree_impl<T, U>()(std::declval<const T &>(), std::declval<const U &>(),
1669 std::declval<const symbol_fset &>())),
1698 template <
typename T,
typename U, detail::truncate_degree_enabler<T, U> = 0>
1726 template <
typename T,
typename U, detail::truncate_pdegree_enabler<T, U> = 0>
1738 template <
typename T,
typename U>
1741 template <
typename T1,
typename U1>
1742 static auto test1(
const T1 &t,
const U1 &u) -> decltype(
math::truncate_degree(t, u),
void(), yes());
1743 static no test1(...);
1744 template <
typename T1,
typename U1>
1745 static auto test2(
const T1 &t,
const U1 &u)
1747 static no test2(...);
1751 static const bool value = std::is_same<decltype(test1(std::declval<T>(), std::declval<U>())), yes>
::value 1752 && std::is_same<decltype(test2(std::declval<T>(), std::declval<U>())), yes>
::value;
1755 template <
typename T,
typename U>
1763 template <
typename T>
1766 template <
typename U>
1767 static auto test(
const U &u) -> decltype(
math::partial(u,
""),
void(), yes());
1768 static no test(...);
1769 static const bool implementation_defined = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
1773 static const bool value = implementation_defined;
1777 template <
typename T>
1780 inline namespace impl
1785 template <
typename,
typename>
1786 struct is_differential_key_pair : std::false_type {
1789 template <
typename Key,
typename T>
1790 struct is_differential_key_pair<Key,
std::pair<T, Key>> : std::true_type {
1806 template <
typename Key>
1809 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
1810 template <
typename U>
1811 using key_partial_t = decltype(
1812 std::declval<const U &>().partial(std::declval<const symbol_idx &>(), std::declval<const symbol_fset &>()));
1813 static const bool implementation_defined
1814 = is_differential_key_pair<uncvref_t<Key>, detected_t<key_partial_t, Key>>
::value;
1818 static const bool value = implementation_defined;
1821 template <
typename Key>
1829 template <
typename T>
1832 template <
typename U>
1833 static auto test(
const U &u) -> decltype(
math::integrate(u,
""),
void(), yes());
1834 static no test(...);
1835 static const bool implementation_defined = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
1839 static const bool value = implementation_defined;
1842 template <
typename T>
1857 template <
typename Key>
1860 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
1861 template <
typename U>
1862 using key_integrate_t = decltype(
1863 std::declval<const U &>().integrate(std::declval<const std::string &>(), std::declval<const symbol_fset &>()));
1864 static const bool implementation_defined
1865 = is_differential_key_pair<uncvref_t<Key>, detected_t<key_integrate_t, Key>>
::value;
1869 static const bool value = implementation_defined;
1872 template <
typename T>
1880 template <
typename T>
1883 template <
typename U>
1884 static auto test1(
const U &u) -> decltype(
math::degree(u),
void(), yes());
1885 static no test1(...);
1886 template <
typename U>
1887 static auto test2(
const U &u) -> decltype(
math::degree(u, std::declval<const symbol_fset &>()),
void(), yes());
1888 static no test2(...);
1892 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 1893 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
1897 template <
typename T>
1905 template <
typename T>
1908 template <
typename U>
1909 static auto test1(
const U &u) -> decltype(
math::ldegree(u),
void(), yes());
1910 static no test1(...);
1911 template <
typename U>
1912 static auto test2(
const U &u) -> decltype(
math::ldegree(u, std::declval<const symbol_fset &>()),
void(), yes());
1913 static no test2(...);
1917 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 1918 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
1922 template <
typename T>
1930 template <
typename T>
1933 template <
typename U>
1934 static auto test1(
const U &u) -> decltype(
math::t_degree(u),
void(), yes());
1935 static no test1(...);
1936 template <
typename U>
1937 static auto test2(
const U &u) -> decltype(
math::t_degree(u, std::declval<const symbol_fset &>()),
void(), yes());
1938 static no test2(...);
1942 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 1943 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
1947 template <
typename T>
1955 template <
typename T>
1958 template <
typename U>
1959 static auto test1(
const U &u) -> decltype(
math::t_ldegree(u),
void(), yes());
1960 static no test1(...);
1961 template <
typename U>
1962 static auto test2(
const U &u) -> decltype(
math::t_ldegree(u, std::declval<const symbol_fset &>()),
void(), yes());
1963 static no test2(...);
1967 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 1968 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
1972 template <
typename T>
1980 template <
typename T>
1983 template <
typename U>
1984 static auto test1(
const U &u) -> decltype(
math::t_order(u),
void(), yes());
1985 static no test1(...);
1986 template <
typename U>
1987 static auto test2(
const U &u) -> decltype(
math::t_order(u, std::declval<const symbol_fset &>()),
void(), yes());
1988 static no test2(...);
1992 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 1993 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
1997 template <
typename T>
2005 template <
typename T>
2008 template <
typename U>
2009 static auto test1(
const U &u) -> decltype(
math::t_lorder(u),
void(), yes());
2010 static no test1(...);
2011 template <
typename U>
2012 static auto test2(
const U &u) -> decltype(
math::t_lorder(u, std::declval<const symbol_fset &>()),
void(), yes());
2013 static no test2(...);
2017 static const bool value = std::is_same<decltype(test1(std::declval<T>())), yes>::
value 2018 && std::is_same<decltype(test2(std::declval<T>())), yes>
::value;
2022 template <
typename T>
2038 template <
typename Key>
2041 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2042 template <
typename U>
2043 using total_degree_t = decltype(std::declval<const U &>().degree(std::declval<const symbol_fset &>()));
2044 template <
typename U>
2045 using partial_degree_t = decltype(
2046 std::declval<const U &>().degree(std::declval<const symbol_idx_fset &>(), std::declval<const symbol_fset &>()));
2047 static const bool implementation_defined
2048 = conjunction<is_detected<total_degree_t, Key>, is_detected<partial_degree_t, Key>>
::value;
2052 static const bool value = implementation_defined;
2055 template <
typename Key>
2071 template <
typename Key>
2074 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2075 template <
typename U>
2076 using total_ldegree_t = decltype(std::declval<const U &>().ldegree(std::declval<const symbol_fset &>()));
2077 template <
typename U>
2078 using partial_ldegree_t = decltype(std::declval<const U &>().ldegree(std::declval<const symbol_idx_fset &>(),
2079 std::declval<const symbol_fset &>()));
2080 static const bool implementation_defined
2081 = conjunction<is_detected<total_ldegree_t, Key>, is_detected<partial_ldegree_t, Key>>
::value;
2085 static const bool value = implementation_defined;
2088 template <
typename Key>
2104 template <
typename Key>
2107 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2108 template <
typename U>
2109 using total_t_degree_t = decltype(std::declval<const U &>().t_degree(std::declval<const symbol_fset &>()));
2110 template <
typename U>
2111 using partial_t_degree_t = decltype(std::declval<const U &>().t_degree(std::declval<const symbol_idx_fset &>(),
2112 std::declval<const symbol_fset &>()));
2113 static const bool implementation_defined
2114 = conjunction<is_detected<total_t_degree_t, Key>, is_detected<partial_t_degree_t, Key>>
::value;
2118 static const bool value = implementation_defined;
2122 template <
typename T>
2138 template <
typename Key>
2141 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2142 template <
typename U>
2143 using total_t_ldegree_t = decltype(std::declval<const U &>().t_ldegree(std::declval<const symbol_fset &>()));
2144 template <
typename U>
2145 using partial_t_ldegree_t = decltype(std::declval<const U &>().t_ldegree(std::declval<const symbol_idx_fset &>(),
2146 std::declval<const symbol_fset &>()));
2147 static const bool implementation_defined
2148 = conjunction<is_detected<total_t_ldegree_t, Key>, is_detected<partial_t_ldegree_t, Key>>
::value;
2152 static const bool value = implementation_defined;
2156 template <
typename T>
2172 template <
typename Key>
2175 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2176 template <
typename U>
2177 using total_t_order_t = decltype(std::declval<const U &>().t_order(std::declval<const symbol_fset &>()));
2178 template <
typename U>
2179 using partial_t_order_t = decltype(std::declval<const U &>().t_order(std::declval<const symbol_idx_fset &>(),
2180 std::declval<const symbol_fset &>()));
2181 static const bool implementation_defined
2182 = conjunction<is_detected<total_t_order_t, Key>, is_detected<partial_t_order_t, Key>>
::value;
2186 static const bool value = implementation_defined;
2190 template <
typename T>
2206 template <
typename Key>
2209 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2210 template <
typename U>
2211 using total_t_lorder_t = decltype(std::declval<const U &>().t_lorder(std::declval<const symbol_fset &>()));
2212 template <
typename U>
2213 using partial_t_lorder_t = decltype(std::declval<const U &>().t_lorder(std::declval<const symbol_idx_fset &>(),
2214 std::declval<const symbol_fset &>()));
2215 static const bool implementation_defined
2216 = conjunction<is_detected<total_t_lorder_t, Key>, is_detected<partial_t_lorder_t, Key>>
::value;
2220 static const bool value = implementation_defined;
2224 template <
typename T>
2231 template <
typename T>
2234 typedef typename std::decay<T>::type Td;
2235 template <
typename T1>
2236 static auto test(
const T1 &t) -> decltype(
math::is_unitary(t),
void(), yes());
2237 static no test(...);
2238 static const bool implementation_defined = std::is_same<decltype(test(std::declval<Td>())), yes>::
value;
2242 static const bool value = implementation_defined;
2245 template <
typename T>
2253 template <
typename T,
typename U>
2256 typedef typename std::decay<T>::type Td;
2257 typedef typename std::decay<U>::type Ud;
2258 template <
typename T1,
typename U1>
2259 static auto test(
const T1 &t,
const U1 &u)
2261 static no test(...);
2262 static const bool implementation_defined
2263 = std::is_same<decltype(test(std::declval<Td>(), std::declval<Ud>())), yes>
::value;
2267 static const bool value = implementation_defined;
2271 template <
typename T,
typename U>
2279 template <
typename T,
typename U,
typename V>
2282 typedef typename std::decay<T>::type Td;
2283 typedef typename std::decay<U>::type Ud;
2284 typedef typename std::decay<V>::type Vd;
2285 template <
typename T1,
typename U1,
typename V1>
2286 static auto test(
const T1 &t,
const U1 &u,
const V1 &v)
2287 -> decltype(
math::t_subs(t, std::declval<std::string const &>(), u, v),
void(), yes());
2288 static no test(...);
2289 static const bool implementation_defined
2290 = std::is_same<decltype(test(std::declval<Td>(), std::declval<Ud>(), std::declval<Vd>())), yes>::
value;
2294 static const bool value = implementation_defined;
2298 template <
typename T,
typename U,
typename V>
2301 inline namespace impl
2305 template <
typename,
typename>
2306 struct key_subs_check_type : std::false_type {
2309 template <
typename Key,
typename T>
2310 struct key_subs_check_type<Key,
std::vector<std::pair<T, Key>>> : std::true_type {
2327 template <
typename Key,
typename T,
typename U>
2330 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2331 template <
typename Key1,
typename T1,
typename U1>
2332 using t_subs_t = decltype(
2333 std::declval<const Key1 &>().t_subs(std::declval<const symbol_idx &>(), std::declval<const T1 &>(),
2334 std::declval<const U1 &>(), std::declval<const symbol_fset &>()));
2335 static const bool implementation_defined
2336 = key_subs_check_type<uncvref_t<Key>, detected_t<t_subs_t, Key, T, U>>
::value;
2340 static const bool value = implementation_defined;
2344 template <
typename Key,
typename T,
typename U>
2359 template <
typename Key,
typename T>
2362 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2363 template <
typename Key1,
typename T1>
2364 using subs_t = decltype(std::declval<const Key1 &>().subs(std::declval<
const symbol_idx_fmap<T1> &>(),
2365 std::declval<const symbol_fset &>()));
2366 static const bool implementation_defined = key_subs_check_type<uncvref_t<Key>, detected_t<subs_t, Key, T>>
::value;
2370 static const bool value = implementation_defined;
2374 template <
typename Key,
typename T>
2382 template <
typename T>
2385 template <
typename U>
2386 using multiply_accumulate_t = decltype(
2388 static const bool implementation_defined = is_detected<multiply_accumulate_t, T>::value;
2392 static const bool value = implementation_defined;
2396 template <
typename T>
2404 template <
typename T,
typename U>
2407 template <
typename T1,
typename U1>
2409 static const bool implementation_defined = is_detected<eval_t, T, U>::value;
2413 static const bool value = implementation_defined;
2416 template <
typename T,
typename U>
2430 template <
typename Key,
typename T>
2433 PIRANHA_TT_CHECK(
is_key, uncvref_t<Key>);
2434 template <
typename Key1,
typename T1>
2435 using evaluate_t = decltype(std::declval<const Key1 &>().evaluate(std::declval<
const std::vector<T1> &>(),
2436 std::declval<const symbol_fset &>()));
2437 static const bool implementation_defined = is_detected<evaluate_t, Key, T>::value;
2441 static const bool value = implementation_defined;
2444 template <
typename Key,
typename T>
2452 template <
typename T>
2455 template <
typename T1>
2456 static auto test(
const T1 &x) -> decltype(
math::sin(x),
void(), yes());
2457 static no test(...);
2461 static const bool value = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
2464 template <
typename T>
2472 template <
typename T>
2475 template <
typename T1>
2476 static auto test(
const T1 &x) -> decltype(
math::cos(x),
void(), yes());
2477 static no test(...);
2481 static const bool value = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
2484 template <
typename T>
2492 template <
typename T>
2495 using v_string = std::vector<std::string>;
2496 template <
typename T1>
2498 std::declval<std::vector<T1>
const &>(),
2499 std::declval<v_string const &>(),
2500 std::declval<v_string const &>()),
2502 static no test(...);
2506 static const bool value = std::is_same<decltype(test(std::declval<T>())), yes>::
value;
2509 template <
typename T>
2519 template <
typename T,
typename Enable =
void>
2537 template <
typename U>
2538 auto operator()(U &a,
const U &b,
const U &c)
const -> decltype(a = b + c)
2548 template <
typename T>
2549 struct add3_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
2563 return a =
static_cast<T
>(b + c);
2581 template <
typename T>
2591 template <
typename T,
typename Enable =
void>
2609 template <
typename U>
2610 auto operator()(U &a,
const U &b,
const U &c)
const -> decltype(a = b - c)
2620 template <
typename T>
2621 struct sub3_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
2635 return a =
static_cast<T
>(b - c);
2653 template <
typename T>
2663 template <
typename T,
typename Enable =
void>
2681 template <
typename U>
2682 auto operator()(U &a,
const U &b,
const U &c)
const -> decltype(a = b * c)
2692 template <
typename T>
2693 struct mul3_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
2707 return a =
static_cast<T
>(b * c);
2725 template <
typename T>
2735 template <
typename T,
typename Enable =
void>
2753 template <
typename U>
2754 auto operator()(U &a,
const U &b,
const U &c)
const -> decltype(a = b / c)
2764 template <
typename T>
2765 struct div3_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
2779 return a =
static_cast<T
>(b / c);
2797 template <
typename T>
2812 template <
typename T>
2813 inline T gcd_euclidean(T a, T b)
2836 template <
typename T,
typename U,
typename =
void>
2844 template <
typename T,
typename U>
2845 struct gcd_impl<T, U, typename
std::enable_if<std::is_integral<T>::value && std::is_integral<U>::value>::type> {
2847 using p_type = decltype(std::declval<const T &>() + std::declval<const U &>());
2860 return detail::gcd_euclidean(static_cast<p_type>(a), static_cast<p_type>(b));
2877 template <
typename T,
typename U>
2887 template <
typename T,
typename =
void>
2903 template <
typename T1>
2914 template <
typename T>
2915 struct gcd3_impl<T, typename
std::enable_if<std::is_integral<T>::value>::type> {
2928 return out =
static_cast<T
>(
math::gcd(a, b));
2946 template <
typename T>
2958 template <
typename T>
2961 template <
typename U>
2962 using add3_t = decltype(
math::add3(std::declval<U &>(), std::declval<const U &>(), std::declval<const U &>()));
2963 static const bool implementation_defined = is_detected<add3_t, T>::value;
2967 static const bool value = implementation_defined;
2970 template <
typename T>
2978 template <
typename T>
2981 template <
typename U>
2982 using sub3_t = decltype(
math::sub3(std::declval<U &>(), std::declval<const U &>(), std::declval<const U &>()));
2983 static const bool implementation_defined = is_detected<sub3_t, T>::value;
2987 static const bool value = implementation_defined;
2990 template <
typename T>
2998 template <
typename T>
3001 template <
typename U>
3002 using mul3_t = decltype(
math::mul3(std::declval<U &>(), std::declval<const U &>(), std::declval<const U &>()));
3003 static const bool implementation_defined = is_detected<mul3_t, T>::value;
3007 static const bool value = implementation_defined;
3010 template <
typename T>
3018 template <
typename T>
3021 template <
typename U>
3022 using div3_t = decltype(
math::div3(std::declval<U &>(), std::declval<const U &>(), std::declval<const U &>()));
3023 static const bool implementation_defined = is_detected<div3_t, T>::value;
3027 static const bool value = implementation_defined;
3030 template <
typename T>
3038 template <
typename T,
typename U = T>
3041 template <
typename T1,
typename U1>
3042 using gcd_t = decltype(
math::gcd(std::declval<const T1 &>(), std::declval<const U1 &>()));
3043 static const bool implementation_defined = is_detected<gcd_t, T, U>::value;
3047 static const bool value = implementation_defined;
3050 template <
typename T,
typename U>
3058 template <
typename T>
3061 template <
typename U>
3062 using gcd3_t = decltype(
math::gcd3(std::declval<U &>(), std::declval<const U &>(), std::declval<const U &>()));
3063 static const bool implementation_defined = is_detected<gcd3_t, T>::value;
3067 static const bool value = implementation_defined;
3070 template <
typename T>
Default functor for the implementation of piranha::math::mul3().
static const bool value
Value of the type trait.
auto gcd(const T &a, const U &b) -> decltype(gcd_impl< T, U >()(a, b))
GCD.
Detect piranha::math::gcd3().
Detect piranha::math::sub3().
detail::math_integrate_type< T > integrate(const T &x, const std::string &str)
Integration.
Default functor for the implementation of piranha::math::negate().
auto operator()(U &a, const U &b, const U &c) const -> decltype(a=b *c)
Call operator.
static const bool value
Value of the type trait.
Default functor for the implementation of piranha::math::div3().
Default functor for the implementation of piranha::math::t_degree().
Default functor for the implementation of piranha::math::multiply_accumulate().
Equality-comparable type trait.
detail::math_partial_type< T > partial(const T &x, const std::string &str)
Partial derivative.
Type trait to detect piranha::math::sin().
T & operator()(T &out, const T &a, const T &b) const
Call operator.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
Default functor for the implementation of piranha::math::integrate().
auto add3(T &a, const T &b, const T &c) -> decltype(add3_impl< T >()(a, b, c))
Ternary addition.
Detect piranha::math::div3().
auto t_lorder(const T &x) -> decltype(t_lorder_impl< T >
Total trigonometric low order.
Type trait to detect if type has a degree property.
auto operator()(U &a, const U &b, const U &c) const -> decltype(a=b - c)
Call operator.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
auto operator()(const T &x) const -> decltype(impl(x))
Call operator.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
Default functor for the implementation of piranha::math::is_zero().
Default functor for the implementation of piranha::math::ldegree().
boost::container::flat_map< std::string, T > symbol_fmap
Flat map of symbols.
Type trait to detect the presence of the piranha::math::is_unitary() function.
Type trait to detect if a key type has a trigonometric degree property.
ret_type< T1, U1 > operator()(const T1 &x, const symbol_fmap< U1 > &) const
Call operator.
Type trait to detect the presence of the piranha::math::t_subs function.
detail::math_cos_type< T > cos(const T &x)
Cosine.
Default functor for the implementation of piranha::math::sin().
Type trait to detect the presence of the piranha::math::subs function.
void negate(T &x)
In-place negation.
Type trait to detect the presence of the piranha::math::negate function.
p_type operator()(const T &a, const U &b) const
Call operator.
Default functor for the implementation of piranha::math::cos().
T operator()(const T &x) const
Call operator.
Default functor for the implementation of piranha::math::evaluate().
auto degree(const T &x) -> decltype(degree_impl< T >()(x))
Total degree.
static const bool value
Value of the type trait.
auto operator()(T1 &out, const T1 &a, const T1 &b) const -> decltype(out=math::gcd(a, b))
Call operator.
Type trait to detect the presence of the piranha::math::is_zero() function.
bool transformation_is_canonical(const std::vector< T > &new_p, const std::vector< T > &new_q, const std::vector< std::string > &p_list, const std::vector< std::string > &q_list)
Check if a transformation is canonical.
static const bool value
Value of the type trait.
Type trait to detect if type has a trigonometric low degree property.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
detail::math_t_subs_type< T, U, V > t_subs(const T &x, const std::string &name, const U &c, const V &s)
Trigonometric substitution.
Default functor for the implementation of piranha::math::t_lorder().
Detect piranha::math::pbracket().
bool operator()(const U &x) const
Call operator.
static const bool value
Value of the type trait.
Type trait to detect if type has a trigonometric order property.
bool operator()(const T &c) const
Call operator.
void operator()(U &x) const
Generic call operator.
math_evaluate_t< T, U > evaluate(const T &x, const symbol_fmap< U > &dict)
Evaluation.
Implementation of the piranha::math::truncate_degree() functor.
Default functor for the implementation of piranha::math::add3().
static const bool value
Value of the type trait.
Type trait to detect integrable keys.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
Type trait for differentiable types.
boost::container::flat_set< std::string > symbol_fset
Flat set of symbols.
Default functor for the implementation of piranha::math::t_ldegree().
bool operator()(const U &x) const
Call operator.
T operator()(const T &x) const
Call operator.
Default functor for the implementation of piranha::math::sub3().
Default functor for the implementation of piranha::math::gcd3().
Type trait to detect if types can be used in piranha::math::truncate_degree().
T & operator()(T &a, const T &b, const T &c) const
Call operator.
Default functor for the implementation of piranha::math::partial().
Type trait to detect the presence of the substitution method in keys.
auto operator()(U &a, const U &b, const U &c) const -> decltype(a=b+c)
Call operator.
auto div3(T &a, const T &b, const T &c) -> decltype(div3_impl< T >()(a, b, c))
Ternary division.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
auto t_degree(const T &x) -> decltype(t_degree_impl< T >
Total trigonometric degree.
auto abs(const T &x) -> decltype(abs_impl< T >()(x))
Absolute value.
Default functor for the implementation of piranha::math::gcd().
T operator()(const T &, const std::string &) const
Call operator.
Type trait to detect if a key type has a trigonometric order property.
T & operator()(T &a, const T &b, const T &c) const
Call operator.
bool is_zero(const T &x)
Zero test.
Default functor for the implementation of piranha::math::t_subs().
Type trait to detect if a key type has a trigonometric low order property.
boost::container::flat_map< symbol_idx, T > symbol_idx_fmap
Flat map of symbol indices.
T & operator()(T &a, const T &b, const T &c) const
Call operator.
Type trait to detect if type has a trigonometric degree property.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
T truncate_degree(const T &x, const U &max_degree)
Truncation based on the total degree.
T & operator()(T &a, const T &b, const T &c) const
Call operator.
Type trait to detect the availability of piranha::math::multiply_accumulate().
static const bool value
Value of the type trait.
Type trait to detect the availability of piranha::math::evaluate().
auto t_ldegree(const T &x) -> decltype(t_ldegree_impl< T >
Total trigonometric low degree.
Type trait to detect the presence of the trigonometric substitution method in keys.
static const bool value
Value of the type trait.
Type trait for integrable types.
void multiply_accumulate(T &x, const T &y, const T &z)
Multiply-accumulate.
Detect piranha::math::gcd().
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
auto ldegree(const T &x) -> decltype(ldegree_impl< T >()(x))
Total low degree.
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
Type trait to detect if a key type has a low degree property.
Default functor for the implementation of piranha::math::degree().
Type trait to detect piranha::math::cos().
auto mul3(T &a, const T &b, const T &c) -> decltype(mul3_impl< T >()(a, b, c))
Ternary multiplication.
Type trait to detect if type has a low degree property.
static const bool value
Value of the type trait.
Detect piranha::math::add3().
Type trait to detect if type has a trigonometric low order property.
Type trait to detect differentiable keys.
auto t_order(const T &x) -> decltype(t_order_impl< T >
Total trigonometric order.
auto operator()(U &a, const U &b, const U &c) const -> decltype(a=b/c)
Call operator.
Type trait to detect if a key type has a degree property.
void operator()(U &x, const U &y, const U &z) const
Call operator.
static const bool value
Value of the type trait.
auto sub3(T &a, const T &b, const T &c) -> decltype(sub3_impl< T >()(a, b, c))
Ternary subtraction.
Detect piranha::math::mul3().
static const bool value
Value of the type trait.
static const bool value
Value of the type trait.
Type trait to detect if a key type has a trigonometric low degree property.
Default functor for the implementation of piranha::math::t_order().
Default functor for the implementation of piranha::math::abs().
static const bool value
Value of the type trait.
Default functor for the implementation of piranha::math::subs().
static const bool value
Value of the type trait.
Type trait to detect the presence of the piranha::math::abs() function.
T operator()(const T &x) const
Call operator.
detail::math_subs_type< T, U > subs(const T &x, const symbol_fmap< U > &dict)
Substitution.
auto gcd3(T &out, const T &a, const T &b) -> decltype(gcd3_impl< T >()(out, a, b))
Ternary GCD.
static const bool value
Value of the type trait.
decltype(std::declval< const T & >()+std::declval< const U & >()) p_type
The promoted type of T and U.
static const bool value
Value of the type trait.
T operator()(const T &x) const
Call operator.
detail::pbracket_type< T > pbracket(const T &f, const T &g, const std::vector< std::string > &p_list, const std::vector< std::string > &q_list)
Poisson bracket.
detail::math_sin_type< T > sin(const T &x)
Sine.
static const bool value
Value of the type trait.
Default functor for the implementation of piranha::math::is_unitary().
Type trait to detect evaluable keys.
bool is_unitary(const T &x)
Unitary test.