tuples.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - Test type list library based on tuples.
  3. // (c) Daniel Llorens - 2010
  4. // This library is free software; you can redistribute it and/or modify it under
  5. // the terms of the GNU Lesser General Public License as published by the Free
  6. // Software Foundation; either version 3 of the License, or (at your option) any
  7. // later version.
  8. #include <iostream>
  9. #include "ra/test.hh"
  10. #include "mpdebug.hh"
  11. using std::tuple, std::tuple_element, std::is_same_v;
  12. using std::cout, std::endl, ra::TestRecorder;
  13. using ra::int_c, ra::mp::ref, ra::mp::int_list;
  14. template <class A>
  15. struct Inc1
  16. {
  17. using type = int_c<A::value+1>;
  18. };
  19. template <class A, class B>
  20. struct Sum2
  21. {
  22. using type = int_c<A::value+B::value>;
  23. };
  24. template <class ... A> struct SumV;
  25. template <class A0, class ... A>
  26. struct SumV<A0, A ...>
  27. {
  28. constexpr static int value = A0::value + SumV<A ...>::value;
  29. };
  30. template <>
  31. struct SumV<>
  32. {
  33. constexpr static int value = 0;
  34. };
  35. template <class A>
  36. struct SamePP
  37. {
  38. template <class B>
  39. struct type
  40. {
  41. constexpr static bool value = is_same_v<A, B>;
  42. };
  43. };
  44. struct True
  45. {
  46. constexpr static bool value = true;
  47. };
  48. // These used to be in tuples.hh, but then I thought it wasn't worth having them there. Some are tested below.
  49. namespace ra::mp {
  50. template <class ... A> using sum = int_c<(A::value + ... + 0)>;
  51. template <class ... A> using prod = int_c<(A::value * ... * 1)>;
  52. template <class ... A> using andb = bool_c<(A::value && ...)>;
  53. template <class ... A> using orb = bool_c<(A::value || ...)>;
  54. // increment L[w]
  55. template <class L, int w> using inc = append<take<L, w>, cons<int_c<ref<L, w>::value+1>, drop<L, w+1>>>;
  56. template <bool a> using when = bool_c<a>;
  57. template <bool a> using unless = bool_c<(!a)>;
  58. // like fold-left
  59. template <template <class ... A> class F, class Def, class ... L>
  60. struct fold_
  61. {
  62. using def = std::conditional_t<std::is_same_v<void, Def>, F<>, Def>;
  63. using type = typename fold_<F, F<def, first<L> ...>, drop1<L> ...>::type;
  64. };
  65. template <template <class ... A> class F, class Def, class ... L>
  66. struct fold_<F, Def, nil, L ...>
  67. {
  68. using type = std::conditional_t<std::is_same_v<void, Def>, F<>, Def>;
  69. };
  70. template <template <class ... A> class F, class Def>
  71. struct fold_<F, Def>
  72. {
  73. using type = std::conditional_t<std::is_same_v<void, Def>, F<>, Def>;
  74. };
  75. template <template <class ... A> class F, class Def, class ... L>
  76. using fold = typename fold_<F, Def, L ...>::type;
  77. template <class ... A> using max = int_c<[]() { int r=std::numeric_limits<int>::min(); ((r=std::max(r, A::value)), ...); return r; }()>;
  78. template <class ... A> using min = int_c<[]() { int r=std::numeric_limits<int>::max(); ((r=std::min(r, A::value)), ...); return r; }()>;
  79. template <class A> struct InvertIndex_;
  80. template <class ... A> struct InvertIndex_<tuple<A ...>>
  81. {
  82. using AT = tuple<A ...>;
  83. template <class T> using IndexA = int_c<index<AT, T>::value>;
  84. constexpr static int N = apply<max, AT>::value;
  85. using type = map<IndexA, iota<(N>=0 ? N+1 : 0)>>;
  86. };
  87. template <class A> using InvertIndex = typename InvertIndex_<A>::type;
  88. } // namespace ra::mp
  89. int main()
  90. {
  91. TestRecorder tr(std::cout);
  92. // Booleans.
  93. {
  94. static_assert(True::value, "bad True");
  95. }
  96. // Map
  97. {
  98. using A = int_list<5, 6, 3>;
  99. using B = int_list<2, 3, -1>;
  100. static_assert(ra::mp::check_idx<ra::mp::map<ra::mp::sum, A>, 5, 6, 3>::value, "");
  101. static_assert(ra::mp::check_idx<ra::mp::map<ra::mp::sum, A, B>, 7, 9, 2>::value, "");
  102. }
  103. // fold.
  104. {
  105. using A = int_list<5, 6, 3>;
  106. using B = int_list<2, 3, -1>;
  107. static_assert(ra::mp::fold<ra::mp::sum, int_c<1>, A>::value==15, "");
  108. static_assert(ra::mp::fold<ra::mp::sum, int_c<3>, B>::value==7, "");
  109. static_assert(ra::mp::fold<ra::mp::max, int_c<4>, A>::value==6, "");
  110. static_assert(ra::mp::fold<ra::mp::max, void, A>::value==6, "");
  111. static_assert(ra::mp::fold<ra::mp::max, int_c<9>, A>::value==9, "");
  112. static_assert(ra::mp::fold<ra::mp::min, int_c<4>, A>::value==3, "");
  113. static_assert(ra::mp::fold<ra::mp::min, void, A>::value==3, "");
  114. static_assert(ra::mp::fold<ra::mp::min, int_c<1>, A>::value==1, "");
  115. }
  116. // Reductions.
  117. {
  118. using list_ = int_list<>;
  119. using list_1 = int_list<1>;
  120. using list_0 = int_list<0>;
  121. using list_10 = int_list<1, 0>;
  122. using list_01 = int_list<0, 1>;
  123. using list_11 = int_list<1, 1>;
  124. using list_00 = int_list<0, 0>;
  125. static_assert(ra::mp::apply<ra::mp::andb, list_>::value, "bad And");
  126. static_assert(ra::mp::apply<ra::mp::andb, list_1>::value, "bad And");
  127. static_assert(!ra::mp::apply<ra::mp::andb, list_0>::value, "bad And");
  128. static_assert(!ra::mp::apply<ra::mp::andb, list_10>::value, "bad And");
  129. static_assert(!ra::mp::apply<ra::mp::andb, list_01>::value, "bad And");
  130. static_assert(ra::mp::apply<ra::mp::andb, list_11>::value, "bad And");
  131. static_assert(!ra::mp::apply<ra::mp::andb, list_00>::value, "bad And");
  132. static_assert(!ra::mp::apply<ra::mp::orb, list_>::value, "bad Or");
  133. static_assert(ra::mp::apply<ra::mp::orb, list_1>::value, "bad Or");
  134. static_assert(!ra::mp::apply<ra::mp::orb, list_0>::value, "bad Or");
  135. static_assert(ra::mp::apply<ra::mp::orb, list_10>::value, "bad Or");
  136. static_assert(ra::mp::apply<ra::mp::orb, list_01>::value, "bad Or");
  137. static_assert(ra::mp::apply<ra::mp::orb, list_11>::value, "bad Or");
  138. static_assert(!ra::mp::apply<ra::mp::orb, list_00>::value, "bad Or");
  139. static_assert(ra::mp::apply<ra::mp::sum, list_>::value==0, "bad Sum");
  140. static_assert(ra::mp::apply<ra::mp::sum, int_list<2, 4>>::value==6, "bad Sum");
  141. static_assert(ra::mp::apply<ra::mp::prod, list_>::value==1, "bad Prod");
  142. static_assert(ra::mp::apply<ra::mp::prod, int_list<2, 3>>::value==6, "bad Prod");
  143. }
  144. // append.
  145. using A = int_list<0, 2, 3>;
  146. using B = int_list<5, 6, 7>;
  147. using C = int_list<9, 8>;
  148. static_assert(is_same_v<int_list<>, ra::mp::nil>, "");
  149. static_assert(is_same_v<C, tuple<int_c<9>, int_c<8>>>, "");
  150. using O = ra::mp::nil;
  151. using A_B = ra::mp::append<A, B>;
  152. using A_C = ra::mp::append<A, C>;
  153. using C_B = ra::mp::append<C, B>;
  154. static_assert(ra::mp::check_idx<A_B, 0, 2, 3, 5, 6, 7>::value, "bad AB");
  155. static_assert(ra::mp::check_idx<A_C, 0, 2, 3, 9, 8>::value, "bad AB");
  156. static_assert(ra::mp::check_idx<C_B, 9, 8, 5, 6, 7>::value, "bad AB");
  157. static_assert(is_same_v<A, ra::mp::append<A, O>>, "bad A+empty");
  158. static_assert(is_same_v<A, ra::mp::append<O, A>>, "bad empty+A");
  159. // mp::iota.
  160. static_assert(ra::mp::check_idx<ra::mp::iota<4, 0>, 0, 1, 2, 3>::value, "0a");
  161. static_assert(ra::mp::check_idx<ra::mp::iota<4, 3>, 3, 4, 5, 6>::value, "0b");
  162. static_assert(ra::mp::check_idx<ra::mp::iota<0, 3>>::value, "0c");
  163. static_assert(ra::mp::check_idx<ra::mp::iota<1, 3>, 3>::value, "0d");
  164. static_assert(ra::mp::check_idx<ra::mp::iota<3, -2>, -2, -1, 0>::value, "0e");
  165. static_assert(ra::mp::check_idx<ra::mp::iota<4, 3, -1>, 3, 2, 1, 0>::value, "0a");
  166. // makelist
  167. static_assert(ra::mp::check_idx<ra::mp::makelist<2, int_c<9>>, 9, 9>::value, "1a");
  168. static_assert(ra::mp::check_idx<ra::mp::makelist<0, int_c<9>>>::value, "1b");
  169. // ref
  170. static_assert(ref<tuple<A, B, C>, 0, 0>::value==0, "3a");
  171. static_assert(ref<tuple<A, B, C>, 0, 1>::value==2, "3b");
  172. static_assert(ref<tuple<A, B, C>, 0, 2>::value==3, "3c");
  173. static_assert(ref<tuple<A, B, C>, 1, 0>::value==5, "3d");
  174. static_assert(ref<tuple<A, B, C>, 1, 1>::value==6, "3e");
  175. static_assert(ref<tuple<A, B, C>, 1, 2>::value==7, "3f");
  176. static_assert(ref<tuple<A, B, C>, 2, 0>::value==9, "3g");
  177. static_assert(ref<tuple<A, B, C>, 2, 1>::value==8, "3h");
  178. static_assert(ra::mp::first<B>::value==5 && ra::mp::first<C>::value==9, "3i");
  179. static_assert(ra::mp::last<B>::value==7 && ra::mp::last<C>::value==8, "3j");
  180. // Useful default.
  181. static_assert(ra::mp::len<ref<ra::mp::nil>> ==0, "3i");
  182. // 3-indices.
  183. using S2AB = tuple<A, B>;
  184. using S2BC = tuple<B, C>;
  185. using S3 = tuple<S2AB, S2BC>;
  186. // in S2AB.
  187. static_assert(ref<S3, 0, 0, 0>::value==0, "3j");
  188. static_assert(ref<S3, 0, 0, 1>::value==2, "3k");
  189. static_assert(ref<S3, 0, 0, 2>::value==3, "3l");
  190. static_assert(ref<S3, 0, 1, 0>::value==5, "3m");
  191. static_assert(ref<S3, 0, 1, 1>::value==6, "3n");
  192. static_assert(ref<S3, 0, 1, 2>::value==7, "3o");
  193. // in S2BC.
  194. static_assert(ref<S3, 1, 0, 0>::value==5, "3p");
  195. static_assert(ref<S3, 1, 0, 1>::value==6, "3q");
  196. static_assert(ref<S3, 1, 0, 2>::value==7, "3r");
  197. static_assert(ref<S3, 1, 1, 0>::value==9, "3s");
  198. static_assert(ref<S3, 1, 1, 1>::value==8, "3t");
  199. // index.
  200. static_assert(ra::mp::index<A, int_c<0>>::value==0, "4a");
  201. static_assert(ra::mp::index<A, int_c<2>>::value==1, "4b");
  202. static_assert(ra::mp::index<A, int_c<3>>::value==2, "4c");
  203. static_assert(ra::mp::index<A, int_c<4>>::value==-1, "4d");
  204. static_assert(ra::mp::index<S3, S2BC>::value==1, "4e");
  205. // InvertIndex
  206. {
  207. using II0 = int_list<4, 6, 7, 1>;
  208. using II1 = ra::mp::InvertIndex<II0>;
  209. static_assert(is_same_v<int_list<-1, 3, -1, -1, 0, -1, 1, 2>, II1>);
  210. }
  211. {
  212. using II0 = int_list<3>;
  213. using II1 = ra::mp::InvertIndex<II0>;
  214. static_assert(is_same_v<int_list<-1, -1, -1, 0>, II1>);
  215. }
  216. {
  217. using II0 = int_list<>;
  218. using II1 = ra::mp::InvertIndex<II0>;
  219. static_assert(is_same_v<int_list<>, II1>);
  220. }
  221. // IndexIf.
  222. static_assert(ra::mp::IndexIf<A, SamePP<int_c<0>>::type>::value==0, "5a");
  223. static_assert(ra::mp::IndexIf<A, SamePP<int_c<2>>::type>::value==1, "5b");
  224. static_assert(ra::mp::IndexIf<A, SamePP<int_c<3>>::type>::value==2, "5c");
  225. static_assert(ra::mp::IndexIf<A, SamePP<int_c<9>>::type>::value==-1, "5d");
  226. // findtail.
  227. static_assert(is_same_v<ra::mp::findtail<A, int_c<0>>, A>, "4a");
  228. static_assert(ra::mp::check_idx<ra::mp::findtail<A, int_c<2>>, 2, 3>::value, "4b");
  229. static_assert(ra::mp::check_idx<ra::mp::findtail<A, int_c<3>>, 3>::value, "4c");
  230. static_assert(ra::mp::nilp<ra::mp::findtail<A, int_c<4>>>, "4d");
  231. static_assert(is_same_v<ra::mp::findtail<S3, S2BC>, tuple<S2BC>>, "4e");
  232. // reverse.
  233. static_assert(ra::mp::check_idx<ra::mp::reverse<A_B>, 7, 6, 5, 3, 2, 0>::value, "5a");
  234. static_assert(ra::mp::check_idx<ra::mp::reverse<O>>::value, "5b");
  235. static_assert(is_same_v<ra::mp::reverse<ra::mp::nil>, ra::mp::nil>, "bad reverse");
  236. // drop & take
  237. static_assert(ra::mp::check_idx<ra::mp::drop<A, 0>, 0, 2, 3>::value, "bad 6a");
  238. static_assert(ra::mp::check_idx<ra::mp::drop<A, 1>, 2, 3>::value, "bad 6b");
  239. static_assert(ra::mp::check_idx<ra::mp::drop<A, 2>, 3>::value, "bad 6c");
  240. static_assert(ra::mp::check_idx<ra::mp::drop<A, 3>>::value, "bad 6d");
  241. static_assert(ra::mp::check_idx<ra::mp::take<A, 0>>::value, "bad 6e");
  242. static_assert(ra::mp::check_idx<ra::mp::take<A, 1>, 0>::value, "bad 6f");
  243. static_assert(ra::mp::check_idx<ra::mp::take<A, 2>, 0, 2>::value, "bad 6g");
  244. static_assert(ra::mp::check_idx<ra::mp::take<A, 3>, 0, 2, 3>::value, "bad 6h");
  245. // complement.
  246. {
  247. using case1 = int_list<1>;
  248. static_assert(ra::mp::check_idx<ra::mp::complement<case1, 0>>::value, "");
  249. static_assert(ra::mp::check_idx<ra::mp::complement<case1, 1>, 0>::value, "");
  250. static_assert(ra::mp::check_idx<ra::mp::complement<case1, 2>, 0>::value, "");
  251. static_assert(ra::mp::check_idx<ra::mp::complement<case1, 3>, 0, 2>::value, "");
  252. using list3 = ra::mp::iota<3>;
  253. static_assert(ra::mp::check_idx<ra::mp::complement<list3, 3>>::value, "");
  254. using c36 = ra::mp::complement<list3, 6>;
  255. static_assert(ra::mp::check_idx<c36, 3, 4, 5>::value, "");
  256. static_assert(ra::mp::check_idx<ra::mp::complement<c36, 6>, 0, 1, 2>::value, "");
  257. using case0 = tuple<int_c<0>>;
  258. static_assert(ra::mp::check_idx<ra::mp::complement<case0, 0>>::value, "");
  259. static_assert(ra::mp::check_idx<ra::mp::complement<case0, 1>>::value, "");
  260. static_assert(ra::mp::check_idx<ra::mp::complement<case0, 2>, 1>::value, "");
  261. }
  262. // complement_sorted_list && complement_list.
  263. {
  264. #define _ ,
  265. #define CHECK_COMPLEMENT_SLIST( A, B, C ) \
  266. static_assert(ra::mp::check_idx<ra::mp::complement_sorted_list<int_list A , B > C >::value, "a");
  267. CHECK_COMPLEMENT_SLIST( <1>, int_list<>, )
  268. CHECK_COMPLEMENT_SLIST( <1>, int_list<0>, _ 0)
  269. CHECK_COMPLEMENT_SLIST( <1>, int_list<0 _ 1>, _ 0)
  270. CHECK_COMPLEMENT_SLIST( <1>, int_list<0 _ 1 _ 2>, _ 0 _ 2)
  271. using l2 = ra::mp::iota<2>;
  272. CHECK_COMPLEMENT_SLIST( <0>, l2, _ 1 )
  273. CHECK_COMPLEMENT_SLIST( <1>, l2, _ 0 )
  274. CHECK_COMPLEMENT_SLIST( <>, l2, _ 0 _ 1 )
  275. using l3 = ra::mp::iota<3>;
  276. CHECK_COMPLEMENT_SLIST( <0 _ 1>, l3, _ 2 )
  277. CHECK_COMPLEMENT_SLIST( <0 _ 2>, l3, _ 1 )
  278. CHECK_COMPLEMENT_SLIST( <1 _ 2>, l3, _ 0 )
  279. CHECK_COMPLEMENT_SLIST( <0>, l3, _ 1 _ 2 )
  280. CHECK_COMPLEMENT_SLIST( <1>, l3, _ 0 _ 2 )
  281. CHECK_COMPLEMENT_SLIST( <2>, l3, _ 0 _ 1 )
  282. CHECK_COMPLEMENT_SLIST( <>, l3, _ 0 _ 1 _ 2 )
  283. CHECK_COMPLEMENT_SLIST( <>, ra::mp::nil, )
  284. #undef CHECK_COMPLEMENT_SLIST
  285. #undef _
  286. #define _ ,
  287. #define CHECK_COMPLEMENT_LIST( A, B, C ) \
  288. static_assert(ra::mp::check_idx<ra::mp::complement_list<int_list A , B > C >::value, "a");
  289. using l2 = ra::mp::iota<2>;
  290. CHECK_COMPLEMENT_LIST( <0>, l2, _ 1 )
  291. CHECK_COMPLEMENT_LIST( <1>, l2, _ 0 )
  292. CHECK_COMPLEMENT_LIST( <>, l2, _ 0 _ 1 )
  293. using l3 = ra::mp::iota<3>;
  294. CHECK_COMPLEMENT_LIST( <0 _ 1>, l3, _ 2 )
  295. CHECK_COMPLEMENT_LIST( <0 _ 2>, l3, _ 1 )
  296. CHECK_COMPLEMENT_LIST( <1 _ 2>, l3, _ 0 )
  297. CHECK_COMPLEMENT_LIST( <0>, l3, _ 1 _ 2 )
  298. CHECK_COMPLEMENT_LIST( <1>, l3, _ 0 _ 2 )
  299. CHECK_COMPLEMENT_LIST( <2>, l3, _ 0 _ 1 )
  300. CHECK_COMPLEMENT_LIST( <>, l3, _ 0 _ 1 _ 2 )
  301. CHECK_COMPLEMENT_LIST( <>, ra::mp::nil, )
  302. // this must also work on unserted lists.
  303. CHECK_COMPLEMENT_LIST( <1 _ 0>, l3, _ 2 )
  304. CHECK_COMPLEMENT_LIST( <2 _ 1>, l3, _ 0 )
  305. CHECK_COMPLEMENT_LIST( <2 _ 0>, l3, _ 1 )
  306. using x3 = int_list<2, 0, 1>;
  307. CHECK_COMPLEMENT_LIST( <1 _ 0>, x3, _ 2 )
  308. CHECK_COMPLEMENT_LIST( <2 _ 0>, x3, _ 1 )
  309. CHECK_COMPLEMENT_LIST( <2 _ 1>, x3, _ 0 )
  310. #undef CHECK_COMPLEMENT_LIST
  311. #undef _
  312. }
  313. // MapCons.
  314. {
  315. using a = ra::mp::iota<2>;
  316. using b = ra::mp::iota<2, 1>;
  317. using mc = ra::mp::MapCons<int_c<9>, tuple<a, b>>;
  318. static_assert(ra::mp::check_idx<ref<mc, 0>, 9, 0, 1>::value, "a");
  319. static_assert(ra::mp::check_idx<ref<mc, 1>, 9, 1, 2>::value, "b");
  320. }
  321. // Combinations.
  322. {
  323. static_assert(ra::mp::len<ra::mp::combinations<ra::mp::nil, 0>> == 1, "");
  324. using l3 = ra::mp::iota<3>;
  325. using c31 = ra::mp::combinations<l3, 1>;
  326. using c32 = ra::mp::combinations<l3, 2>;
  327. static_assert(ra::mp::len<c31> == 3, "a");
  328. static_assert(ra::mp::check_idx<ref<c31, 0>, 0>::value, "a");
  329. static_assert(ra::mp::check_idx<ref<c31, 1>, 1>::value, "b");
  330. static_assert(ra::mp::check_idx<ref<c31, 2>, 2>::value, "c");
  331. static_assert(ra::mp::len<c32> == 3, "b");
  332. static_assert(ra::mp::check_idx<ref<c32, 0>, 0, 1>::value, "d");
  333. static_assert(ra::mp::check_idx<ref<c32, 1>, 0, 2>::value, "e");
  334. static_assert(ra::mp::check_idx<ref<c32, 2>, 1, 2>::value, "f");
  335. using l4 = ra::mp::iota<4>;
  336. using c40 = ra::mp::combinations<l4, 0>;
  337. using c41 = ra::mp::combinations<l4, 1>;
  338. using c42 = ra::mp::combinations<l4, 2>;
  339. using c43 = ra::mp::combinations<l4, 3>;
  340. using c44 = ra::mp::combinations<l4, 4>;
  341. static_assert(ra::mp::len<c40> == 1, "a");
  342. static_assert(ra::mp::check_idx<ref<c40, 0>>::value, "a");
  343. static_assert(ra::mp::len<c41> == 4, "b");
  344. static_assert(ra::mp::check_idx<ref<c41, 0>, 0>::value, "b");
  345. static_assert(ra::mp::check_idx<ref<c41, 1>, 1>::value, "b");
  346. static_assert(ra::mp::check_idx<ref<c41, 2>, 2>::value, "b");
  347. static_assert(ra::mp::check_idx<ref<c41, 3>, 3>::value, "b");
  348. static_assert(ra::mp::len<c42> == 6, "c");
  349. static_assert(ra::mp::check_idx<ref<c42, 0>, 0, 1>::value, "c");
  350. static_assert(ra::mp::check_idx<ref<c42, 1>, 0, 2>::value, "c");
  351. static_assert(ra::mp::check_idx<ref<c42, 2>, 0, 3>::value, "c");
  352. static_assert(ra::mp::check_idx<ref<c42, 3>, 1, 2>::value, "c");
  353. static_assert(ra::mp::check_idx<ref<c42, 4>, 1, 3>::value, "c");
  354. static_assert(ra::mp::check_idx<ref<c42, 5>, 2, 3>::value, "c");
  355. static_assert(ra::mp::len<c43> == 4, "d");
  356. static_assert(ra::mp::check_idx<ref<c43, 0>, 0, 1, 2>::value, "d");
  357. static_assert(ra::mp::check_idx<ref<c43, 1>, 0, 1, 3>::value, "d");
  358. static_assert(ra::mp::check_idx<ref<c43, 2>, 0, 2, 3>::value, "d");
  359. static_assert(ra::mp::check_idx<ref<c43, 3>, 1, 2, 3>::value, "d");
  360. static_assert(ra::mp::len<c44> == 1, "e");
  361. static_assert(ra::mp::check_idx<ref<c44, 0>, 0, 1, 2, 3>::value, "e");
  362. }
  363. // MapPrepend & ProductAppend.
  364. {
  365. using la = ra::mp::iota<3>;
  366. using ca = ra::mp::combinations<la, 1>;
  367. using lb = ra::mp::iota<3>;
  368. using cb = ra::mp::combinations<lb, 1>;
  369. using test0 = ra::mp::MapPrepend<ra::mp::nil, cb>;
  370. static_assert(is_same_v<test0, cb>, "");
  371. using test1 = ra::mp::MapPrepend<la, cb>;
  372. static_assert(ra::mp::len<test1> == int(ra::mp::len<cb>), "");
  373. static_assert(ra::mp::check_idx<ref<test1, 0>, 0, 1, 2, 0>::value, "");
  374. static_assert(ra::mp::check_idx<ref<test1, 1>, 0, 1, 2, 1>::value, "");
  375. static_assert(ra::mp::check_idx<ref<test1, 2>, 0, 1, 2, 2>::value, "");
  376. using test2 = ra::mp::ProductAppend<ca, cb>;
  377. static_assert(ra::mp::len<test2> == 9, "");
  378. static_assert(ra::mp::check_idx<ref<test2, 0>, 0, 0>::value, "");
  379. static_assert(ra::mp::check_idx<ref<test2, 1>, 0, 1>::value, "");
  380. static_assert(ra::mp::check_idx<ref<test2, 2>, 0, 2>::value, "");
  381. static_assert(ra::mp::check_idx<ref<test2, 3>, 1, 0>::value, "");
  382. static_assert(ra::mp::check_idx<ref<test2, 4>, 1, 1>::value, "");
  383. static_assert(ra::mp::check_idx<ref<test2, 5>, 1, 2>::value, "");
  384. static_assert(ra::mp::check_idx<ref<test2, 6>, 2, 0>::value, "");
  385. static_assert(ra::mp::check_idx<ref<test2, 7>, 2, 1>::value, "");
  386. static_assert(ra::mp::check_idx<ref<test2, 8>, 2, 2>::value, "");
  387. }
  388. // PermutationSign.
  389. {
  390. #define _ ,
  391. #define CHECK_PERM_SIGN( A, B, C ) \
  392. static_assert(ra::mp::PermutationSign<int_list A , int_list B >::value == C, "");
  393. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <0 _ 1 _ 2>, +1 );
  394. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <0 _ 2 _ 1>, -1 );
  395. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <1 _ 2 _ 0>, +1 );
  396. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <2 _ 1 _ 0>, -1 );
  397. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <1 _ 0 _ 2>, -1 );
  398. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <2 _ 0 _ 1>, +1 );
  399. // inverted.
  400. CHECK_PERM_SIGN( <0 _ 1 _ 2>, <0 _ 1 _ 2>, +1 );
  401. CHECK_PERM_SIGN( <0 _ 2 _ 1>, <0 _ 1 _ 2>, -1 );
  402. CHECK_PERM_SIGN( <1 _ 2 _ 0>, <0 _ 1 _ 2>, +1 );
  403. CHECK_PERM_SIGN( <2 _ 1 _ 0>, <0 _ 1 _ 2>, -1 );
  404. CHECK_PERM_SIGN( <1 _ 0 _ 2>, <0 _ 1 _ 2>, -1 );
  405. CHECK_PERM_SIGN( <2 _ 0 _ 1>, <0 _ 1 _ 2>, +1 );
  406. // other cases.
  407. CHECK_PERM_SIGN( <0>, <0>, +1 );
  408. CHECK_PERM_SIGN( <>, <>, +1 );
  409. CHECK_PERM_SIGN( <0>, <1>, 0 );
  410. CHECK_PERM_SIGN( <0>, <>, 0 );
  411. CHECK_PERM_SIGN( <>, <0>, 0 );
  412. #undef CHECK_PERM_SIGN
  413. #undef _
  414. }
  415. // inc
  416. {
  417. using l = int_list<7, 8, 2>;
  418. static_assert(ra::mp::check_idx<l, 7, 8, 2>::value, "bad");
  419. static_assert(ra::mp::check_idx<ra::mp::inc<l, 0>, 8, 8, 2>::value, "bad");
  420. static_assert(ra::mp::check_idx<ra::mp::inc<l, 1>, 7, 9, 2>::value, "bad");
  421. static_assert(ra::mp::check_idx<ra::mp::inc<l, 2>, 7, 8, 3>::value, "bad");
  422. }
  423. // Prod & Sum
  424. {
  425. using l = int_list<3, 5, 7>;
  426. static_assert(ra::mp::apply<ra::mp::prod, l>::value==105, "bad");
  427. static_assert(ra::mp::apply<ra::mp::sum, l>::value==15, "bad");
  428. }
  429. // tuples in dynamic context
  430. {
  431. using l = int_list<3, 4, 5>;
  432. tr.test_eq(0, ra::mp::int_list_index<l>(3));
  433. tr.test_eq(1, ra::mp::int_list_index<l>(4));
  434. tr.test_eq(2, ra::mp::int_list_index<l>(5));
  435. tr.test_eq(-1, ra::mp::int_list_index<l>(7));
  436. }
  437. return tr.summary();
  438. };