frame-new.cc 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - Test abilities of post v10 driverless frame matching Map.
  3. // (c) Daniel Llorens - 2019-2023
  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 <iterator>
  10. #include "ra/test.hh"
  11. using std::cout, std::endl, std::flush, ra::TestRecorder;
  12. template <int i> using UU = decltype(std::declval<ra::Unique<double, i>>().iter());
  13. using ra::int_c;
  14. namespace ra::mp {
  15. template <class K, class T, class F>
  16. constexpr auto
  17. fold_tuple(K && k, T && t, F && f)
  18. {
  19. return std::apply([&](auto ... i) { auto r=k; ((r=f(r, i)), ...); return r; }, t);
  20. }
  21. } // namespace ra::mp
  22. int
  23. main()
  24. {
  25. TestRecorder tr(std::cout);
  26. tr.section("view");
  27. {
  28. ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
  29. ra::Big<int, 4> b({2, 2, 3, 4}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
  30. cout << a << endl;
  31. }
  32. tr.section("II");
  33. {
  34. ra::ilist_t<6, 3, -4> x;
  35. static_assert(6==ra::mp::fold_tuple(-99, x, [](auto && k, auto && a) { return max(k, a.value); }));
  36. static_assert(-4==ra::mp::fold_tuple(+99, x, [](auto && k, auto && a) { return min(k, a.value); }));
  37. static_assert(5==ra::mp::fold_tuple(0, x, [](auto && k, auto && a) { return k + a.value; }));
  38. }
  39. tr.section("static size - like Map");
  40. {
  41. ra::Small<int, 2, 3, 4> a = (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1);
  42. ra::Small<int, 2, 3, 4, 5> b = (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1);
  43. #define MAP map_([](auto && a, auto && b) { return a+b; }, start(a), start(b))
  44. tr.test_eq(4, MAP.rank());
  45. tr.test_eq(b.len(0), MAP.len(0));
  46. tr.test_eq(b.len(1), MAP.len(1));
  47. tr.test_eq(b.len(2), MAP.len(2));
  48. tr.test_eq(b.len(3), MAP.len(3));
  49. tr.test_eq(2*3*4*5, size(MAP));
  50. static_assert(4==ra::rank_s<decltype(MAP)>());
  51. static_assert(b.len_s(0)==MAP.len_s(0));
  52. static_assert(b.len_s(1)==MAP.len_s(1));
  53. static_assert(b.len_s(2)==MAP.len_s(2));
  54. static_assert(b.len_s(3)==MAP.len_s(3));
  55. static_assert(2*3*4*5 == ra::size_s<decltype(MAP)>());
  56. #undef MAP
  57. }
  58. tr.section("check mismatches - static");
  59. {
  60. ra::Small<int, 2, 3, 4> a = (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1);
  61. ra::Small<int, 2, 4, 4, 5> b = (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1);
  62. // properly fails to compile, which we cannot check at present [ra42]
  63. // #define MAP map_([](auto && a, auto && b) { return a+b; }, start(a), start(b))
  64. // tr.test_eq(2*3*4*5, ra::size_s<decltype(MAP)>());
  65. // tr.test_eq(3, MAP.len_s(1));
  66. // #undef MAP
  67. // we can use non-static Match::check() as constexpr however.
  68. static_assert(!agree(a, b));
  69. }
  70. tr.section("static rank, dynamic size - like Map");
  71. {
  72. ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
  73. ra::Big<int, 4> b({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
  74. #define MAP map_([](auto && a, auto && b) { return a+b; }, start(a), start(b))
  75. tr.test_eq(4, MAP.rank());
  76. tr.test_eq(b.len(0), MAP.len(0));
  77. tr.test_eq(b.len(1), MAP.len(1));
  78. tr.test_eq(b.len(2), MAP.len(2));
  79. tr.test_eq(b.len(3), MAP.len(3));
  80. tr.test_eq(2*3*4*5, size(MAP));
  81. // could check all statically through decltype, although Big cannot be constexpr yet.
  82. static_assert(4==ra::rank_s<decltype(MAP)>());
  83. tr.test_eq(ra::ANY, MAP.len_s(0));
  84. tr.test_eq(ra::ANY, MAP.len_s(1));
  85. tr.test_eq(ra::ANY, MAP.len_s(2));
  86. tr.test_eq(ra::ANY, MAP.len_s(3));
  87. tr.test_eq(ra::ANY, ra::size_s<decltype(MAP)>());
  88. cout << MAP << endl;
  89. #undef MAP
  90. }
  91. tr.section("check mismatches - dynamic (explicit)");
  92. {
  93. {
  94. ra::Big<int, 3> a({2, 3, 4}, 0);
  95. ra::Big<int, 4> b({2, 4, 4, 5}, 0);
  96. tr.test(!ra::agree(a, b));
  97. // TestRecorder sees mismatches as another kind of error, it used to happen this would RA_ASSERT instead.
  98. // FIXME This isn't true for static mismatches, which will fail to compile.
  99. tr.expectfail().test_eq(a, b);
  100. }
  101. {
  102. ra::Big<int, 3> a({2, 3, 4}, 0);
  103. ra::Big<int, 4> b({2, 3, 4, 5}, 0);
  104. tr.test(ra::agree(a, b));
  105. tr.test_eq(a, b);
  106. }
  107. }
  108. tr.section("dynamic rank - Map driver selection is broken in this case.");
  109. {
  110. ra::Big<int, 3> as({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
  111. ra::Big<int> ad({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
  112. ra::Big<int, 4> bs({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
  113. ra::Big<int> bd({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
  114. #define MAP(a, b) map_([](auto && a, auto && b) { return a+b; }, start(a), start(b))
  115. auto test = [&tr](auto tag, auto && a, auto && b)
  116. {
  117. tr.section(tag);
  118. tr.test_eq(4, MAP(a, b).rank());
  119. tr.info("0d").test_eq(b.len(0), MAP(a, b).len(0));
  120. tr.test_eq(b.len(1), MAP(a, b).len(1));
  121. tr.test_eq(b.len(2), MAP(a, b).len(2));
  122. tr.test_eq(b.len(3), MAP(a, b).len(3));
  123. tr.info("0-size()").test_eq(2*3*4*5, size(MAP(a, b)));
  124. tr.test_eq(ra::ANY, ra::rank_s<decltype(MAP(a, b))>());
  125. tr.test_eq(ra::ANY, ra::size_s<decltype(MAP(a, b))>());
  126. tr.test_eq(ra::ANY, MAP(a, b).len_s(0));
  127. tr.test_eq(ra::ANY, MAP(a, b).len_s(1));
  128. tr.test_eq(ra::ANY, MAP(a, b).len_s(2));
  129. tr.test_eq(ra::ANY, MAP(a, b).len_s(3));
  130. tr.info("0-size_s()").test_eq(ra::ANY, ra::size_s<decltype(MAP(a, b))>());
  131. };
  132. test("sta-dyn", as, bd);
  133. test("dyn-sta", ad, bs);
  134. test("dyn-dyn", ad, bd);
  135. #undef MAP
  136. }
  137. tr.section("cases with periodic axes - dynamic (broken with Map)");
  138. {
  139. ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
  140. auto b = a(ra::all, ra::insert<1>, ra::iota(4, 0, 0));
  141. #define MAP(a, b) map_([](auto && a, auto && b) { return a+b; }, start(a), start(b))
  142. tr.test_eq(4, MAP(a, b).rank());
  143. tr.test_eq(b.len(0), MAP(a, b).len(0));
  144. tr.test_eq(a.len(1), MAP(a, b).len(1));
  145. tr.test_eq(b.len(2), MAP(a, b).len(2));
  146. tr.test_eq(b.len(3), MAP(a, b).len(3));
  147. tr.test_eq(2*3*4*4, size(MAP(a, b)));
  148. // could check all statically through decltype, although Big cannot be constexpr yet.
  149. static_assert(4==ra::rank_s<decltype(MAP(a, b))>());
  150. tr.test_eq(ra::ANY, MAP(a, b).len_s(0));
  151. tr.test_eq(ra::ANY, MAP(a, b).len_s(1));
  152. tr.test_eq(ra::ANY, MAP(a, b).len_s(2));
  153. tr.test_eq(ra::ANY, MAP(a, b).len_s(3));
  154. tr.test_eq(ra::ANY, ra::size_s<decltype(MAP(a, b))>());
  155. cout << MAP(a, b) << endl;
  156. // value test.
  157. ra::Big<int, 4> c({2, 3, 4, 4}, 0);
  158. c(ra::all, 0) = a(ra::all, ra::iota(4, 0, 0));
  159. c(ra::all, 1) = a(ra::all, ra::iota(4, 0, 0));
  160. c(ra::all, 2) = a(ra::all, ra::iota(4, 0, 0));
  161. tr.test_eq((a+c), MAP(a, b));
  162. // order doesn't affect prefix matching with Map
  163. tr.test_eq((a+c), MAP(b, a));
  164. #undef MAP
  165. }
  166. tr.section("broadcasting - like outer product");
  167. {
  168. ra::Big<int, 2> a({4, 3}, 10*ra::_1+100*ra::_0);
  169. ra::Big<int, 1> b({5}, ra::_0);
  170. cout << ra::start(ra::shape(from([](auto && a, auto && b) { return a-b; }, a, b))) << endl;
  171. #define MAP(a, b) map_([](auto && a, auto && b) { return a-b; }, start(a(ra::dots<2>, ra::insert<1>)), start(b(ra::insert<2>, ra::dots<1>)))
  172. tr.test_eq(3, ra::rank_s<decltype(MAP(a, b))>());
  173. tr.test_eq(ra::ANY, MAP(a, b).len_s(0));
  174. tr.test_eq(ra::ANY, MAP(a, b).len_s(1));
  175. tr.test_eq(ra::ANY, MAP(a, b).len_s(2));
  176. tr.test_eq(3, MAP(a, b).rank());
  177. tr.test_eq(4, MAP(a, b).len(0));
  178. tr.test_eq(3, MAP(a, b).len(1));
  179. tr.test_eq(5, MAP(a, b).len(2));
  180. tr.test_eq(from([](auto && a, auto && b) { return a-b; }, a, b), MAP(a, b));
  181. #undef MAP
  182. }
  183. tr.section("Map has operatorX=");
  184. {
  185. ra::Big<int, 2> a({4, 3}, 10*ra::_1+100*ra::_0);
  186. map_([](auto & a) -> decltype(auto) { return a; }, start(a)) += 1;
  187. tr.test_eq(10*ra::_1 + 100*ra::_0 + 1, a);
  188. }
  189. tr.section("Compat with old Map, from ra-0.cc");
  190. {
  191. int p[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  192. int * pp = &p[0]; // force pointer decay in case we ever enforce p's shape
  193. ra::ViewBig<int> d(ra::pack<ra::Dim>(ra::Small<int, 3> {5, 1, 2}, ra::Small<int, 3> {1, 0, 5}), pp);
  194. #define MAP map_([](auto && a, auto && b) { return a==b; }, ra::_0*1 + ra::_1*0 + ra::_2*5 + 1, start(d))
  195. tr.test(every(MAP));
  196. auto x = MAP;
  197. static_assert(ra::ANY==ra::size_s<decltype(x)>());
  198. static_assert(ra::ANY==ra::size_s<decltype(x)>());
  199. tr.test_eq(10, size(MAP));
  200. }
  201. #undef MAP
  202. tr.section("BAD on any len_s(k) means size_s() is BAD");
  203. {
  204. using order = ra::ilist_t<0, 1>;
  205. using T0 = ra::Map<std::multiplies<void>, std::tuple<decltype(ra::iota<0>()), ra::Scalar<int>>, order>;
  206. ra::dim_t s0 = ra::size_s<T0>();
  207. using T1 = ra::Map<std::multiplies<void>, std::tuple<decltype(ra::iota<1>()), ra::Scalar<int>>, order>;
  208. ra::dim_t s1 = ra::size_s<T1>();
  209. using T2 = ra::Map<std::multiplies<void>, std::tuple<decltype(ra::iota<2>()), ra::Scalar<int>>, order>;
  210. ra::dim_t s2 = ra::size_s<T2>();
  211. tr.test_eq(ra::BAD, s0);
  212. tr.test_eq(ra::BAD, s1);
  213. tr.test_eq(ra::BAD, s2);
  214. }
  215. return tr.summary();
  216. }