tuple-list.H 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. // (c) Daniel Llorens - 2005-2013, 2016
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file tuple-list.H
  7. /// @brief Using tuples as compile time lists.
  8. #pragma once
  9. #include "ra/int_t.H"
  10. #include <tuple>
  11. #include <limits>
  12. namespace mp {
  13. using std::tuple;
  14. using nil = tuple<>;
  15. template <class T> constexpr bool nilp = std::is_same<nil, T>::value;
  16. template <class A> constexpr int len = std::tuple_size<A>::value;
  17. template <class A, class B> struct Cons;
  18. template <class A0, class ... A>
  19. struct Cons<A0, tuple<A ...>>
  20. {
  21. using type = tuple<A0, A ...>;
  22. };
  23. template <class A, class B>
  24. using Cons_ = typename Cons<A, B>::type;
  25. template <class A, class B> struct Append;
  26. template <class ... A, class ... B>
  27. struct Append<tuple<A ...>, tuple<B ...>>
  28. {
  29. using type = tuple<A ..., B ...>;
  30. };
  31. template <class A, class B>
  32. using Append_ = typename Append<A, B>::type;
  33. template <class A, class B> struct Zip;
  34. template <class ... A, class ... B>
  35. struct Zip<tuple<A ...>, tuple<B ...>>
  36. {
  37. using type = tuple<tuple<A, B> ...>;
  38. };
  39. template <class A, class B> using Zip_ = typename Zip<A, B>::type;
  40. // The list is [a .. a+n).
  41. template <int n, int a=0, int step=1>
  42. struct Iota
  43. {
  44. static_assert(n>=0, "bad size for Iota");
  45. using type = typename Cons<int_t<a>, typename Iota<n-1, a+step, step>::type>::type;
  46. };
  47. template <int a, int step>
  48. struct Iota<0, a, step>
  49. {
  50. using type = nil;
  51. };
  52. template <int n, int a=0, int step=1>
  53. using Iota_ = typename Iota<n, a, step>::type;
  54. template <int n, class T>
  55. struct MakeList
  56. {
  57. static_assert(n>=0, "bad size for MakeList");
  58. using type = typename Cons<T, typename MakeList<n-1, T>::type>::type;
  59. };
  60. template <class T>
  61. struct MakeList<0, T>
  62. {
  63. using type = nil;
  64. };
  65. template <int n, class T>
  66. using MakeList_ = typename MakeList<n, T>::type;
  67. // Subscript a list (of lists (of lists ...)).
  68. // @param A a list (of lists (of lists ...)).
  69. // @param I... the indices.
  70. template <class A, int ... I>
  71. struct Ref
  72. {
  73. using type = A;
  74. };
  75. template <class A, int I0, int ... I>
  76. struct Ref<A, I0, I ...>
  77. {
  78. static_assert(I0>=0, "bad index for Ref");
  79. using type = typename Ref<typename std::tuple_element<I0, A>::type, I ...>::type;
  80. };
  81. template <class A, int ... I> using Ref_ = typename Ref<A, I ...>::type;
  82. template <class A> struct First { using type = Ref_<A, 0>; };
  83. template <class A> using First_ = typename First<A>::type;
  84. template <class A> struct Last { using type = Ref_<A, len<A>-1>; };
  85. template <class A> using Last_ = typename Last<A>::type;
  86. template <bool c, class A, class B> using If = std::conditional<c, A, B>;
  87. template <bool c, class A, class B> using If_ = typename If<c, A, B>::type;
  88. template <bool a>
  89. struct When
  90. {
  91. constexpr static bool value = a;
  92. using type = int_t<value>;
  93. };
  94. template <bool a>
  95. struct Unless
  96. {
  97. constexpr static bool value = !a;
  98. using type = int_t<value>;
  99. };
  100. // Return the index of a type in a type list, or -1 if not found.
  101. template <class A, class Val, int i=0>
  102. struct Index
  103. {
  104. constexpr static int value = -1;
  105. };
  106. template <class ... A, class Val, int i>
  107. struct Index<tuple<Val, A ...>, Val, i>
  108. {
  109. constexpr static int value = i;
  110. };
  111. template <class A0, class ... A, class Val, int i>
  112. struct Index<tuple<A0, A ...>, Val, i>
  113. {
  114. constexpr static int value = Index<tuple<A ...>, Val, i+1>::value;
  115. };
  116. // Index (& type) of the 1st item for which Pred<> is true, or -1 (& nil).
  117. template <class A, template <class> class Pred, int i=0, class Enable=void>
  118. struct IndexIf
  119. {
  120. constexpr static int value = -1;
  121. using type = nil;
  122. };
  123. template <class A0, class ... A, template <class> class Pred, int i>
  124. struct IndexIf<tuple<A0, A ...>, Pred, i, std::enable_if_t<Pred<A0>::value>>
  125. {
  126. using type = A0;
  127. constexpr static int value = i;
  128. };
  129. template <class A0, class ... A, template <class> class Pred, int i>
  130. struct IndexIf<tuple<A0, A ...>, Pred, i, std::enable_if_t<!(Pred<A0>::value)>>
  131. {
  132. using next = IndexIf<tuple<A ...>, Pred, i+1>;
  133. using type = typename next::type;
  134. constexpr static int value = next::value;
  135. };
  136. // Index (& type) of pairwise winner. A variant of Fold.
  137. template <template <class A, class B> class pick_i, class T, int k=1, int sel=0>
  138. struct IndexOf;
  139. template <template <class A, class B> class pick_i, class T0, int k, int sel>
  140. struct IndexOf<pick_i, tuple<T0>, k, sel>
  141. {
  142. constexpr static int value = sel;
  143. using type = T0;
  144. };
  145. template <template <class A, class B> class pick_i, class T0, class T1, class ... Ti, int k, int sel>
  146. struct IndexOf<pick_i, tuple<T0, T1, Ti ...>, k, sel>
  147. {
  148. constexpr static int i = pick_i<std::decay_t<T0>, std::decay_t<T1>>::value;
  149. using next = IndexOf<pick_i, tuple<mp::If_<i==0, T0, T1>, Ti ...>, k+1, i==0 ? sel : k>;
  150. using type = typename next::type;
  151. constexpr static int value = next::value;
  152. };
  153. // Return the first tail of A headed by Val, like find-tail.
  154. template <class A, class Val> struct FindTail;
  155. template <class Val>
  156. struct FindTail<nil, Val>
  157. {
  158. using type = nil;
  159. };
  160. template <class ... A, class Val>
  161. struct FindTail<tuple<Val, A ...>, Val>
  162. {
  163. using type = tuple<Val, A ...>;
  164. };
  165. template <class A0, class ... A, class Val>
  166. struct FindTail<tuple<A0, A ...>, Val>
  167. {
  168. using type = typename FindTail<tuple<A ...>, Val>::type;
  169. };
  170. // Reverse list. See TSPL^3, p. 137.
  171. template <class A, class New=nil>
  172. struct Reverse
  173. {
  174. using type = New;
  175. };
  176. template <class A0, class ... A, class New>
  177. struct Reverse<tuple<A0, A ...>, New>
  178. {
  179. using type = typename Reverse<tuple<A ...>, typename Cons<A0, New>::type>::type;
  180. };
  181. template <class A, class New=nil>
  182. using Reverse_ = typename Reverse<A, New>::type;
  183. // Drop1 is needed to avoid ambiguity in the declarations of Drop, Take.
  184. template <class A> struct Drop1;
  185. template <class A0, class ... A>
  186. struct Drop1<tuple<A0, A ...>>
  187. {
  188. using type = tuple<A ...>;
  189. };
  190. template <class A>
  191. using Drop1_ = typename Drop1<A>::type;
  192. template <class A, int n>
  193. struct Drop
  194. {
  195. static_assert(n>=0, "bad drop size");
  196. using type = typename Drop<typename Drop1<A>::type, n-1>::type;
  197. };
  198. template <class A>
  199. struct Drop<A, 0>
  200. {
  201. using type = A;
  202. };
  203. template <class A, int n>
  204. using Drop_ = typename Drop<A, n>::type;
  205. template <class A, int n>
  206. struct Take
  207. {
  208. static_assert(n>=0, "bad take size");
  209. using type = typename Cons<First_<A>,
  210. typename Take<typename Drop1<A>::type, n-1>::type>::type;
  211. };
  212. template <class A>
  213. struct Take<A, 0>
  214. {
  215. using type = nil;
  216. };
  217. template <class A, int n>
  218. using Take_ = typename Take<A, n>::type;
  219. // As apply, or as ApplyV<Valuer<>>
  220. template <template <class ... A> class F, class L>
  221. struct Apply
  222. {
  223. static_assert(len<L> >= 0, "arg must be a tuple");
  224. };
  225. template <template <class ... A> class F, class ... L>
  226. struct Apply<F, tuple<L ...>>
  227. {
  228. using type = typename F<L ...>::type;
  229. };
  230. template <template <class ... A> class F, class L>
  231. using Apply_ = typename Apply<F, L>::type;
  232. // As apply, or as Apply<Typer<>>
  233. template <template <class ... A> class F, class L>
  234. struct ApplyV
  235. {
  236. static_assert(len<L> >= 0, "arg must be a tuple"); // ??
  237. };
  238. template <template <class ... A> class F, class ... L>
  239. struct ApplyV<F, tuple<L ...>>
  240. {
  241. static int const value = F<L ...>::value;
  242. };
  243. // As map.
  244. template <template <class ... A> class F, class ... L>
  245. struct Map
  246. {
  247. using type = typename Cons<typename F<First_<L> ...>::type,
  248. typename Map<F, typename Drop1<L>::type ...>::type>::type;
  249. };
  250. template <template <class ... A> class F, class ... L>
  251. struct Map<F, nil, L ...>
  252. {
  253. using type = nil;
  254. };
  255. template <template <class ... A> class F>
  256. struct Map<F>
  257. {
  258. using type = nil;
  259. };
  260. template <template <class ... A> class F, class ... L>
  261. using Map_ = typename Map<F, L ...>::type;
  262. template <class A, class B> struct Filter
  263. {
  264. using type = mp::Append_<mp::If_<mp::First_<A>::value, mp::Take_<B, 1>, mp::nil>,
  265. typename Filter<mp::Drop1_<A>, mp::Drop1_<B>>::type>;
  266. };
  267. template <class B> struct Filter<mp::nil, B>
  268. {
  269. using type = B;
  270. };
  271. template <class A, class B>
  272. using Filter_ = typename Filter<A, B>::type;
  273. // As SRFI-1 fold (= fold-left).
  274. template <template <class ... A> class F, class Def, class ... L>
  275. struct Fold
  276. {
  277. using def = If_<std::is_same<void, Def>::value, F<>, Def>;
  278. using type = typename Fold<F,
  279. typename F<def, First_<L> ...>::type,
  280. typename Drop1<L>::type ...>::type;
  281. };
  282. template <template <class ... A> class F, class Def, class ... L>
  283. struct Fold<F, Def, nil, L ...>
  284. {
  285. using type = If_<std::is_same<void, Def>::value, F<>, Def>;
  286. };
  287. template <template <class ... A> class F, class Def>
  288. struct Fold<F, Def>
  289. {
  290. using type = If_<std::is_same<void, Def>::value, F<>, Def>;
  291. };
  292. template <template <class ... A> class F, class Def, class ... L>
  293. using Fold_ = typename Fold<F, Def, L ...>::type;
  294. // Pass F(A) to templates expecting F(A ...). todo Wait for C++ to be fixed.
  295. template <template <class A> class F>
  296. struct Coerce1
  297. {
  298. template <class ... B> struct type_; // bug ---breaks composability
  299. template <class B0, class ... B>
  300. struct type_<B0, B ...>
  301. {
  302. using type = typename F<B0>::type;
  303. };
  304. };
  305. // Pass F(A, B) to templates expecting F(A ...). todo Wait for C++ to be fixed.
  306. template <template <class A, class B> class F>
  307. struct Coerce2
  308. {
  309. template <class ... B> struct type_; // bug ---breaks composability
  310. template <class B0, class B1, class ... B>
  311. struct type_<B0, B1, B ...>
  312. {
  313. using type = typename F<B0, B1>::type;
  314. };
  315. };
  316. // Pass F(A ...) -> type to/from templates expecting F(A ...) -> value.
  317. template <template <class ... A> class F>
  318. struct Valuer
  319. {
  320. template <class ... B>
  321. struct type
  322. {
  323. constexpr static int value = F<B ...>::type::value;
  324. };
  325. };
  326. template <template <class ... A> class F>
  327. struct Typer
  328. {
  329. template <class ... B>
  330. struct type_ // bug ---breaks composability
  331. {
  332. using type = int_t<F<B ...>::value>;
  333. };
  334. };
  335. // Operations on int_t arguments.
  336. template <class ... A> struct Sum
  337. {
  338. constexpr static int value = (A::value + ... + 0);
  339. using type = int_t<value>;
  340. };
  341. template <class ... A> struct Max
  342. {
  343. constexpr static int value = std::numeric_limits<int>::min();
  344. using type = int_t<value>;
  345. };
  346. template <class A0, class ... A>
  347. struct Max<A0, A ...>
  348. {
  349. constexpr static int value = std::max(A0::value, Max<A ...>::type::value);
  350. using type = int_t<value>;
  351. };
  352. template <class ... A> struct Min
  353. {
  354. constexpr static int value = std::numeric_limits<int>::max();
  355. using type = int_t<value>;
  356. };
  357. template <class A0, class ... A>
  358. struct Min<A0, A ...>
  359. {
  360. constexpr static int value = std::min(A0::value, Min<A ...>::type::value);
  361. using type = int_t<value>;
  362. };
  363. template <class ... A> struct Prod
  364. {
  365. constexpr static int value = (A::value * ... * 1);
  366. using type = int_t<value>;
  367. };
  368. template <class ... A> struct And
  369. {
  370. constexpr static bool value = (A::value && ...);
  371. using type = bool_t<value>;
  372. };
  373. template <class ... A> struct Or
  374. {
  375. constexpr static bool value = (A::value || ...);
  376. using type = bool_t<value>;
  377. };
  378. // Remove from the second list the elements of the first list. None may have repeated elements, but they may be unsorted.
  379. template <class S, class T, class SS=S>
  380. struct ComplementList;
  381. // end of T.
  382. template <class S, class SS>
  383. struct ComplementList<S, nil, SS>
  384. {
  385. using type = nil;
  386. };
  387. // end search on S, did not find.
  388. template <class T0, class ... T, class SS>
  389. struct ComplementList<nil, tuple<T0, T ...>, SS>
  390. {
  391. using type = typename Cons<T0, typename ComplementList<SS, tuple<T ...>>::type>::type;
  392. };
  393. // end search on S, found.
  394. template <class F, class ... S, class ... T, class SS>
  395. struct ComplementList<tuple<F, S ...>, tuple<F, T ...>, SS>
  396. {
  397. using type = typename ComplementList<SS, tuple<T ...>>::type;
  398. };
  399. // keep searching on S.
  400. template <class S0, class ... S, class T0, class ... T, class SS>
  401. struct ComplementList<tuple<S0, S ...>, tuple<T0, T ...>, SS>
  402. {
  403. using type = typename ComplementList<tuple<S ...>, tuple<T0, T ...>, SS>::type;
  404. };
  405. template <class S, class T, class SS=S>
  406. using ComplementList_ = typename ComplementList<S, T, SS>::type;
  407. // Like ComplementList, but assume that both lists are sorted.
  408. template <class S, class T>
  409. struct ComplementSList
  410. {
  411. using type = nil;
  412. };
  413. template <class T>
  414. struct ComplementSList<nil, T>
  415. {
  416. using type = T;
  417. };
  418. template <class F, class ... S, class ... T>
  419. struct ComplementSList<tuple<F, S ...>, tuple<F, T ...>>
  420. {
  421. using type = typename ComplementSList<tuple<S ...>, tuple<T ...>>::type;
  422. };
  423. template <class S0, class ... S, class T0, class ... T>
  424. struct ComplementSList<tuple<S0, S ...>, tuple<T0, T ...>>
  425. {
  426. static_assert(T0::value<=S0::value, "bad lists for ComplementSList<>");
  427. using type = typename Cons<T0, typename ComplementSList<tuple<S0, S ...>, tuple<T ...>>::type>::type;
  428. };
  429. // Variant of ComplementList where the second argument is [0 .. end-1].
  430. template <class S, int end>
  431. struct Complement
  432. {
  433. using type = typename ComplementSList<S, typename Iota<end>::type>::type;
  434. };
  435. template <class S, int end>
  436. using Complement_ = typename Complement<S, end>::type;
  437. // Prepend an element to each of a list of lists.
  438. template <class c, class A> struct MapCons;
  439. template <class c, class ... A>
  440. struct MapCons<c, tuple<A ...>>
  441. {
  442. using type = tuple<typename Cons<c, A>::type ...>;
  443. };
  444. // Prepend a list to each list in a list of lists.
  445. template <class c, class A> struct MapPrepend;
  446. template <class c, class ... A>
  447. struct MapPrepend<c, tuple<A ...>>
  448. {
  449. using type = tuple<typename Append<c, A>::type ...>;
  450. };
  451. // Form all possible lists by prepending an element of A to an element of B.
  452. template <class A, class B> struct ProductAppend
  453. {
  454. using type = nil;
  455. };
  456. template <class A0, class ... A, class B>
  457. struct ProductAppend<tuple<A0, A ...>, B>
  458. {
  459. using type = typename Append<typename MapPrepend<A0, B>::type,
  460. typename ProductAppend<tuple<A ...>, B>::type
  461. >::type;
  462. };
  463. // Compute the K-combinations of the N elements of A.
  464. //
  465. // @param A type list.
  466. // @param K take combinations of length K.
  467. template <class A, int K, int N=len<A>>
  468. struct Combinations
  469. {
  470. static_assert(N>=0 && K>=0, "N and K must be positive in Combinations");
  471. static_assert(K<=N, "K cannot be > N in Combinations of N elements by K");
  472. using Rest = typename Drop1<A>::type;
  473. using type = typename Append
  474. // with the first element and the (N-1 K-1) combinations on the rest.
  475. <typename MapCons<First_<A>,
  476. typename Combinations<Rest, K-1, N-1>::type>::type,
  477. // combinations on the rest, which are another (N-1 K).
  478. typename Combinations<Rest, K, N-1>::type
  479. >::type;
  480. };
  481. // In this case, return a list with one element: the null list.
  482. template <class A, int N>
  483. struct Combinations<A, 0, N>
  484. {
  485. using type = tuple<nil>;
  486. };
  487. // In this case, return a list with one element: the whole list.
  488. template <class A, int N>
  489. struct Combinations<A, N, N>
  490. {
  491. using type = tuple<A>;
  492. };
  493. // Special case for 0 over 0, to resolve ambiguity of 0/N and N/N when N=0.
  494. template <>
  495. struct Combinations<nil, 0>
  496. {
  497. using type = tuple<nil>;
  498. };
  499. template <class A, int k, int N=len<A>>
  500. using Combinations_ = typename Combinations<A, k, N>::type;
  501. // Sign of permutations.
  502. template <class C, class R> struct PermutationSign;
  503. template <int w, class C, class R>
  504. struct PermutationSignIfFound
  505. {
  506. constexpr static int value
  507. = ((w & 1) ? -1 : +1)
  508. * PermutationSign<typename Append<typename Take<C, w>::type,
  509. typename Drop<C, w+1>::type>::type,
  510. typename Drop1<R>::type>::value;
  511. };
  512. template <class C, class R>
  513. struct PermutationSignIfFound<-1, C, R>
  514. {
  515. constexpr static int value = 0;
  516. };
  517. template <>
  518. struct PermutationSign<nil, nil>
  519. {
  520. constexpr static int value = 1;
  521. };
  522. template <class C>
  523. struct PermutationSign<C, nil>
  524. {
  525. constexpr static int value = 0;
  526. };
  527. template <class R>
  528. struct PermutationSign<nil, R>
  529. {
  530. constexpr static int value = 0;
  531. };
  532. template <class C, class Org>
  533. struct PermutationSign
  534. {
  535. constexpr static int value
  536. = PermutationSignIfFound<Index<C, First_<Org>>::value,
  537. C, Org>::value;
  538. };
  539. template <int ... I> using int_list = tuple<int_t<I> ...>;
  540. // increment the w-th element of an int_t<> list.
  541. template <class L, int w>
  542. struct Inc
  543. {
  544. using type = typename
  545. Append<typename Take<L, w>::type,
  546. typename Cons<int_t<Ref_<L, w>::value+1>,
  547. typename Drop<L, w+1>::type>::type>::type;
  548. };
  549. template <class A> struct InvertIndex;
  550. template <class ... A> struct InvertIndex<std::tuple<A ...>>
  551. {
  552. using AT = std::tuple<A ...>;
  553. template <class T> struct IndexA
  554. {
  555. using type = int_t<Index<AT, T>::value>;
  556. };
  557. constexpr static int N = Apply_<Max, AT>::value;
  558. using type = Map_<IndexA, Iota_<(N>=0 ? N+1 : 0)>>;
  559. };
  560. template <class A> using InvertIndex_ = typename InvertIndex<A>::type;
  561. // Used in tests.
  562. template <class A, int ... I>
  563. struct check_idx
  564. {
  565. constexpr static bool value = false;
  566. };
  567. template <>
  568. struct check_idx<nil>
  569. {
  570. constexpr static bool value = true;
  571. };
  572. template <class A0, int I0, class ... A, int ... I>
  573. struct check_idx<std::tuple<A0, A ...>, I0, I ...>
  574. {
  575. constexpr static bool value = (A0::value==I0)
  576. && check_idx<std::tuple<A ...>, I ...>::value;
  577. };
  578. } // namespace mp