ra-0.C 36 KB

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