mp.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. // Copyright Peter Dimov 2015-2021.
  2. // Copyright Matt Borland 2021.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Template metaprogramming classes and functions to replace MPL
  8. // Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html
  9. // Source: https://github.com/boostorg/mp11/
  10. #ifndef BOOST_MATH_TOOLS_MP
  11. #define BOOST_MATH_TOOLS_MP
  12. #include <type_traits>
  13. #include <cstddef>
  14. #include <utility>
  15. namespace boost { namespace math { namespace tools { namespace meta_programming {
  16. // Types:
  17. // Typelist
  18. template<typename... T>
  19. struct mp_list {};
  20. // Size_t
  21. template<std::size_t N>
  22. using mp_size_t = std::integral_constant<std::size_t, N>;
  23. // Boolean
  24. template<bool B>
  25. using mp_bool = std::integral_constant<bool, B>;
  26. // Identity
  27. template<typename T>
  28. struct mp_identity
  29. {
  30. using type = T;
  31. };
  32. // Turns struct into quoted metafunction
  33. template<template<typename...> class F>
  34. struct mp_quote_trait
  35. {
  36. template<typename... T>
  37. using fn = typename F<T...>::type;
  38. };
  39. namespace detail {
  40. // Size
  41. template<typename L>
  42. struct mp_size_impl {};
  43. template<template<typename...> class L, typename... T> // Template template parameter must use class
  44. struct mp_size_impl<L<T...>>
  45. {
  46. using type = std::integral_constant<std::size_t, sizeof...(T)>;
  47. };
  48. }
  49. template<typename T>
  50. using mp_size = typename detail::mp_size_impl<T>::type;
  51. namespace detail {
  52. // Front
  53. template<typename L>
  54. struct mp_front_impl {};
  55. template<template<typename...> class L, typename T1, typename... T>
  56. struct mp_front_impl<L<T1, T...>>
  57. {
  58. using type = T1;
  59. };
  60. }
  61. template<typename T>
  62. using mp_front = typename detail::mp_front_impl<T>::type;
  63. namespace detail {
  64. // At
  65. // TODO - Use tree based lookup for larger typelists
  66. // http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html
  67. template<typename L, std::size_t>
  68. struct mp_at_c {};
  69. template<template<typename...> class L, typename T0, typename... T>
  70. struct mp_at_c<L<T0, T...>, 0>
  71. {
  72. using type = T0;
  73. };
  74. template<template<typename...> class L, typename T0, typename T1, typename... T>
  75. struct mp_at_c<L<T0, T1, T...>, 1>
  76. {
  77. using type = T1;
  78. };
  79. template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
  80. struct mp_at_c<L<T0, T1, T2, T...>, 2>
  81. {
  82. using type = T2;
  83. };
  84. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
  85. struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
  86. {
  87. using type = T3;
  88. };
  89. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
  90. struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
  91. {
  92. using type = T4;
  93. };
  94. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
  95. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
  96. {
  97. using type = T5;
  98. };
  99. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  100. typename... T>
  101. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
  102. {
  103. using type = T6;
  104. };
  105. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  106. typename T7, typename... T>
  107. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
  108. {
  109. using type = T7;
  110. };
  111. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  112. typename T7, typename T8, typename... T>
  113. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
  114. {
  115. using type = T8;
  116. };
  117. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  118. typename T7, typename T8, typename T9, typename... T>
  119. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
  120. {
  121. using type = T9;
  122. };
  123. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  124. typename T7, typename T8, typename T9, typename T10, typename... T>
  125. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
  126. {
  127. using type = T10;
  128. };
  129. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  130. typename T7, typename T8, typename T9, typename T10, typename T11, typename... T>
  131. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>
  132. {
  133. using type = T11;
  134. };
  135. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  136. typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T>
  137. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>
  138. {
  139. using type = T12;
  140. };
  141. }
  142. template<typename L, std::size_t Index>
  143. using mp_at_c = typename detail::mp_at_c<L, Index>::type;
  144. template<typename L, typename Index>
  145. using mp_at = typename detail::mp_at_c<L, Index::value>::type;
  146. // Back
  147. template<typename L>
  148. using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
  149. namespace detail {
  150. // Push back
  151. template<typename L, typename... T>
  152. struct mp_push_back_impl {};
  153. template<template<typename...> class L, typename... U, typename... T>
  154. struct mp_push_back_impl<L<U...>, T...>
  155. {
  156. using type = L<U..., T...>;
  157. };
  158. }
  159. template<typename L, typename... T>
  160. using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
  161. namespace detail {
  162. // Push front
  163. template<typename L, typename... T>
  164. struct mp_push_front_impl {};
  165. template<template<typename...> class L, typename... U, typename... T>
  166. struct mp_push_front_impl<L<U...>, T...>
  167. {
  168. using type = L<T..., U...>;
  169. };
  170. }
  171. template<typename L, typename... T>
  172. using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
  173. namespace detail{
  174. // If
  175. template<bool C, typename T, typename... E>
  176. struct mp_if_c_impl{};
  177. template<typename T, typename... E>
  178. struct mp_if_c_impl<true, T, E...>
  179. {
  180. using type = T;
  181. };
  182. template<typename T, typename E>
  183. struct mp_if_c_impl<false, T, E>
  184. {
  185. using type = E;
  186. };
  187. }
  188. template<bool C, typename T, typename... E>
  189. using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
  190. template<typename C, typename T, typename... E>
  191. using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
  192. namespace detail {
  193. // Find if
  194. template<typename L, template<typename...> class P>
  195. struct mp_find_if_impl {};
  196. template<template<typename...> class L, template<typename...> class P>
  197. struct mp_find_if_impl<L<>, P>
  198. {
  199. using type = mp_size_t<0>;
  200. };
  201. template<typename L, template<typename...> class P>
  202. struct mp_find_if_impl_2
  203. {
  204. using r = typename mp_find_if_impl<L, P>::type;
  205. using type = mp_size_t<1 + r::value>;
  206. };
  207. template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
  208. struct mp_find_if_impl<L<T1, T...>, P>
  209. {
  210. using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
  211. };
  212. }
  213. template<typename L, template<typename...> class P>
  214. using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
  215. template<typename L, typename Q>
  216. using mp_find_if_q = mp_find_if<L, Q::template fn>;
  217. namespace detail {
  218. // Append
  219. template<typename... L>
  220. struct mp_append_impl {};
  221. template<>
  222. struct mp_append_impl<>
  223. {
  224. using type = mp_list<>;
  225. };
  226. template<template<typename...> class L, typename... T>
  227. struct mp_append_impl<L<T...>>
  228. {
  229. using type = L<T...>;
  230. };
  231. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
  232. struct mp_append_impl<L1<T1...>, L2<T2...>>
  233. {
  234. using type = L1<T1..., T2...>;
  235. };
  236. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  237. template<typename...> class L3, typename... T3>
  238. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
  239. {
  240. using type = L1<T1..., T2..., T3...>;
  241. };
  242. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  243. template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>
  244. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
  245. {
  246. using type = L1<T1..., T2..., T3..., T4...>;
  247. };
  248. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  249. template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4,
  250. template<typename...> class L5, typename... T5, typename... Lr>
  251. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
  252. {
  253. using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
  254. };
  255. }
  256. template<typename... L>
  257. using mp_append = typename detail::mp_append_impl<L...>::type;
  258. namespace detail {
  259. // Remove if
  260. template<typename L, template<typename...> class P>
  261. struct mp_remove_if_impl{};
  262. template<template<typename...> class L, typename... T, template<typename...> class P>
  263. struct mp_remove_if_impl<L<T...>, P>
  264. {
  265. template<typename U>
  266. struct _f
  267. {
  268. using type = mp_if<P<U>, mp_list<>, mp_list<U>>;
  269. };
  270. using type = mp_append<L<>, typename _f<T>::type...>;
  271. };
  272. }
  273. template<typename L, template<class...> class P>
  274. using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
  275. template<typename L, typename Q>
  276. using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
  277. // Index sequence
  278. // Use C++14 index sequence if available
  279. #if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304)
  280. template<std::size_t... Index>
  281. using index_sequence = std::index_sequence<Index...>;
  282. template<std::size_t N>
  283. using make_index_sequence = std::make_index_sequence<N>;
  284. template<typename... T>
  285. using index_sequence_for = std::index_sequence_for<T...>;
  286. #else
  287. template<typename T, T... Index>
  288. struct integer_sequence {};
  289. template<std::size_t... Index>
  290. using index_sequence = integer_sequence<std::size_t, Index...>;
  291. namespace detail {
  292. template<bool C, typename T, typename E>
  293. struct iseq_if_c_impl {};
  294. template<typename T, typename F>
  295. struct iseq_if_c_impl<true, T, F>
  296. {
  297. using type = T;
  298. };
  299. template<typename T, typename F>
  300. struct iseq_if_c_impl<false, T, F>
  301. {
  302. using type = F;
  303. };
  304. template<bool C, typename T, typename F>
  305. using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
  306. template<typename T>
  307. struct iseq_identity
  308. {
  309. using type = T;
  310. };
  311. template<typename T1, typename T2>
  312. struct append_integer_sequence {};
  313. template<typename T, T... Index, T... J>
  314. struct append_integer_sequence<integer_sequence<T, Index...>, integer_sequence<T, J...>>
  315. {
  316. using type = integer_sequence<T, Index..., (J + sizeof...(Index))...>;
  317. };
  318. template<typename T, T N>
  319. struct make_integer_sequence_impl;
  320. template<typename T, T N>
  321. class make_integer_sequence_impl_
  322. {
  323. private:
  324. static_assert(N >= 0, "N must not be negative");
  325. static constexpr T M = N / 2;
  326. static constexpr T R = N % 2;
  327. using seq1 = typename make_integer_sequence_impl<T, M>::type;
  328. using seq2 = typename append_integer_sequence<seq1, seq1>::type;
  329. using seq3 = typename make_integer_sequence_impl<T, R>::type;
  330. using seq4 = typename append_integer_sequence<seq2, seq3>::type;
  331. public:
  332. using type = seq4;
  333. };
  334. template<typename T, T N>
  335. struct make_integer_sequence_impl
  336. {
  337. using type = typename iseq_if_c<N == 0,
  338. iseq_identity<integer_sequence<T>>,
  339. iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>,
  340. make_integer_sequence_impl_<T, N>>>::type;
  341. };
  342. } // namespace detail
  343. template<typename T, T N>
  344. using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
  345. template<std::size_t N>
  346. using make_index_sequence = make_integer_sequence<std::size_t, N>;
  347. template<typename... T>
  348. using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
  349. #endif
  350. }}}} // namespaces
  351. #endif // BOOST_MATH_TOOLS_MP