big-0.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - Tests specific to Container, constructors.
  3. // (c) Daniel Llorens - 2017-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. #include "mpdebug.hh"
  12. using std::cout, std::endl, std::flush, ra::TestRecorder;
  13. template <class T> constexpr bool ctest1 = requires { ra::Big<T, 2> ({2, 3, 1}, 99); }; // bad shape for rank
  14. template <class T> constexpr bool ctest2 = requires { ra::Big<T, 2> ({2, 3, 1}, {1, 2, 3, 4, 5, 6}); }; // bad shape for rank
  15. template <class T> constexpr bool ctest3 = requires { ra::Big<T, 2> ({2, 3, 1}, ra::none); }; // bad shape for rank
  16. template <class T> constexpr bool ctest4 = requires { ra::Big<T, 0> ({3, 4}, 3.); }; // bad shape for rank
  17. int main(int argc, char * * argv)
  18. {
  19. TestRecorder tr;
  20. tr.section("predicates");
  21. {
  22. ra::ViewBig<int, 2> a;
  23. static_assert(ra::rank_s<decltype(a().iter<0>())>()==ra::rank_s<decltype(a().iter())>());
  24. }
  25. tr.section("constructors");
  26. {
  27. tr.section("null View constructor");
  28. {
  29. ra::ViewBig<int, 1> a;
  30. tr.test(nullptr==a.data());
  31. }
  32. tr.section("regression with some shape arguments (fixed rank)");
  33. {
  34. ra::Big<int, 1> sizes = {5};
  35. ra::Big<double, 1> a(sizes, ra::none);
  36. a = 33.;
  37. tr.test_eq(5, a.size());
  38. tr.test_eq(33, a);
  39. }
  40. {
  41. ra::Big<int> sizes = {5};
  42. ra::Big<double, 1> a(sizes, ra::none);
  43. a = 33.;
  44. tr.test_eq(5, a.size());
  45. tr.test_eq(33, a);
  46. }
  47. tr.section("regression with implicitly declared View constructors [ra38]. Reduced from examples/maxwell.cc");
  48. {
  49. ra::Big<int, 1> A = {1, 2};
  50. ra::Big<int, 1> X = {0, 0};
  51. X(ra::all) = A();
  52. tr.test_eq(ra::start({1, 2}), X);
  53. }
  54. tr.section("need for non-default View::operator=(View const & x) [ra34]");
  55. {
  56. ra::Big<int, 1> a {0, 1, 2, 3, 4, 5};
  57. ra::ViewBig<int, 1> const va = a();
  58. ra::Big<int, 1> x(va); // replacing default operator= by copy-to-view.
  59. tr.test_eq(ra::iota(6), x);
  60. }
  61. tr.section("init list constructors handle implicit conversions");
  62. {
  63. ra::Big<int, 2> a({int(3), ra::dim_t(2)}, {0, 1, 2, 3, 4, 5});
  64. tr.test_eq(ra::_0 * 2 + ra::_1, a);
  65. tr.test_eq(3, a.len(0));
  66. tr.test_eq(2, a.len(1));
  67. }
  68. }
  69. tr.section("should-fail constructors");
  70. {
  71. static_assert(!ctest1<int>);
  72. static_assert(!ctest2<int>);
  73. static_assert(!ctest3<int>);
  74. static_assert(!ctest4<int>);
  75. // FIXME these errors depend on static_assert so cannot be checked with requires.
  76. // ra::Big<T, 2> {3, 4}; // Invalid shape for rank
  77. // ra::Big<int, 2> (2, ra::none); // shape arg must have rank 1 for array rank>1
  78. // ra::Big<T, 2> {1, 2, 3, 4, 5, 6}; // bad deduced shape from content arg
  79. // ra::Big<T, 2> (ra::Small<int, 3>{2, 3, 4}, 99.); // bad shape for rank
  80. }
  81. tr.section("any rank 1 expression for the shape argument");
  82. {
  83. ra::Big<int, 2> a (2+ra::iota(2), {0, 1, 2, 3, 4, 5});
  84. tr.test_eq(ra::Small<int, 2, 3> {{0, 1, 2}, {3, 4, 5}}, a);
  85. }
  86. tr.section("even non-drivable expressions if the rank is fixed");
  87. {
  88. ra::Big<int, 2> a(ra::_0 + 2, {0, 1, 2, 3, 4, 5});
  89. tr.test_eq(ra::Small<int, 2, 3> {{0, 1, 2}, {3, 4, 5}}, a);
  90. }
  91. tr.section("also on raw views");
  92. {
  93. int ap[6] = {0, 1, 2, 3, 4, 5};
  94. ra::ViewBig<int, 2> a(2+ra::iota(2), ap);
  95. tr.test_eq(2, a.len(0));
  96. tr.test_eq(3, a.len(1));
  97. tr.test_eq(ra::Small<int, 2, 3> {{0, 1, 2}, {3, 4, 5}}, a);
  98. tr.test_eq(ra::scalar(ap), ra::scalar(a.data()));
  99. }
  100. tr.section("also on raw views with var rank");
  101. {
  102. int ap[6] = {0, 1, 2, 3, 4, 5};
  103. ra::ViewBig<int> a(2+ra::iota(2), ap);
  104. tr.test_eq(2, a.len(0));
  105. tr.test_eq(3, a.len(1));
  106. tr.test_eq(ra::Small<int, 2, 3> {{0, 1, 2}, {3, 4, 5}}, a);
  107. tr.test_eq(ra::scalar(ap), ra::scalar(a.data()));
  108. }
  109. tr.section("nested braces operator=");
  110. {
  111. ra::Big<int, 2> a({2, 3}, {0, 1, 2, 3, 4, 5});
  112. auto ap = a.data();
  113. {
  114. // this uses operator=(nested_braces_r)
  115. a() = {{4, 5, 6}, {7, 8, 9}};
  116. tr.test_eq(ra::scalar(ap), ra::scalar(a.data()));
  117. tr.test_eq(ra::iota(6, 4), ra::ptr(a.data()));
  118. }
  119. {
  120. // uses operator=(nested_braces_r)
  121. a = {{5, 6, 7}, {8, 9, 10}};
  122. tr.test_eq(ra::scalar(ap), ra::scalar(a.data()));
  123. tr.test_eq(ra::iota(6, 5), ra::ptr(a.data()));
  124. // uses nested_braces_r constructor, so a's storage is NOT preserved. Don't rely on this either way
  125. a = {{{4, 5, 6}, {7, 8, 9}}};
  126. tr.skip().test_eq(ra::scalar(ap), ra::scalar(a.data()));
  127. tr.test_eq(2, a.len(0));
  128. tr.test_eq(3, a.len(1));
  129. tr.test_eq(ra::iota(6, 4), ra::ptr(a.data()));
  130. }
  131. }
  132. tr.section("nested braces constructor");
  133. {
  134. ra::Big<int, 2> a = {{4, 5, 6}, {7, 8, 9}};
  135. tr.test_eq(2, a.len(0));
  136. tr.test_eq(3, a.len(1));
  137. tr.test_eq(ra::iota(6, 4), ra::ptr(a.data()));
  138. }
  139. tr.section("nested braces for nested type I");
  140. {
  141. using int2 = ra::Small<int, 2>;
  142. // FIXME removed (shape, nested) constructors so this wouldn't be ambiguous (bc 1 converts to int2). But maybe int shouldn't convert to int2 [ra16]
  143. ra::Big<int2, 2> a({2, 2}, { {1, 2}, {2, 3}, {4, 5}, {6, 7} });
  144. ra::Big<int2, 2> b({{{1, 2}, {2, 3}}, {{4, 5}, {6, 7}}});
  145. ra::Big<int2, 2> c {{{1, 2}, {2, 3}}, {{4, 5}, {6, 7}}};
  146. ra::Big<int2, 2> d = {{{1, 2}, {2, 3}}, {{4, 5}, {6, 7}}};
  147. tr.test_eq(a, b);
  148. tr.test_eq(a, c);
  149. tr.test_eq(a, d);
  150. }
  151. tr.section("nested braces for nested type II");
  152. {
  153. int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
  154. int y[2][3] = {{10, 20, 30}, {40, 50, 60}};
  155. ra::Big<ra::Small<int, 2, 3>, 1> a = {x, y};
  156. tr.test_eq(ra::_0*3+ra::_1 + 1, a(0));
  157. tr.test_eq(10*(ra::_0*3+ra::_1 + 1), a(1));
  158. }
  159. tr.section("nested braces for nested type II");
  160. {
  161. int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
  162. int y[2][3] = {{10, 20, 30}, {40, 50, 60}};
  163. ra::Big<ra::Small<int, 2, 3>, 1> a = {x, y};
  164. tr.test_eq(ra::_0*3+ra::_1 + 1, a(0));
  165. tr.test_eq(10*(ra::_0*3+ra::_1 + 1), a(1));
  166. }
  167. tr.section("nested braces for nested type III");
  168. {
  169. int x[4] = {1, 2, 3, 4};
  170. int y[6] = {10, 20, 30, 40, 50, 60};
  171. ra::Big<ra::Big<int, 1>, 1> a = {x, y};
  172. tr.test_eq(ra::iota(4, 1), a(0));
  173. tr.test_eq(ra::iota(6, 10, 10), a(1));
  174. }
  175. tr.section("nested braces for nested type IV");
  176. {
  177. ra::Big<ra::Big<int, 1>, 1> a = {{1, 2, 3, 4}, {10, 20, 30, 40, 50, 60}};
  178. tr.test_eq(ra::iota(4, 1), a(0));
  179. tr.test_eq(ra::iota(6, 10, 10), a(1));
  180. }
  181. tr.section("nested braces for nested type V [ra45]");
  182. {
  183. int u[3] = { 1, 2, 3 };
  184. ra::Big<int, 1> v = u;
  185. ra::Small<ra::Big<int, 1>, 1> b = { {u} }; // ok; broken with { u }
  186. tr.test_eq(ra::iota(3, 1), b(0));
  187. ra::Small<ra::Big<int, 1>, 1> c = { v }; // ok
  188. tr.test_eq(ra::iota(3, 1), c(0));
  189. ra::Small<ra::Big<int, 1>, 1> d = { {1, 2, 3} }; // ok
  190. tr.test_eq(ra::iota(3, 1), d(0));
  191. auto x = ra::iota(3, 1);
  192. ra::Small<ra::Big<int, 1>, 1> f = { {x} }; // ok; broken with { x }
  193. tr.test_eq(ra::iota(3, 1), f(0));
  194. // ra::Small<int, 3> w = { 1, 2, 3 };
  195. // ra::Small<ra::Big<int, 1>, 1> e = { w }; // broken with { w }, ct error with { {w} }
  196. // tr.test_eq(ra::iota(3, 1), e(0));
  197. }
  198. tr.section("nested braces for nested type VI");
  199. {
  200. ra::Small<ra::Big<double, 1>, 3> g = { { 1 }, { 1, 2 }, { 1, 2, 3 } };
  201. tr.test_eq(ra::start({1}), g[0]);
  202. tr.test_eq(ra::start({1, 2}), g[1]);
  203. tr.test_eq(ra::start({1, 2, 3}), g[2]);
  204. }
  205. tr.section("more nested braces");
  206. {
  207. tr.section("with dynamic rank");
  208. ra::Small<float, 2, 4> ref = { {1, 2, 3, 4}, {5, 6, 7, 8} };
  209. ra::Big<float> A = { {1, 2, 3, 4}, {5, 6, 7, 8} };
  210. ra::Big<float> B({2, 4}, {1, 2, 3, 4, 5, 6, 7, 8});
  211. // ra::Big<float> C({2, 4}, { {1, 2, 3, 4}, {5, 6, 7, 8} }); // not allowed bc ambiguity with empty braces
  212. ra::Big<float, 2> A2 = { {1, 2, 3, 4}, {5, 6, 7, 8} };
  213. ra::Big<float, 2> B2({2, 4}, {1, 2, 3, 4, 5, 6, 7, 8});
  214. // ra::Big<float, 2> C2({2, 4}, { {1, 2, 3, 4}, {5, 6, 7, 8} }); // not allowed to avoid ambiguity in [ra16] :-/
  215. tr.test_eq(ref, A);
  216. tr.test_eq(ref, B);
  217. tr.test_eq(ref, A2);
  218. tr.test_eq(ref, B2);
  219. }
  220. // FIXME This works for Small, that has multi-arg constructors. Right now this calls the 2-elem constructor shape, content instead of the braces constructor, since initializer_list<T> doesn't match.
  221. // tr.section("item constructor");
  222. // {
  223. // ra::Big<int, 2> a {{1, 2}, ra::iota(2, 33)};
  224. // tr.test_eq(1, a(0, 0));
  225. // tr.test_eq(2, a(0, 1));
  226. // tr.test_eq(33, a(1, 0));
  227. // tr.test_eq(34, a(1, 1));
  228. // }
  229. tr.section("at() takes foreign vector");
  230. {
  231. ra::Big<double, 2> a({3, 3}, ra::_0 + 10*ra::_1);
  232. std::array<int, 2> b = {2, 2};
  233. tr.test_eq(22, a.at(b));
  234. }
  235. tr.section("default constructor of var rank");
  236. {
  237. ra::Big<int> a {};
  238. ra::Big<int, 1> b {};
  239. tr.test_eq(b.rank(), a.rank());
  240. tr.test_eq(b.len(0), a.len(0));
  241. tr.test_eq(1, a.rank());
  242. tr.test_eq(0, a.len(0));
  243. }
  244. tr.section("allow scalar shape for rank 1");
  245. {
  246. ra::Big<int> a(3, ra::_0);
  247. tr.test_eq(1, rank(a));
  248. tr.test_eq(ra::iota(3), a);
  249. ra::Big<int, 1> b(4, ra::_0);
  250. tr.test_eq(ra::iota(4), b);
  251. }
  252. tr.section("default constructor for ct rank 0 Container");
  253. {
  254. ra::Big<int, 0> a = {}; // uninitialized
  255. a = 3;
  256. tr.test_eq(3, a);
  257. }
  258. tr.section("scalar constructor for rt rank 0 Container");
  259. {
  260. ra::Big<int> a(4);
  261. tr.test_eq(4, a);
  262. }
  263. tr.section("index with rank 0 exprs");
  264. {
  265. ra::Big<int, 0> a = 1;
  266. ra::Big<int, 1> b = { 1, 2, 3 };
  267. tr.test(std::is_same_v<int &, decltype(b(a))>);
  268. tr.test_eq(2, b(a));
  269. }
  270. tr.section("scalar conversion");
  271. {
  272. ra::Big<int, 0> xa({}, 1);
  273. ra::Big<int, 1> xb({1}, 2);
  274. ra::Big<int, 2> xc({1, 1}, 3);
  275. int a = xa;
  276. int b = xb;
  277. int c = xc;
  278. tr.test_eq(1, a);
  279. tr.test_eq(2, b);
  280. tr.test_eq(3, c);
  281. }
  282. return tr.summary();
  283. }