test-ra-0.C 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. // (c) Daniel Llorens - 2013-2015
  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 test-ra-0.C
  7. /// @brief Checks for ra:: arrays, iterators.
  8. #include <iostream>
  9. #include <iterator>
  10. #include <numeric>
  11. #include <type_traits>
  12. #include "ra/test.H"
  13. #include "ra/big.H"
  14. #include "ra/operators.H"
  15. #include "ra/io.H"
  16. #include "ra/mpdebug.H"
  17. using std::cout; using std::endl; using std::flush;
  18. template <int i> using TI = ra::TensorIndex<i, int>;
  19. template <class A>
  20. void CheckArrayOutput(TestRecorder & tr, A const & a, double * begin)
  21. {
  22. std::ostringstream o;
  23. o << a;
  24. cout << "a: " << o.str() << endl;
  25. std::istringstream i(o.str());
  26. std::istream_iterator<double> iend;
  27. std::istream_iterator<double> ibegin(i);
  28. tr.test(std::equal(ibegin, iend, begin));
  29. }
  30. template <class A>
  31. void CheckArrayIO(TestRecorder & tr, A const & a, double * begin)
  32. {
  33. std::ostringstream o;
  34. o << a;
  35. {
  36. std::istringstream i(o.str());
  37. std::istream_iterator<double> iend;
  38. std::istream_iterator<double> ibegin(i);
  39. tr.info("reading back from '", o.str(), "'").test(std::equal(ibegin, iend, begin));
  40. }
  41. {
  42. std::istringstream i(o.str());
  43. A b;
  44. tr.test(bool(i));
  45. i >> b;
  46. auto as = ra::ra_traits<A>::shape(a);
  47. auto bs = ra::ra_traits<A>::shape(b);
  48. tr.info("shape from '", o.str(), "'").test(std::equal(as.begin(), as.end(), bs.begin()));
  49. tr.info("content").test(std::equal(a.begin(), a.begin(), b.begin()));
  50. }
  51. }
  52. template <int i> using UU = decltype(std::declval<ra::Unique<double, i>>().iter());
  53. using SM1 = decltype(std::declval<ra::Small<double, 2>>().iter());
  54. using SM2 = decltype(std::declval<ra::Small<double, 2, 2>>().iter());
  55. using SM3 = decltype(std::declval<ra::Small<double, 2, 2, 2>>().iter());
  56. using SS = decltype(ra::scalar(1));
  57. template <class A>
  58. void CheckReverse(TestRecorder & tr, A && a)
  59. {
  60. std::iota(a.begin(), a.end(), 1);
  61. cout << "a: " << a << endl;
  62. auto b0 = reverse(a, 0);
  63. cout << "b: " << b0 << endl;
  64. double check0[24] = { 17, 18, 19, 20, 21, 22, 23, 24,
  65. 9, 10, 11, 12, 13, 14, 15, 16,
  66. 1, 2, 3, 4, 5, 6, 7, 8 };
  67. tr.test(std::equal(check0, check0+24, b0.begin()));
  68. auto b1 = reverse(a, 1);
  69. cout << "b: " << b1 << endl;
  70. double check1[24] = { 5, 6, 7, 8, 1, 2, 3, 4,
  71. 13, 14, 15, 16, 9, 10, 11, 12,
  72. 21, 22, 23, 24, 17, 18, 19, 20 };
  73. tr.test(std::equal(check1, check1+24, b1.begin()));
  74. auto b2 = reverse(a, 2);
  75. cout << "b: " << b2 << endl;
  76. double check2[24] = { 4, 3, 2, 1, 8, 7, 6, 5,
  77. 12, 11, 10, 9, 16, 15, 14, 13,
  78. 20, 19, 18, 17, 24, 23, 22, 21 };
  79. tr.test(std::equal(check2, check2+24, b2.begin()));
  80. }
  81. template <class A>
  82. void CheckTranspose1(TestRecorder & tr, A && a)
  83. {
  84. {
  85. std::iota(a.begin(), a.end(), 1);
  86. cout << "a: " << a << endl;
  87. auto b = transpose(ra::Small<int, 2>{1, 0}, a);
  88. cout << "b: " << b << endl;
  89. double check[6] = {1, 3, 5, 2, 4, 6};
  90. tr.test(std::equal(b.begin(), b.end(), check));
  91. }
  92. {
  93. std::iota(a.begin(), a.end(), 1);
  94. cout << "a: " << a << endl;
  95. auto b = transpose<1, 0>(a);
  96. cout << "b: " << b << endl;
  97. double check[6] = {1, 3, 5, 2, 4, 6};
  98. tr.test(std::equal(b.begin(), b.end(), check));
  99. }
  100. }
  101. int main()
  102. {
  103. TestRecorder tr(std::cout);
  104. tr.section("concepts");
  105. {
  106. ra::Small<int, 2> a(0.), b(0.);
  107. auto e0 = ra::expr([](int a, int b) { return a+b; }, start(a), start(b));
  108. static_assert(std::is_literal_type<decltype(e0)>::value);
  109. auto e1 = ra::expr([](int a, int b) { return a+b; }, start(a), ra::scalar(0.));
  110. static_assert(std::is_literal_type<decltype(e1)>::value);
  111. auto e2 = ra::expr([](int a, int b) { return a+b; }, start(a), ra::iota(2));
  112. static_assert(std::is_literal_type<decltype(e2)>::value);
  113. }
  114. tr.section("internal fields");
  115. {
  116. {
  117. double aa[10];
  118. aa[0] = 99;
  119. ra::View<double, 1> a { {{10, 1}}, aa };
  120. tr.test_eq(99., a.p[0]);
  121. }
  122. {
  123. double aa[6] = { 1, 2, 3, 4, 5, 6 };
  124. aa[0] = 99;
  125. ra::View<double, 2> a { {{3, 2}, {2, 1}}, aa };
  126. tr.test_eq(4., a(1, 1));
  127. tr.test_eq(99., a.p[0]);
  128. }
  129. {
  130. double aa[20];
  131. aa[19] = 77;
  132. ra::View<double> a = { {{10, 2}, {2, 1}}, aa };
  133. tr.test_eq(10, a.dim[0].size);
  134. tr.test_eq(2, a.dim[1].size);
  135. cout << "a.p(3, 4): " << a.p[19] << endl;
  136. tr.test_eq(77, a.p[19]);
  137. }
  138. {
  139. auto pp = std::unique_ptr<double []>(new double[10]);
  140. pp[9] = 77;
  141. double * p = pp.get();
  142. ra::Unique<double> a {};
  143. a.store = std::move(pp);
  144. a.p = p;
  145. a.dim = {{5, 2}, {2, 1}};
  146. tr.test_eq(5, a.dim[0].size);
  147. tr.test_eq(2, a.dim[1].size);
  148. cout << "a.p(3, 4): " << a.p[9] << endl;
  149. tr.test_eq(77, a.p[9]);
  150. }
  151. {
  152. auto pp = std::shared_ptr<double>(new double[10]);
  153. pp.get()[9] = 88;
  154. double * p = pp.get();
  155. ra::Shared<double> a {};
  156. a.store = pp;
  157. a.p = p;
  158. a.dim = {{5, 2}, {2, 1}};
  159. tr.test_eq(5, a.dim[0].size);
  160. tr.test_eq(2, a.dim[1].size);
  161. cout << "a.p(3, 4): " << a.p[9] << endl;
  162. tr.test_eq(88, a.p[9]);
  163. }
  164. {
  165. auto pp = std::vector<double>(10);
  166. pp[9] = 99;
  167. double * p = pp.data();
  168. ra::Big<double> a {};
  169. a.store = pp;
  170. a.p = p;
  171. a.dim = {{5, 2}, {2, 1}};
  172. tr.test_eq(5, a.dim[0].size);
  173. tr.test_eq(2, a.dim[1].size);
  174. cout << "a.p(3, 4): " << a.p[9] << endl;
  175. tr.test_eq(99, a.p[9]);
  176. }
  177. }
  178. tr.section("rank 0 -> scalar with Small");
  179. {
  180. auto rank0test0 = [](double & a) { a *= 2; };
  181. auto rank0test1 = [](double const & a) { return a*2; };
  182. ra::Small<double> a { 33 };
  183. static_assert(sizeof(a)==sizeof(double), "bad assumption");
  184. rank0test0(a);
  185. tr.test_eq(66, a);
  186. double b = rank0test1(a);
  187. tr.test_eq(66, a);
  188. tr.test_eq(132, b);
  189. }
  190. tr.section("(170) rank 0 -> scalar with View");
  191. {
  192. auto rank0test0 = [](double & a) { a *= 2; };
  193. auto rank0test1 = [](double const & a) { return a*2; };
  194. double x { 99 };
  195. ra::View<double, 0> a { {}, &x };
  196. tr.test_eq(1, a.size());
  197. // ra::View<T, 0> contains a pointer to T plus the dope vector of type Small<Dim, 0>. But after I put the data of Small in Small itself instead of in SmallBase, sizeof(Small<T, 0>) is no longer 0. That was specific of gcc, so better not to depend on it anyway...
  198. cout << "a()" << a() << endl;
  199. cout << "sizeof(a())" << sizeof(a()) << endl;
  200. cout << "sizeof(double *)" << sizeof(double *) << endl;
  201. // static_assert(sizeof(a())==sizeof(double *), "bad assumption");
  202. rank0test0(a);
  203. tr.test_eq(198, a);
  204. double b = rank0test1(a);
  205. tr.test_eq(198, a);
  206. tr.test_eq(396, b);
  207. }
  208. tr.section("ra traits");
  209. {
  210. {
  211. using double2x3 = ra::Small<double, 2, 3>;
  212. double2x3 r { 1, 2, 3, 4, 5, 6 };
  213. tr.test_eq(2, ra::ra_traits<double2x3>::rank(r));
  214. tr.test_eq(6, ra::ra_traits<double2x3>::size(r));
  215. }
  216. {
  217. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  218. ra::View<double> r { {{3, 2}, {2, 1}}, pool };
  219. tr.test_eq(2, ra::ra_traits<ra::View<double>>::rank(r));
  220. tr.test_eq(6, ra::ra_traits<ra::View<double>>::size(r));
  221. }
  222. {
  223. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  224. ra::View<double, 2> r {{ra::Dim {3, 2}, ra::Dim {2, 1}}, pool };
  225. tr.test_eq(2, ra::ra_traits<ra::View<double, 2>>::rank(r));
  226. tr.test_eq(6, ra::ra_traits<ra::View<double, 2>>::size(r));
  227. }
  228. }
  229. tr.section("iterator for View (I)");
  230. {
  231. double chk[6] = { 0, 0, 0, 0, 0, 0 };
  232. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  233. ra::View<double> r { {{3, 2}, {2, 1}}, pool };
  234. ra::ra_iterator<ra::View<double>> it(r.dim, r.p);
  235. cout << "as iterator: " << ra::print_iterator(it) << endl;
  236. tr.test(r.data()==it.c.p);
  237. std::copy(r.begin(), r.end(), chk);
  238. tr.test(std::equal(pool, pool+6, r.begin()));
  239. }
  240. tr.section("iterator for View (II)");
  241. {
  242. double chk[6] = { 0, 0, 0, 0, 0, 0 };
  243. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  244. ra::View<double, 1> r { { ra::Dim {6, 1}}, pool };
  245. ra::ra_iterator<ra::View<double, 1>> it(r.dim, r.p);
  246. cout << "View<double, 1> it.c.p: " << it.c.p << endl;
  247. std::copy(r.begin(), r.end(), chk);
  248. tr.test(std::equal(pool, pool+6, r.begin()));
  249. }
  250. // some of these tests are disabled depending on cell_iterator::operator=.
  251. tr.section("[ra11a] (skipped) ra_iterator operator= (from cell_iterator) does NOT copy contents");
  252. {
  253. double a[6] = { 0, 0, 0, 0, 0, 0 };
  254. double b[6] = { 1, 2, 3, 4, 5, 6 };
  255. ra::View<double> ra { {{3, 2}, {2, 1}}, a };
  256. ra::View<double> rb { {{3, 2}, {2, 1}}, b };
  257. auto aiter = ra.iter();
  258. {
  259. auto biter = rb.iter();
  260. aiter = biter;
  261. tr.skip().test_eq(0, ra);
  262. tr.skip().test_eq(rb, aiter);
  263. }
  264. {
  265. aiter = rb.iter();
  266. tr.skip().test_eq(0, ra);
  267. tr.skip().test_eq(rb, aiter);
  268. }
  269. }
  270. tr.section("[ra11b] ra_iterator operator= (from cell_iterator) DOES copy contents");
  271. {
  272. ra::Unique<double, 2> A({6, 7}, ra::_0 - ra::_1);
  273. ra::Unique<double, 2> AA({6, 7}, 0.);
  274. AA.iter<1>() = A.iter<1>();
  275. tr.test_eq(A, AA);
  276. }
  277. tr.section("[ra11c] STL-type iterators never copy contents");
  278. {
  279. double a[6] = { 0, 0, 0, 0, 0, 0 };
  280. double b[6] = { 1, 2, 3, 4, 5, 6 };
  281. ra::View<double> ra { {{3, 2}, {2, 1}}, a };
  282. ra::View<double> rb { {{3, 2}, {2, 1}}, b };
  283. auto aiter = ra.begin();
  284. {
  285. auto biter = rb.begin();
  286. aiter = biter;
  287. tr.test_eq(0, ra); // ra unchanged
  288. tr.test(std::equal(rb.begin(), rb.end(), aiter)); // aiter changed
  289. }
  290. {
  291. aiter = rb.begin();
  292. tr.test_eq(0, ra); // ra unchanged
  293. tr.test(std::equal(rb.begin(), rb.end(), aiter)); // aiter changed
  294. }
  295. }
  296. tr.section("shape of .iter()");
  297. {
  298. auto test = [&tr](auto && A)
  299. {
  300. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, ra::ra_traits<decltype(A)>::shape(A));
  301. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, A.iter().shape());
  302. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, iter<0>(A).shape());
  303. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, iter<-2>(A).shape());
  304. tr.test_eq(ra::Small<ra::dim_t, 1> {6}, iter<1>(A).shape());
  305. tr.test_eq(ra::Small<ra::dim_t, 1> {6}, iter<-1>(A).shape());
  306. tr.test_eq(ra::Small<ra::dim_t, 0> {}, iter<2>(A).shape());
  307. };
  308. test(ra::Unique<double, 2>({6, 7}, ra::_0 - ra::_1));
  309. test(ra::Unique<double>({6, 7}, ra::_0 - ra::_1));
  310. }
  311. tr.section("STL-type iterators");
  312. {
  313. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  314. ra::View<double, 1> r { {ra::Dim {6, 1}}, rpool };
  315. double spool[6] = { 0, 0, 0, 0, 0, 0 };
  316. ra::View<double> s { {{3, 1}, {2, 3}}, spool };
  317. std::copy(r.begin(), r.end(), s.begin());
  318. std::copy(spool, spool+6, std::ostream_iterator<double>(cout, " "));
  319. double cpool[6] = { 1, 3, 5, 2, 4, 6 };
  320. tr.test(std::equal(cpool, cpool+6, spool));
  321. cout << endl;
  322. }
  323. tr.section("storage types");
  324. {
  325. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  326. ra::Shared<double> s({3, 2}, pool, pool+6);
  327. tr.test_eq(2, s.rank());
  328. tr.test(std::equal(pool, pool+6, s.begin()));
  329. ra::Unique<double> u({3, 2}, pool, pool+6);
  330. tr.test_eq(2, u.rank());
  331. tr.test(std::equal(pool, pool+6, u.begin()));
  332. ra::Big<double> o({3, 2}, pool, pool+6);
  333. tr.test_eq(2, o.rank());
  334. tr.test(std::equal(pool, pool+6, o.begin()));
  335. }
  336. tr.section("driver selection");
  337. {
  338. static_assert(TI<0>::rank_s()==1, "bad TI rank");
  339. static_assert(ra::pick_driver<UU<0>, UU<1> >::value==1, "bad driver 1a");
  340. static_assert(ra::pick_driver<TI<1>, UU<2> >::value==1, "bad driver 1b");
  341. // these two depend on TI<w>::rank_s() being w+1, which I haven't settled on.
  342. static_assert(TI<1>::rank_s()==2, "bad TI rank");
  343. static_assert(ra::pick_driver<TI<0>, TI<1> >::value==1, "bad driver 1c");
  344. static_assert(UU<0>::size_s()==1, "bad size_s 0");
  345. static_assert(SS::size_s()==1, "bad size_s 1");
  346. static_assert(ra::pick_driver<UU<0>, SS>::value==0, "bad size_s 2");
  347. // static size/rank identical; prefer the first.
  348. static_assert(ra::largest_rank<UU<0>, SS>::value==0, "bad match 1a");
  349. static_assert(ra::largest_rank<SS, UU<0>>::value==0, "bad match 1b");
  350. // prefer the larger rank.
  351. static_assert(ra::largest_rank<SS, UU<1>>::value==1, "bad match 2a");
  352. static_assert(ra::largest_rank<UU<1>, SS>::value==0, "bad match 2b");
  353. // never choose TensorIndex.
  354. static_assert(ra::pick_driver<UU<2>, TI<0>>::value==0, "bad match 3a");
  355. static_assert(ra::pick_driver<TI<0>, UU<2>>::value==1, "bad match 3b");
  356. // static size/rank identical; prefer the first.
  357. static_assert(ra::pick_driver<UU<2>, UU<2>>::value==0, "bad match 4");
  358. static_assert(ra::largest_rank<UU<2>, TI<0>, UU<2>>::value==0, "bad match 5a");
  359. // dynamic rank counts as +inf.
  360. static_assert(ra::gt_rank(ra::RANK_ANY, 2), "bad match 6a");
  361. static_assert(ra::gt_rank(UU<ra::RANK_ANY>::rank_s(), UU<2>::rank_s()), "bad match 6b");
  362. static_assert(!ra::gt_rank(UU<2>::rank_s(), UU<ra::RANK_ANY>::rank_s()), "bad match 6c");
  363. static_assert(ra::pick_driver<UU<ra::RANK_ANY>, UU<2>>::value==0, "bad match 6d");
  364. static_assert(ra::pick_driver<UU<2>, UU<ra::RANK_ANY>>::value==1, "bad match 6e");
  365. static_assert(ra::pick_driver<UU<ra::RANK_ANY>, UU<ra::RANK_ANY>>::value==0, "bad match 6f");
  366. static_assert(ra::pick_driver<TI<0>, UU<ra::RANK_ANY>>::value==1, "bad match 6g");
  367. static_assert(ra::pick_driver<UU<ra::RANK_ANY>, TI<0>>::value==0, "bad match 6h");
  368. static_assert(ra::largest_rank<TI<0>, UU<ra::RANK_ANY>>::value==1, "bad match 6i");
  369. static_assert(ra::largest_rank<UU<ra::RANK_ANY>, TI<0>>::value==0, "bad match 6j");
  370. static_assert(ra::largest_rank<UU<2>, UU<ra::RANK_ANY>, TI<0>>::value==1, "bad match 6k");
  371. static_assert(ra::largest_rank<UU<1>, UU<2>, UU<3>>::value==2, "bad match 6l");
  372. static_assert(ra::largest_rank<UU<2>, TI<0>, UU<ra::RANK_ANY>>::value==2, "bad match 6m");
  373. // dynamic vs static size, both static rank
  374. static_assert(ra::pick_driver<UU<3>, SM3>::value==1, "static rank, dynamic vs static size");
  375. // dynamic rank vs static size & rank
  376. static_assert(ra::pick_driver<UU<ra::RANK_ANY>, SM1 >::value==0, "bad match 7a");
  377. static_assert(ra::pick_driver<SM1, UU<ra::RANK_ANY> >::value==1, "bad match 7b");
  378. static_assert(ra::pick_driver<UU<ra::RANK_ANY>, SM2 >::value==0, "bad match 7c");
  379. static_assert(ra::pick_driver<SM2, UU<ra::RANK_ANY> >::value==1, "bad match 7d");
  380. // more cases with +2 candidates.
  381. static_assert(ra::largest_rank<UU<3>, UU<1>, TI<0>>::value==0, "bad match 7b");
  382. static_assert(ra::largest_rank<TI<0>, UU<3>, UU<1>>::value==1, "bad match 7c");
  383. static_assert(ra::largest_rank<UU<1>, TI<0>, UU<3>>::value==2, "bad match 7d");
  384. static_assert(ra::largest_rank<UU<1>, TI<0>, UU<3>>::value==2, "bad match 7e");
  385. }
  386. tr.section("copy between arrays, construct from iterator pair");
  387. {
  388. // copy from Fortran order to C order.
  389. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  390. double check[6] = { 1, 4, 2, 5, 3, 6 };
  391. ra::View<double> r { {{3, 1}, {2, 3}}, rpool };
  392. std::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  393. tr.test(std::equal(check, check+6, r.begin()));
  394. ra::Unique<double> u({3, 2}, r.begin(), r.end());
  395. std::copy(u.begin(), u.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  396. tr.test(std::equal(check, check+6, u.begin()));
  397. // TODO Have strides in Small.
  398. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  399. std::copy(s.begin(), s.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  400. tr.test(std::equal(check, check+6, s.begin()));
  401. // construct Small from iterators.
  402. ra::Small<double, 3, 2> z(r.begin(), r.end());
  403. std::copy(z.begin(), z.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  404. tr.test(std::equal(check, check+6, z.begin()));
  405. }
  406. // In this case, the View + shape provides the driver.
  407. tr.section("construct View from shape + driverless xpr");
  408. {
  409. static_assert(ra::has_tensorindex<decltype(ra::_0)>, "bad has_tensorindex test 0");
  410. static_assert(ra::has_tensorindex<TI<0>>, "bad has_tensorindex test 1");
  411. ra::Unique<int, 2> a({3, 2}, ra::unspecified);
  412. auto dyn = ra::expr([](int & a, int b) { a = b; }, a.iter(), ra::_0);
  413. static_assert(ra::has_tensorindex<decltype(dyn)>, "bad has_tensorindex test 2");
  414. auto dyn2 = ra::expr([](int & dest, int const & src) { dest = src; }, a.iter(), ra::_0);
  415. static_assert(ra::has_tensorindex<decltype(dyn2)>, "bad has_tensorindex test 3");
  416. {
  417. int checkb[6] = { 0, 0, 1, 1, 2, 2 };
  418. ra::Unique<int, 2> b({3, 2}, ra::_0);
  419. tr.test(std::equal(checkb, checkb+6, b.begin()));
  420. }
  421. // This requires the driverless xpr dyn(scalar, tensorindex) to be constructible.
  422. {
  423. int checkb[6] = { 3, 3, 4, 4, 5, 5 };
  424. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a+b; }, ra::scalar(3), ra::_0));
  425. tr.test(std::equal(checkb, checkb+6, b.begin()));
  426. }
  427. {
  428. int checkb[6] = { 0, -1, 1, 0, 2, 1 };
  429. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::_0, ra::_1));
  430. tr.test(std::equal(checkb, checkb+6, b.begin()));
  431. }
  432. // TODO Check this is an error (chosen driver is TensorIndex<2>, that can't drive).
  433. // {
  434. // ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::_2, ra::_1));
  435. // cout << b << endl;
  436. // }
  437. // TODO Could this be made to bomb at compile time?
  438. // {
  439. // ra::Unique<int> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::_2, ra::_1));
  440. // cout << b << endl;
  441. // }
  442. }
  443. tr.section("construct View from shape + xpr");
  444. {
  445. double checka[6] = { 9, 9, 9, 9, 9, 9 };
  446. ra::Unique<double, 2> a({3, 2}, ra::scalar(9));
  447. tr.test(std::equal(checka, checka+6, a.begin()));
  448. double checkb[6] = { 11, 11, 22, 22, 33, 33 };
  449. ra::Unique<double, 2> b({3, 2}, ra::Small<double, 3> { 11, 22, 33 });
  450. tr.test(std::equal(checkb, checkb+6, b.begin()));
  451. }
  452. tr.section("construct Unique from Unique");
  453. {
  454. double check[6] = { 2, 3, 1, 4, 8, 9 };
  455. ra::Unique<double, 2> a({3, 2}, { 2, 3, 1, 4, 8, 9 });
  456. // ra::Unique<double, 2> b(a); // error; need temp
  457. ra::Unique<double, 2> c(ra::Unique<double, 2>({3, 2}, { 2, 3, 1, 4, 8, 9 })); // ok; from actual temp
  458. tr.test(std::equal(check, check+6, c.begin()));
  459. ra::Unique<double, 2> d(std::move(a)); // ok; from fake temp
  460. tr.test(std::equal(check, check+6, d.begin()));
  461. }
  462. tr.section("construct from xpr having its own shape");
  463. {
  464. ra::Unique<double, 0> a(ra::scalar(33));
  465. ra::Unique<double> b(ra::scalar(44));
  466. cout << "a: " << a << endl;
  467. cout << "b: " << b << endl;
  468. // b.rank() is runtime, so b()==44. and the whole assert argument become array xprs when operators.H is included.
  469. tr.test_eq(0, b.rank());
  470. tr.test_eq(1, b.size());
  471. tr.test_eq(44, b());
  472. b = 55.;
  473. cout << "b: " << b << endl;
  474. // see above for b.rank().
  475. tr.test_eq(0, b.rank());
  476. tr.test_eq(1, b.size());
  477. tr.test_eq(55., b());
  478. }
  479. tr.section("rank 0 -> scalar with storage type");
  480. {
  481. auto rank0test0 = [](double & a) { a *= 2; };
  482. auto rank0test1 = [](double const & a) { return a*2; };
  483. ra::Unique<double, 0> a(ra::scalar(33));
  484. tr.test_eq(1, a.size());
  485. // See note in (170).
  486. // static_assert(sizeof(a())==sizeof(double *), "bad assumption");
  487. rank0test0(a);
  488. tr.test_eq(66, a);
  489. double b = rank0test1(a);
  490. tr.test_eq(66, a);
  491. tr.test_eq(132, b);
  492. }
  493. tr.section("rank 0 -> scalar with storage type, explicit size");
  494. {
  495. auto rank0test0 = [](double & a) { a *= 2; };
  496. auto rank0test1 = [](double const & a) { return a*2; };
  497. ra::Unique<double, 0> a({}, ra::scalar(33));
  498. tr.test_eq(1, a.size());
  499. // See note in (170).
  500. // static_assert(sizeof(a())==sizeof(double *), "bad assumption");
  501. rank0test0(a);
  502. tr.test_eq(66, a);
  503. double b = rank0test1(a);
  504. tr.test_eq(66, a);
  505. tr.test_eq(132, b);
  506. }
  507. tr.section("constructors from data in initializer_list");
  508. {
  509. double checka[6] = { 2, 3, 1, 4, 8, 9 };
  510. {
  511. ra::Unique<double, 2> a({2, 3}, { 2, 3, 1, 4, 8, 9 });
  512. tr.test_eq(2, a.dim[0].size);
  513. tr.test_eq(3, a.dim[1].size);
  514. tr.test(std::equal(a.begin(), a.end(), checka));
  515. }
  516. {
  517. ra::Unique<double> a { 2, 3, 1, 4, 8, 9 };
  518. tr.test_eq(6, a.size());
  519. tr.test_eq(1, a.rank());
  520. tr.test(std::equal(a.begin(), a.end(), checka));
  521. ra::Unique<double> b ({ 2, 3, 1, 4, 8, 9 });
  522. tr.test_eq(6, b.size());
  523. tr.test_eq(1, b.rank());
  524. tr.test(std::equal(b.begin(), b.end(), checka));
  525. }
  526. {
  527. ra::Unique<double, 1> a { 2, 3, 1, 4, 8, 9 };
  528. tr.test_eq(6, a.size());
  529. tr.test_eq(1, a.rank());
  530. tr.test(std::equal(a.begin(), a.end(), checka));
  531. ra::Unique<double, 1> b ({ 2, 3, 1, 4, 8, 9 });
  532. tr.test_eq(6, b.size());
  533. tr.test_eq(1, b.rank());
  534. tr.test(std::equal(b.begin(), b.end(), checka));
  535. }
  536. }
  537. tr.section("transpose of 0 rank");
  538. {
  539. {
  540. ra::Unique<double, 0> a({}, 99);
  541. auto b = transpose(ra::Small<int, 0> {}, a);
  542. tr.test_eq(0, b.rank());
  543. tr.test_eq(99, b());
  544. }
  545. {
  546. ra::Unique<double, 0> a({}, 99);
  547. auto b = transpose<>(a);
  548. tr.test_eq(0, b.rank());
  549. tr.test_eq(99, b());
  550. }
  551. }
  552. tr.section("row-major assignment from initializer_list, rank 2");
  553. {
  554. ra::Unique<double, 2> a({3, 2}, ra::unspecified);
  555. a = { 2, 3, 1, 4, 8, 9 };
  556. tr.test_eq(2, a(0, 0));
  557. tr.test_eq(3, a(0, 1));
  558. tr.test_eq(1, a(1, 0));
  559. tr.test_eq(4, a(1, 1));
  560. tr.test_eq(8, a(2, 0));
  561. tr.test_eq(9, a(2, 1));
  562. auto b = transpose({1, 0}, a);
  563. b = { 2, 3, 1, 4, 8, 9 };
  564. tr.test_eq(2, b(0, 0));
  565. tr.test_eq(3, b(0, 1));
  566. tr.test_eq(1, b(0, 2));
  567. tr.test_eq(4, b(1, 0));
  568. tr.test_eq(8, b(1, 1));
  569. tr.test_eq(9, b(1, 2));
  570. tr.test_eq(2, a(0, 0));
  571. tr.test_eq(4, a(0, 1));
  572. tr.test_eq(3, a(1, 0));
  573. tr.test_eq(8, a(1, 1));
  574. tr.test_eq(1, a(2, 0));
  575. tr.test_eq(9, a(2, 1));
  576. auto c = transpose({1, 0}, a);
  577. tr.test(a.data()==c.data()); // pointers are not ra::scalars. Dunno if this deserves fixing.
  578. tr.test_eq(a.size(0), c.size(1));
  579. tr.test_eq(a.size(1), c.size(0));
  580. tr.test_eq(b, c);
  581. }
  582. tr.section("row-major assignment from initializer_list, rank 1");
  583. {
  584. ra::Big<double, 1> a({5}, ra::unspecified);
  585. a = { 2, 3, 1, 4, 8 };
  586. tr.test_eq(2, a(0));
  587. tr.test_eq(3, a(1));
  588. tr.test_eq(1, a(2));
  589. tr.test_eq(4, a(3));
  590. tr.test_eq(8, a(4));
  591. }
  592. tr.section("subscripts");
  593. {
  594. tr.section("View fixed rank == 0");
  595. {
  596. double x = 99;
  597. ra::View<double, 0> y(ra::Small<int, 0>{}, &x);
  598. tr.test_eq(99, y());
  599. tr.test_eq(99, y);
  600. double u = 77.;
  601. ra::View<double, 0> v(ra::Small<int, 0>{}, &u);
  602. y = v;
  603. tr.test_eq(77, u);
  604. tr.test_eq(77, v);
  605. tr.test_eq(77, x);
  606. tr.test_eq(77, y);
  607. }
  608. tr.section("View fixed rank > 0");
  609. {
  610. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  611. ra::View<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  612. cout << "org" << endl;
  613. std::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  614. {
  615. double rcheck[6] = { 1, 4, 2, 5, 3, 6 };
  616. auto r0 = r();
  617. tr.test(std::equal(r0.begin(), r0.end(), rcheck));
  618. ra::Small<int, 0> i0 {};
  619. tr.info("ra::Small<int, 0> rank").test_eq(1, i0.rank());
  620. auto r0a = r.at(ra::Small<int, 0> {});
  621. tr.info("fix size").test(std::equal(r0a.begin(), r0a.end(), rcheck));
  622. auto r0b = r.at(ra::Big<int, 1> {});
  623. tr.info("fix rank").test(std::equal(r0b.begin(), r0b.end(), rcheck));
  624. auto r0c = r.at(0+ra::Big<int, 1> {});
  625. tr.info("fix rank expr").test(std::equal(r0c.begin(), r0c.end(), rcheck));
  626. // TODO check out why ra::Big<int> {} is rank 0.
  627. auto r0d = r.at(0+ra::Big<int>({0}, {}));
  628. tr.info("r0d: [", r0d, "]").test(std::equal(r0d.begin(), r0d.end(), rcheck));
  629. }
  630. {
  631. double rcheck[2] = { 2, 5 };
  632. auto r1 = r(1);
  633. tr.test_eq(ra::ptr(rcheck), r1);
  634. auto r1a = r.at(ra::Small<int, 1> {1});
  635. tr.test_eq(ra::ptr(rcheck), r1a);
  636. auto r1b = r.at(ra::Big<int, 1> {1});
  637. tr.test_eq(ra::ptr(rcheck), r1b);
  638. auto r1c = r.at(0+ra::Big<int, 1> {1});
  639. tr.test_eq(ra::ptr(rcheck), r1c);
  640. auto r1d = r.at(0+ra::Big<int> {1});
  641. tr.test_eq(ra::ptr(rcheck), r1d);
  642. }
  643. {
  644. double rcheck[2] = { 5 };
  645. // Does r(1, 1) return rank 0, or a scalar directly?
  646. // std::copy(r2.begin(), r2.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  647. // tr.test(std::equal(r2.begin(), r2.end(), rcheck));
  648. auto r2 = r(1, 1);
  649. tr.test_eq(5, r2);
  650. auto r2a = r.at(ra::Small<int, 2> {1, 1});
  651. tr.test(std::equal(r2a.begin(), r2a.end(), rcheck));
  652. auto r2b = r.at(ra::Big<int, 1> {1, 1});
  653. tr.test(std::equal(r2a.begin(), r2a.end(), rcheck));
  654. auto r2c = r.at(0+ra::Big<int, 1> {1, 1});
  655. tr.test(std::equal(r2c.begin(), r2c.end(), rcheck));
  656. auto r2d = r.at(0+ra::Big<int> {1, 1});
  657. tr.test(std::equal(r2d.begin(), r2d.end(), rcheck));
  658. }
  659. }
  660. // TODO Subscript a rank>1 array, multiple selectors, mixed beatable & unbeatable selectors.
  661. tr.section("View fixed rank, unbeatable subscripts");
  662. {
  663. ra::Unique<double, 1> a = {1, 2, 3, 4};
  664. ra::Unique<int, 1> i = {3, 1, 2};
  665. cout << a(i) << endl;
  666. ra::Unique<double, 1> ai = a(i);
  667. tr.test_eq(i.size(), ai.size());
  668. tr.test_eq(a[i[0]], ai[0]);
  669. tr.test_eq(a[i[1]], ai[1]);
  670. tr.test_eq(a[i[2]], ai[2]);
  671. a(i) = ra::Unique<double, 1> {7, 8, 9};
  672. cout << a << endl;
  673. tr.test_eq(4, a.size());
  674. tr.test_eq(1, a[0]);
  675. tr.test_eq(a[i[0]], 7);
  676. tr.test_eq(a[i[1]], 8);
  677. tr.test_eq(a[i[2]], 9);
  678. }
  679. tr.section("View var rank");
  680. {
  681. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  682. ra::View<double> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  683. tr.test_eq(2, r.rank());
  684. cout << "org" << endl;
  685. std::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  686. double rcheck0[6] = { 1, 4, 2, 5, 3, 6 };
  687. auto r0 = r();
  688. auto r0a = r.at(ra::Small<int, 0> {});
  689. tr.test_eq(2, r0a.rank());
  690. tr.test_eq(2, r0.rank());
  691. cout << "r0" << endl;
  692. std::copy(r0.begin(), r0.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  693. tr.test(std::equal(r0.begin(), r0.end(), rcheck0));
  694. tr.test(std::equal(r0a.begin(), r0a.end(), rcheck0));
  695. double rcheck1[2] = { 2, 5 };
  696. auto r1 = r(1);
  697. auto r1a = r.at(ra::Small<int, 1> {1});
  698. tr.test_eq(1, r1a.rank());
  699. tr.test_eq(1, r1.rank());
  700. cout << "r1" << endl;
  701. std::copy(r1.begin(), r1.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  702. tr.test(std::equal(r1.begin(), r1.end(), rcheck1));
  703. tr.test(std::equal(r1a.begin(), r1a.end(), rcheck1));
  704. double rcheck2[2] = { 5 };
  705. auto r2 = r(1, 1);
  706. auto r2a = r.at(ra::Small<int, 2> {1, 1});
  707. tr.test_eq(0, r2a.rank());
  708. cout << "r2" << endl;
  709. std::copy(r2.begin(), r2.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  710. tr.test(std::equal(r2.begin(), r2.end(), rcheck2));
  711. tr.test(std::equal(r2a.begin(), r2a.end(), rcheck2));
  712. }
  713. // TODO Make sure that this is double & = 99, etc. and not View<double, 0> = 99, etc.
  714. tr.section("assign to rank-0 result of subscript");
  715. {
  716. double check[6] = {99, 88, 77, 66, 55, 44};
  717. ra::Unique<double> a({2, 3}, 11.);
  718. a(0, 0) = 99; a(0, 1) = 88; a(0, 2) = 77;
  719. a(1, 0) = 66; a(1, 1) = 55; a(1, 2) = 44;
  720. std::copy(a.begin(), a.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  721. tr.test(std::equal(check, check+6, a.begin()));
  722. }
  723. }
  724. tr.section("construct from shape");
  725. {
  726. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::unspecified);
  727. std::iota(a.begin(), a.end(), 0);
  728. auto sa = ra::ra_traits<ra::Unique<double>>::shape(a);
  729. tr.test_eq(3, sa[0]);
  730. tr.test_eq(2, sa[1]);
  731. tr.test_eq(4, sa[2]);
  732. double check[24];
  733. std::iota(check, check+24, 0);
  734. tr.test(std::equal(check, check+24, a.begin()));
  735. }
  736. tr.section("Var rank View from fixed rank View");
  737. {
  738. ra::Unique<double, 3> a({3, 2, 4}, ra::unspecified);
  739. ra::View<double> b(a);
  740. tr.test(a.data()==b.data()); // pointers are not ra::scalars. Dunno if this deserves fixing.
  741. tr.test_eq(a.rank(), b.rank());
  742. tr.test_eq(a.size(0), b.size(0));
  743. tr.test_eq(a.size(1), b.size(1));
  744. tr.test_eq(a.size(2), b.size(2));
  745. tr.test(every(a==b));
  746. }
  747. tr.section("I/O");
  748. {
  749. tr.section("1");
  750. {
  751. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  752. double check[6] = { 1, 4, 2, 5, 3, 6 };
  753. CheckArrayIO(tr, s, check);
  754. }
  755. tr.section("2");
  756. {
  757. ra::Small<double, 3> s { 1, 4, 2 };
  758. double check[3] = { 1, 4, 2 };
  759. CheckArrayIO(tr, s, check);
  760. }
  761. tr.section("3");
  762. {
  763. ra::Small<double> s { 77 };
  764. double check[1] = { 77 };
  765. CheckArrayIO(tr, s, check);
  766. }
  767. tr.section("4. View<> can't allocate, so have no istream >>. Check output only.");
  768. {
  769. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  770. ra::View<double, 3> r { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  771. double check[11] = { 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  772. CheckArrayOutput(tr, r, check);
  773. }
  774. tr.section("5");
  775. {
  776. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  777. ra::View<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  778. double check[8] = { 3, 2, 1, 4, 2, 5, 3, 6 };
  779. CheckArrayOutput(tr, r, check);
  780. }
  781. tr.section("6");
  782. {
  783. double rpool[3] = { 1, 2, 3 };
  784. ra::View<double, 1> r { {ra::Dim {3, 1}}, rpool };
  785. double check[4] = { 3, 1, 2, 3 };
  786. CheckArrayOutput(tr, r, check);
  787. }
  788. tr.section("7");
  789. {
  790. double rpool[1] = { 88 };
  791. ra::View<double, 0> r { {}, rpool };
  792. double check[1] = { 88 };
  793. CheckArrayOutput(tr, r, check);
  794. tr.test_eq(1, r.size());
  795. // See note in (170).
  796. // static_assert(sizeof(r)==sizeof(double *), "bad assumption");
  797. tr.test_eq(88, r);
  798. }
  799. tr.section("8");
  800. {
  801. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  802. ra::View<double> a { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  803. double check[12] = { 3, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  804. CheckArrayOutput(tr, a, check);
  805. // default strides.
  806. ra::View<double> b { {2, 2, 2}, rpool };
  807. CheckArrayOutput(tr, b, check);
  808. }
  809. tr.section("9");
  810. {
  811. ra::Unique<double, 3> a(std::vector<ra::dim_t> {3, 2, 4}, ra::unspecified);
  812. std::iota(a.begin(), a.end(), 0);
  813. double check[3+24] = { 3, 2, 4 };
  814. std::iota(check+3, check+3+24, 0);
  815. CheckArrayIO(tr, a, check);
  816. }
  817. tr.section("10");
  818. {
  819. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::unspecified);
  820. std::iota(a.begin(), a.end(), 0);
  821. double check[4+24] = { 3, 3, 2, 4 };
  822. std::iota(check+4, check+4+24, 0);
  823. CheckArrayIO(tr, a, check);
  824. }
  825. }
  826. tr.section("ply - xpr types - Scalar");
  827. {
  828. {
  829. auto s = ra::scalar(7);
  830. cout << "s: " << s.c << endl;
  831. }
  832. {
  833. auto s = ra::scalar(ra::Small<int, 2> {11, 12});
  834. cout << "s: " << s.c << endl;
  835. }
  836. {
  837. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::unspecified);
  838. std::iota(a.begin(), a.end(), 0);
  839. auto s = ra::scalar(a);
  840. cout << "s: " << s.c << endl;
  841. }
  842. }
  843. tr.section("scalar as reference");
  844. {
  845. int a = 3;
  846. ra::scalar(a) += ra::Small<int, 3> {4, 5, 6};
  847. tr.test_eq(18, a);
  848. // beware: throws away 3+4,3+5, only 3+6 is left. [ma107]
  849. ra::scalar(a) = 3 + ra::Small<int, 3> {4, 5, 6};
  850. tr.test_eq(9, a);
  851. }
  852. tr.section("ra::iota");
  853. {
  854. static_assert(ra::is_iterator<decltype(ra::iota(10))>, "bad type pred for iota");
  855. tr.section("straight cases");
  856. {
  857. ra::Big<int, 1> a = ra::iota(4, 1);
  858. assert(a[0]==1 && a[1]==2 && a[2]==3 && a[3]==4);
  859. }
  860. tr.section("work with operators");
  861. {
  862. tr.test(every(ra::iota(4)==ra::Big<int, 1> {0, 1, 2, 3}));
  863. tr.test(every(ra::iota(4, 1)==ra::Big<int, 1> {1, 2, 3, 4}));
  864. tr.test(every(ra::iota(4, 1, 2)==ra::Big<int, 1> {1, 3, 5, 7}));
  865. }
  866. // TODO actually whether unroll is avoided depends on ply(), have a way to require it.
  867. // Cf [trc-01] in test-compatibility.C.
  868. tr.section("[tr0-01] frame-matching, forbidding unroll");
  869. {
  870. ra::Big<int, 3> b ({3, 4, 2}, ra::unspecified);
  871. transpose({0, 2, 1}, b) = ra::iota(3, 1);
  872. cout << b << endl;
  873. tr.test(every(b(0)==1));
  874. tr.test(every(b(1)==2));
  875. tr.test(every(b(2)==3));
  876. }
  877. {
  878. ra::Big<int, 3> b ({3, 4, 2}, ra::unspecified);
  879. transpose<0, 2, 1>(b) = ra::iota(3, 1);
  880. cout << b << endl;
  881. tr.test(every(b(0)==1));
  882. tr.test(every(b(1)==2));
  883. tr.test(every(b(2)==3));
  884. }
  885. }
  886. tr.section("reverse array types");
  887. {
  888. CheckReverse(tr, ra::Unique<double>({ 3, 2, 4 }, ra::unspecified));
  889. CheckReverse(tr, ra::Unique<double, 3>({ 3, 2, 4 }, ra::unspecified));
  890. }
  891. tr.section("transpose A");
  892. {
  893. CheckTranspose1(tr, ra::Unique<double>({ 3, 2 }, ra::unspecified));
  894. CheckTranspose1(tr, ra::Unique<double, 2>({ 3, 2 }, ra::unspecified));
  895. }
  896. tr.section("transpose B");
  897. {
  898. auto transpose_test = [&tr](auto && b)
  899. {
  900. tr.test_eq(1, b.rank());
  901. tr.test_eq(2, b.size());
  902. tr.test_eq(1, b[0]);
  903. tr.test_eq(4, b[1]);
  904. };
  905. ra::Unique<double> a({3, 2}, ra::_0*2 + ra::_1 + 1);
  906. cout << "A: " << a << endl;
  907. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, a)); // dyn rank to dyn rank
  908. transpose_test(transpose<0, 0>(a)); // dyn rank to static rank
  909. ra::Unique<double, 2> b({3, 2}, ra::_0*2 + ra::_1*1 + 1);
  910. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, b)); // static rank to dyn rank
  911. transpose_test(transpose<0, 0>(b)); // static rank to static rank
  912. }
  913. tr.section("transpose C");
  914. {
  915. auto transpose_test = [&tr](auto && b)
  916. {
  917. tr.test_eq(1, b.rank());
  918. tr.test_eq(2, b.size());
  919. tr.test_eq(1, b[0]);
  920. tr.test_eq(5, b[1]);
  921. };
  922. ra::Unique<double> a({2, 3}, ra::_0*3 + ra::_1 + 1);
  923. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, a)); // dyn rank to dyn rank
  924. transpose_test(transpose<0, 0>(a)); // dyn rank to static rank
  925. ra::Unique<double, 2> b({2, 3}, ra::_0*3 + ra::_1 + 1);
  926. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, b)); // static rank to dyn rank
  927. transpose_test(transpose<0, 0>(b)); // static rank to static rank
  928. }
  929. return tr.summary();
  930. }