ra-0.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - Arrays, iterators.
  3. // (c) Daniel Llorens - 2013-2015
  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 <numeric>
  9. #include <iostream>
  10. #include <iterator>
  11. #include "ra/test.hh"
  12. #include "mpdebug.hh"
  13. using std::cout, std::endl, std::flush, ra::TestRecorder;
  14. template <class A>
  15. void CheckArrayOutput(TestRecorder & tr, A const & a, double * begin)
  16. {
  17. std::ostringstream o;
  18. o << a;
  19. cout << "a: " << o.str() << endl;
  20. std::istringstream i(o.str());
  21. std::istream_iterator<double> iend;
  22. std::istream_iterator<double> ibegin(i);
  23. tr.test(std::equal(ibegin, iend, begin));
  24. }
  25. template <class A>
  26. void CheckArrayIO(TestRecorder & tr, A const & a, double * begin)
  27. {
  28. std::ostringstream o;
  29. o << a;
  30. {
  31. std::istringstream i(o.str());
  32. std::istream_iterator<double> iend;
  33. std::istream_iterator<double> ibegin(i);
  34. tr.info("reading back from '", o.str(), "'").test(std::equal(ibegin, iend, begin));
  35. }
  36. {
  37. std::istringstream i(o.str());
  38. A b;
  39. tr.test(bool(i));
  40. i >> b;
  41. auto as = ra::shape(a);
  42. auto bs = ra::shape(b);
  43. tr.info("shape from '", o.str(), "'").test(std::equal(as.begin(), as.end(), bs.begin()));
  44. tr.info("content").test(std::equal(a.begin(), a.begin(), b.begin()));
  45. }
  46. }
  47. int main()
  48. {
  49. TestRecorder tr(std::cout);
  50. tr.section("expr len_s doesn't depend on operand order");
  51. {
  52. ra::Small<int, 4> a = ra::_0;
  53. ra::Big<int, 1> b({4}, ra::_0);
  54. tr.test_eq(4, (a+b).len_s(0));
  55. tr.test_eq(4, (b+a).len_s(0));
  56. }
  57. tr.section("internal fields");
  58. {
  59. {
  60. double aa[10];
  61. aa[0] = 99;
  62. ra::ViewBig<double, 1> a { {{10, 1}}, aa }; // [ra36]
  63. tr.test_eq(99., a.data()[0]);
  64. }
  65. {
  66. double aa[6] = { 1, 2, 3, 4, 5, 6 };
  67. aa[0] = 99;
  68. ra::ViewBig<double, 2> a { { {3, 2}, {2, 1}}, aa };
  69. tr.test_eq(4., a(1, 1));
  70. tr.test_eq(99., a.data()[0]);
  71. }
  72. {
  73. double aa[20];
  74. aa[19] = 77;
  75. ra::ViewBig<double> a = { {{10, 2}, {2, 1}}, aa };
  76. tr.test_eq(10, a.dimv[0].len);
  77. tr.test_eq(2, a.dimv[1].len);
  78. cout << "a.data()(3, 4): " << a.data()[19] << endl;
  79. tr.test_eq(77, a.data()[19]);
  80. }
  81. {
  82. auto pp = std::unique_ptr<double []>(new double[10]);
  83. pp[9] = 77;
  84. double * p = pp.get();
  85. ra::Unique<double> a {};
  86. a.store = std::move(pp);
  87. a.cp = p;
  88. a.dimv = {{5, 2}, {2, 1}};
  89. tr.test_eq(5, a.dimv[0].len);
  90. tr.test_eq(2, a.dimv[1].len);
  91. cout << "a.data()(3, 4): " << a.data()[9] << endl;
  92. tr.test_eq(77, a.data()[9]);
  93. }
  94. {
  95. auto pp = std::shared_ptr<double>(new double[10], std::default_delete<double[]>());
  96. pp.get()[9] = 88;
  97. double * p = pp.get();
  98. ra::Shared<double> a {};
  99. a.store = pp;
  100. a.cp = p;
  101. a.dimv = {{5, 2}, {2, 1}};
  102. tr.test_eq(5, a.dimv[0].len);
  103. tr.test_eq(2, a.dimv[1].len);
  104. cout << "a.data()(3, 4): " << a.data()[9] << endl;
  105. tr.test_eq(88, a.data()[9]);
  106. }
  107. {
  108. decltype(std::declval<ra::Big<double>>().store) pp(10);
  109. pp[9] = 99;
  110. double * p = pp.data();
  111. ra::Big<double> a {};
  112. a.store = pp;
  113. a.cp = p;
  114. a.dimv = {{5, 2}, {2, 1}};
  115. tr.test_eq(5, a.dimv[0].len);
  116. tr.test_eq(2, a.dimv[1].len);
  117. cout << "a.data()(3, 4): " << a.data()[9] << endl;
  118. tr.test_eq(99, a.data()[9]);
  119. }
  120. }
  121. tr.section("rank 0 -> scalar with Small");
  122. {
  123. auto rank0test0 = [](double & a) { a *= 2; };
  124. auto rank0test1 = [](double const & a) { return a*2; };
  125. ra::Small<double> a { 33 };
  126. static_assert(sizeof(a)==sizeof(double), "bad assumption");
  127. rank0test0(a);
  128. tr.test_eq(66, a);
  129. double b = rank0test1(a);
  130. tr.test_eq(66, a);
  131. tr.test_eq(132, b);
  132. }
  133. tr.section("[170] rank 0 -> scalar with View");
  134. {
  135. auto rank0test0 = [](double & a) { a *= 2; };
  136. auto rank0test1 = [](double const & a) { return a*2; };
  137. double x { 99 };
  138. ra::ViewBig<double, 0> a { {}, &x };
  139. tr.test_eq(1, a.size());
  140. // ra::ViewBig<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...
  141. cout << "a()" << a() << endl;
  142. cout << "sizeof(a())" << sizeof(a()) << endl;
  143. cout << "sizeof(double *)" << sizeof(double *) << endl;
  144. // static_assert(sizeof(a())==sizeof(double *), "bad assumption");
  145. rank0test0(a);
  146. tr.test_eq(198, a);
  147. double b = rank0test1(a);
  148. tr.test_eq(198, a);
  149. tr.test_eq(396, b);
  150. }
  151. tr.section("rank 0 and rank 1 constructors with ANY");
  152. {
  153. ra::Big<int> x {9};
  154. tr.test_eq(9, x(0));
  155. tr.test_eq(1, x.size());
  156. tr.test_eq(1, x.len(0));
  157. tr.test_eq(1, x.rank());
  158. ra::Big<int> y = 9;
  159. tr.test_eq(9, y());
  160. tr.test_eq(1, y.size());
  161. tr.test_eq(0, y.rank());
  162. // // FIXME ra::Big<int> x {} is WHO NOSE territory, but should probably be rank 1, size 0
  163. // ra::Big<int> z {};
  164. // tr.test_eq(0, z.size());
  165. // tr.test_eq(1, z.rank());
  166. }
  167. tr.section("generic container functions");
  168. {
  169. {
  170. using double2x3 = ra::Small<double, 2, 3>;
  171. double2x3 r { 1, 2, 3, 4, 5, 6 };
  172. tr.test_eq(2, rank(r));
  173. // Not sure why Koenig doesn't work here, might be library defect [ra10].
  174. tr.test_eq(6, ra::size(r));
  175. }
  176. {
  177. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  178. ra::ViewBig<double> r { {{3, 2}, {2, 1}}, pool };
  179. tr.test_eq(2, rank(r));
  180. tr.test_eq(6, size(r));
  181. }
  182. {
  183. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  184. ra::ViewBig<double, 2> r {{ra::Dim {3, 2}, ra::Dim {2, 1}}, pool };
  185. tr.test_eq(2, rank(r));
  186. tr.test_eq(6, size(r));
  187. }
  188. }
  189. tr.section("iterator for View (I)");
  190. {
  191. double chk[6] = { 0, 0, 0, 0, 0, 0 };
  192. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  193. ra::ViewBig<double> r { {{3, 2}, {2, 1}}, pool };
  194. auto it = r.iter();
  195. tr.test_seq(r.data(), it.c.data());
  196. std::ranges::copy(r.begin(), r.end(), chk);
  197. tr.test(std::ranges::equal(pool, pool+6, r.begin(), r.end()));
  198. }
  199. tr.section("iterator for View (II)");
  200. {
  201. double chk[6] = { 0, 0, 0, 0, 0, 0 };
  202. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  203. ra::ViewBig<double, 1> r { { ra::Dim {6, 1}}, pool };
  204. auto it = r.iter();
  205. tr.test_seq(r.data(), it.c.data());
  206. std::ranges::copy(r.begin(), r.end(), chk);
  207. tr.test(std::ranges::equal(pool, pool+6, r.begin(), r.end()));
  208. }
  209. // some of these tests are disabled depending on CellBig::operator=.
  210. tr.section("[ra11a] (skipped) CellBig operator= (from CellBig) does NOT copy contents");
  211. {
  212. double a[6] = { 0, 0, 0, 0, 0, 0 };
  213. double b[6] = { 1, 2, 3, 4, 5, 6 };
  214. ra::ViewBig<double> ra { {{3, 2}, {2, 1}}, a };
  215. ra::ViewBig<double> rb { {{3, 2}, {2, 1}}, b };
  216. auto aiter = ra.iter();
  217. {
  218. auto biter = rb.iter();
  219. aiter = biter;
  220. tr.skip().test_eq(0, ra);
  221. tr.skip().test_eq(rb, aiter);
  222. }
  223. {
  224. aiter = rb.iter();
  225. tr.skip().test_eq(0, ra);
  226. tr.skip().test_eq(rb, aiter);
  227. }
  228. }
  229. tr.section("[ra11b] CellBig operator= (from CellBig) DOES copy contents");
  230. {
  231. ra::Unique<double, 2> A({6, 7}, ra::_0 - ra::_1);
  232. ra::Unique<double, 2> AA({6, 7}, 0.);
  233. AA.iter<1>() = A.iter<1>();
  234. tr.test_eq(ra::_0 - ra::_1, AA);
  235. tr.test_eq(A, AA);
  236. }
  237. tr.section("[ra11b] CellBig operator= (from CellBig) DOES copy contents");
  238. {
  239. ra::Small<double, 6, 7> A = ra::_0 - ra::_1;
  240. ra::Small<double, 6, 7> AA = 0.;
  241. AA.iter<1>() = A.iter<1>();
  242. tr.test_eq(ra::_0 - ra::_1, AA);
  243. tr.test_eq(A, AA);
  244. }
  245. // FIXME re-enable if STL-type iterators become copyable again.
  246. // tr.section("[ra11c] STL-type iterators never copy contents");
  247. // {
  248. // double a[6] = { 0, 0, 0, 0, 0, 0 };
  249. // double b[6] = { 1, 2, 3, 4, 5, 6 };
  250. // ra::ViewBig<double> ra { {{3, 2}, {2, 1}}, a };
  251. // ra::ViewBig<double> rb { {{3, 2}, {2, 1}}, b };
  252. // auto aiter = ra.begin();
  253. // {
  254. // auto biter = rb.begin();
  255. // aiter = biter;
  256. // tr.test_eq(0, ra); // ra unchanged
  257. // tr.test(std::ranges::equal(rb.begin(), rb.end(), aiter, rb.end())); // aiter changed
  258. // }
  259. // {
  260. // aiter = rb.begin();
  261. // tr.test_eq(0, ra); // ra unchanged
  262. // tr.test(std::ranges::equal(rb.begin(), rb.end(), aiter, rb.end())); // aiter changed
  263. // }
  264. // }
  265. tr.section("shape of .iter()");
  266. {
  267. auto test = [&tr](auto && A)
  268. {
  269. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, ra::shape(A));
  270. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(A.iter()));
  271. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(iter<0>(A)));
  272. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(iter<-2>(A)));
  273. tr.test_eq(ra::Small<ra::dim_t, 1> {6}, shape(iter<1>(A)));
  274. tr.test_eq(ra::Small<ra::dim_t, 1> {6}, shape(iter<-1>(A)));
  275. tr.test_eq(ra::Small<ra::dim_t, 0> {}, shape(iter<2>(A)));
  276. };
  277. test(ra::Unique<double, 2>({6, 7}, ra::_0 - ra::_1));
  278. test(ra::Unique<double>({6, 7}, ra::_0 - ra::_1));
  279. }
  280. tr.section("STL-type iterators");
  281. {
  282. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  283. ra::ViewBig<double, 1> r { {ra::Dim {6, 1}}, rpool };
  284. double spool[6] = { 0, 0, 0, 0, 0, 0 };
  285. ra::ViewBig<double> s { {{3, 1}, {2, 3}}, spool };
  286. std::ranges::copy(r.begin(), r.end(), s.begin());
  287. double cpool[6] = { 1, 3, 5, 2, 4, 6 };
  288. tr.test(std::equal(cpool, cpool+6, spool));
  289. }
  290. tr.section("storage types");
  291. {
  292. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  293. ra::Shared<double> s({3, 2}, pool, 6);
  294. tr.test_eq(2, s.rank());
  295. tr.test(std::equal(pool, pool+6, s.begin()));
  296. ra::Unique<double> u({3, 2}, pool, 6);
  297. tr.test_eq(2, u.rank());
  298. tr.test(std::equal(pool, pool+6, u.begin()));
  299. ra::Big<double> o({3, 2}, pool, 6);
  300. tr.test_eq(2, o.rank());
  301. tr.test(std::equal(pool, pool+6, o.begin()));
  302. }
  303. tr.section("copy between arrays, construct from iterator pair");
  304. {
  305. // copy from Fortran order to C order.
  306. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  307. double check[6] = { 1, 4, 2, 5, 3, 6 };
  308. ra::ViewBig<double> r { {{3, 1}, {2, 3}}, rpool };
  309. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  310. tr.test(std::ranges::equal(check, check+6, r.begin(), r.end()));
  311. ra::Unique<double> u({3, 2}, r.begin(), r.size());
  312. std::ranges::copy(u.begin(), u.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  313. tr.test(std::equal(check, check+6, u.begin()));
  314. // Small steps are tested in test/small-0.cc, test/small-1.cc.
  315. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  316. std::copy(s.begin(), s.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  317. tr.test(std::equal(check, check+6, s.begin()));
  318. // construct Small from pointers / iterators. These still work by prefix match.
  319. // use std::copy() after construction for row major fill.
  320. double rrcheck[6] = { 1, 1, 2, 2, 3, 3 };
  321. auto check_ptr
  322. = [&](auto && rr)
  323. {
  324. ra::Small<double, 3, 2> z(ra::ptr(rr));
  325. std::copy(z.begin(), z.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  326. tr.test(std::equal(rrcheck, rrcheck+6, z.begin()));
  327. };
  328. {
  329. std::vector<double> rr { 1, 2, 3, 4, 5, 6 };
  330. check_ptr(rr.begin());
  331. }
  332. {
  333. double rr[6] { 1, 2, 3, 4, 5, 6 };
  334. check_ptr((double *)rr);
  335. }
  336. {
  337. ra::Unique<double, 1> rr = { 1, 2, 3, 4, 5, 6 };
  338. check_ptr(rr.begin());
  339. }
  340. }
  341. // In this case, the View + shape provides the driver.
  342. tr.section("construct View from shape + driverless xpr");
  343. {
  344. {
  345. int checkb[6] = { 0, 0, 1, 1, 2, 2 };
  346. ra::Unique<int, 2> b({3, 2}, ra::_0);
  347. tr.test(std::equal(checkb, checkb+6, b.begin()));
  348. }
  349. // This requires the driverless xpr dyn(scalar, tensorindex) to be constructible.
  350. {
  351. int checkb[6] = { 3, 3, 4, 4, 5, 5 };
  352. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a+b; }, ra::scalar(3), start(ra::_0)));
  353. tr.test(std::equal(checkb, checkb+6, b.begin()));
  354. }
  355. {
  356. int checkb[6] = { 0, -1, 1, 0, 2, 1 };
  357. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, start(ra::_0), start(ra::_1)));
  358. tr.test(std::equal(checkb, checkb+6, b.begin()));
  359. }
  360. // TODO Check this is an error (chosen driver is ra::iota<2>(), that can't drive) [ra42]
  361. // {
  362. // ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::iota<2>(), ra::iota<1>()));
  363. // cout << b << endl;
  364. // }
  365. // TODO Could this be made to bomb at compile time? [ra42]
  366. // {
  367. // ra::Unique<int> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::iota<2>(), ra::iota<1>()));
  368. // cout << b << endl;
  369. // }
  370. }
  371. tr.section("construct View from shape + xpr");
  372. {
  373. double checka[6] = { 9, 9, 9, 9, 9, 9 };
  374. ra::Unique<double, 2> a({3, 2}, ra::scalar(9));
  375. tr.test(std::equal(checka, checka+6, a.begin()));
  376. double checkb[6] = { 11, 11, 22, 22, 33, 33 };
  377. ra::Unique<double, 2> b({3, 2}, ra::Small<double, 3> { 11, 22, 33 });
  378. tr.test(std::equal(checkb, checkb+6, b.begin()));
  379. }
  380. tr.section("construct Unique from Unique");
  381. {
  382. double check[6] = { 2, 3, 1, 4, 8, 9 };
  383. ra::Unique<double, 2> a({3, 2}, { 2, 3, 1, 4, 8, 9 });
  384. // ra::Unique<double, 2> b(a); // error; need temp
  385. ra::Unique<double, 2> c(ra::Unique<double, 2>({3, 2}, { 2, 3, 1, 4, 8, 9 })); // ok; from actual temp
  386. tr.test(std::equal(check, check+6, c.begin()));
  387. ra::Unique<double, 2> d(std::move(a)); // ok; from fake temp
  388. tr.test(std::equal(check, check+6, d.begin()));
  389. }
  390. tr.section("construct from xpr having its own shape");
  391. {
  392. ra::Unique<double, 0> a(ra::scalar(33));
  393. ra::Unique<double> b(ra::scalar(44));
  394. // b.rank() is runtime, so b()==44. and the test arguments become array xprs
  395. tr.test_eq(0, b.rank());
  396. tr.test_eq(1, b.size());
  397. tr.test_eq(44, b());
  398. b = 55.;
  399. cout << "b: " << b << endl;
  400. // see above for b.rank().
  401. tr.test_eq(0, b.rank());
  402. tr.test_eq(1, b.size());
  403. tr.test_eq(55., b());
  404. }
  405. tr.section("rank 0 -> scalar with storage type");
  406. {
  407. auto rank0test0 = [](double & a) { a *= 2; };
  408. auto rank0test1 = [](double const & a) { return a*2; };
  409. ra::Unique<double, 0> a(ra::scalar(33));
  410. tr.test_eq(1, a.size());
  411. // static_assert(sizeof(a())==sizeof(double *), "bad assumption"); // [170]
  412. rank0test0(a);
  413. tr.test_eq(66, a);
  414. double b = rank0test1(a);
  415. tr.test_eq(66, a);
  416. tr.test_eq(132, b);
  417. }
  418. tr.section("rank 0 -> scalar with storage type, explicit size");
  419. {
  420. auto rank0test0 = [](double & a) { a *= 2; };
  421. auto rank0test1 = [](double const & a) { return a*2; };
  422. ra::Unique<double, 0> a({}, ra::scalar(33));
  423. tr.test_eq(1, a.size());
  424. // static_assert(sizeof(a())==sizeof(double *), "bad assumption"); // [170]
  425. rank0test0(a);
  426. tr.test_eq(66, a);
  427. double b = rank0test1(a);
  428. tr.test_eq(66, a);
  429. tr.test_eq(132, b);
  430. }
  431. tr.section("constructors from data in initializer_list");
  432. {
  433. double checka[6] = { 2, 3, 1, 4, 8, 9 };
  434. {
  435. ra::Unique<double, 2> a({2, 3}, { 2, 3, 1, 4, 8, 9 });
  436. tr.test_eq(2, a.dimv[0].len);
  437. tr.test_eq(3, a.dimv[1].len);
  438. tr.test(std::equal(a.begin(), a.end(), checka));
  439. }
  440. {
  441. ra::Unique<double> a { 2, 3, 1, 4, 8, 9 };
  442. tr.test_eq(6, a.size());
  443. tr.test_eq(1, a.rank());
  444. tr.test(std::equal(a.begin(), a.end(), checka));
  445. ra::Unique<double> b ({ 2, 3, 1, 4, 8, 9 });
  446. tr.test_eq(6, b.size());
  447. tr.test_eq(1, b.rank());
  448. tr.test(std::equal(b.begin(), b.end(), checka));
  449. }
  450. {
  451. ra::Unique<double, 1> a { 2, 3, 1, 4, 8, 9 };
  452. tr.test_eq(6, a.size());
  453. tr.test_eq(1, a.rank());
  454. tr.test(std::equal(a.begin(), a.end(), checka));
  455. ra::Unique<double, 1> b ({ 2, 3, 1, 4, 8, 9 });
  456. tr.test_eq(6, b.size());
  457. tr.test_eq(1, b.rank());
  458. tr.test(std::equal(b.begin(), b.end(), checka));
  459. }
  460. }
  461. tr.section("row-major assignment from initializer_list, rank 2");
  462. {
  463. ra::Unique<double, 2> a({3, 2}, ra::none);
  464. a = { 2, 3, 1, 4, 8, 9 };
  465. tr.test_eq(2, a(0, 0));
  466. tr.test_eq(3, a(0, 1));
  467. tr.test_eq(1, a(1, 0));
  468. tr.test_eq(4, a(1, 1));
  469. tr.test_eq(8, a(2, 0));
  470. tr.test_eq(9, a(2, 1));
  471. auto b = transpose({1, 0}, a);
  472. b = { 2, 3, 1, 4, 8, 9 };
  473. tr.test_eq(2, b(0, 0));
  474. tr.test_eq(3, b(0, 1));
  475. tr.test_eq(1, b(0, 2));
  476. tr.test_eq(4, b(1, 0));
  477. tr.test_eq(8, b(1, 1));
  478. tr.test_eq(9, b(1, 2));
  479. tr.test_eq(2, a(0, 0));
  480. tr.test_eq(4, a(0, 1));
  481. tr.test_eq(3, a(1, 0));
  482. tr.test_eq(8, a(1, 1));
  483. tr.test_eq(1, a(2, 0));
  484. tr.test_eq(9, a(2, 1));
  485. auto c = transpose({1, 0}, a);
  486. tr.test(a.data()==c.data()); // pointers are not ra::scalars. Dunno if this deserves fixing.
  487. tr.test_eq(a.len(0), c.len(1));
  488. tr.test_eq(a.len(1), c.len(0));
  489. tr.test_eq(b, c);
  490. }
  491. tr.section("row-major assignment from initializer_list, rank 1");
  492. {
  493. ra::Big<double, 1> a({5}, ra::none);
  494. a = { 2, 3, 1, 4, 8 };
  495. tr.test_eq(2, a(0));
  496. tr.test_eq(3, a(1));
  497. tr.test_eq(1, a(2));
  498. tr.test_eq(4, a(3));
  499. tr.test_eq(8, a(4));
  500. }
  501. tr.section("subscripts");
  502. {
  503. tr.section("View fixed rank == 0");
  504. {
  505. double x = 99;
  506. ra::ViewBig<double, 0> y(ra::Small<int, 0>{}, &x);
  507. tr.test_eq(99, y());
  508. tr.test_eq(99, y);
  509. double u = 77.;
  510. ra::ViewBig<double, 0> v(ra::Small<int, 0>{}, &u);
  511. y = v;
  512. tr.test_eq(77, u);
  513. tr.test_eq(77, v);
  514. tr.test_eq(77, x);
  515. tr.test_eq(77, y);
  516. }
  517. tr.section("View fixed rank > 0");
  518. {
  519. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  520. ra::ViewBig<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  521. cout << "org" << endl;
  522. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  523. {
  524. double rcheck[6] = { 1, 4, 2, 5, 3, 6 };
  525. auto r0 = r();
  526. tr.test(std::ranges::equal(r0.begin(), r0.end(), rcheck, rcheck+6));
  527. ra::Small<int, 0> i0 {};
  528. tr.info("ra::Small<int, 0> rank").test_eq(1, i0.rank());
  529. auto r0a = r.at(ra::Small<int, 0> {});
  530. tr.info("fix size").test(std::ranges::equal(r0a.begin(), r0a.end(), rcheck, rcheck+6));
  531. auto r0b = r.at(ra::Big<int, 1> {});
  532. tr.info("fix rank").test(std::ranges::equal(r0b.begin(), r0b.end(), rcheck, rcheck+6));
  533. auto r0c = r.at(0+ra::Big<int, 1> {});
  534. tr.info("fix rank expr").test(std::ranges::equal(r0c.begin(), r0c.end(), rcheck, rcheck+6));
  535. auto r0d = r.at(0+ra::Big<int>({0}, {}));
  536. tr.info("r0d: [", r0d, "]").test(std::ranges::equal(r0d.begin(), r0d.end(), rcheck, rcheck+6));
  537. }
  538. {
  539. double rcheck[2] = { 2, 5 };
  540. auto r1 = r(1);
  541. tr.test_eq(rcheck, r1);
  542. tr.strictshape().test_eq(rcheck, r.at(ra::Small<int, 1> {1}));
  543. tr.strictshape().test_eq(rcheck, r.at(ra::Big<int, 1> {1}));
  544. tr.strictshape().test_eq(rcheck, r.at(0+ra::Big<int, 1> {1}));
  545. tr.strictshape().test_eq(rcheck, r.at(0+ra::Big<int> {1}));
  546. }
  547. {
  548. auto r2 = r(1, 1);
  549. tr.test_eq(5, r2);
  550. tr.info("r2a 1)").test_eq(5, r.at(ra::Small<int, 2> {1, 1}));
  551. tr.info("r2a 2)").test_eq(5, r.at(ra::Big<int, 1> {1, 1}));
  552. tr.info("r2a 3)").test_eq(5, r.at(0+ra::Big<int, 1> {1, 1}));
  553. tr.info("r2a 4)").test_eq(5, r.at(0+ra::Big<int> {1, 1}));
  554. }
  555. }
  556. // TODO Subscript a rank>1 array, multiple selectors, mixed beatable & unbeatable selectors.
  557. tr.section("View fixed rank, unbeatable subscripts");
  558. {
  559. ra::Unique<double, 1> a = {1, 2, 3, 4};
  560. ra::Unique<int, 1> i = {3, 1, 2};
  561. cout << a(i) << endl;
  562. ra::Unique<double, 1> ai = a(i);
  563. tr.test_eq(i.size(), ai.size());
  564. tr.test_eq(a[i[0]], ai[0]);
  565. tr.test_eq(a[i[1]], ai[1]);
  566. tr.test_eq(a[i[2]], ai[2]);
  567. a(i) = ra::Unique<double, 1> {7, 8, 9};
  568. cout << a << endl;
  569. tr.test_eq(4, a.size());
  570. tr.test_eq(1, a[0]);
  571. tr.test_eq(a[i[0]], 7);
  572. tr.test_eq(a[i[1]], 8);
  573. tr.test_eq(a[i[2]], 9);
  574. }
  575. tr.section("View var rank");
  576. {
  577. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  578. ra::ViewBig<double> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  579. tr.test_eq(2, r.rank());
  580. cout << "org" << endl;
  581. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  582. double rcheck0[6] = { 1, 4, 2, 5, 3, 6 };
  583. auto r0 = r();
  584. auto r0a = r.at(ra::Small<int, 0> {});
  585. tr.test_eq(2, r0a.rank());
  586. tr.test_eq(2, r0.rank());
  587. cout << "r0" << endl;
  588. std::ranges::copy(r0.begin(), r0.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  589. tr.test(std::ranges::equal(r0.begin(), r0.end(), rcheck0, rcheck0+6));
  590. tr.test(std::ranges::equal(r0a.begin(), r0a.end(), rcheck0, rcheck0+6));
  591. double rcheck1[2] = { 2, 5 };
  592. auto r1 = r(1);
  593. auto r1a = r.at(ra::Small<int, 1> {1});
  594. tr.test_eq(1, r1a.rank());
  595. tr.test_eq(1, r1.rank());
  596. cout << "r1" << endl;
  597. std::ranges::copy(r1.begin(), r1.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  598. tr.test(std::ranges::equal(r1.begin(), r1.end(), rcheck1, rcheck1+2));
  599. tr.test(std::ranges::equal(r1a.begin(), r1a.end(), rcheck1, rcheck1+2));
  600. double rcheck2[1] = { 5 };
  601. auto r2 = r(1, 1);
  602. auto r2a = r.at(ra::Small<int, 2> {1, 1});
  603. tr.test_eq(0, r2a.rank());
  604. cout << "r2" << endl;
  605. std::ranges::copy(r2.begin(), r2.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  606. tr.test(std::ranges::equal(r2.begin(), r2.end(), rcheck2, rcheck2+1));
  607. tr.test(std::ranges::equal(r2a.begin(), r2a.end(), rcheck2, rcheck2+1));
  608. }
  609. // TODO Make sure that this is double & = 99, etc. and not View<double, 0> = 99, etc.
  610. tr.section("assign to rank-0 result of subscript");
  611. {
  612. double check[6] = {99, 88, 77, 66, 55, 44};
  613. ra::Unique<double> a({2, 3}, 11.);
  614. a(0, 0) = 99; a(0, 1) = 88; a(0, 2) = 77;
  615. a(1, 0) = 66; a(1, 1) = 55; a(1, 2) = 44;
  616. std::copy(a.begin(), a.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  617. tr.test(std::equal(check, check+6, a.begin()));
  618. }
  619. }
  620. tr.section("construct from shape");
  621. {
  622. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  623. std::iota(a.begin(), a.end(), 0);
  624. auto sa = ra::shape(a);
  625. tr.test_eq(3, sa[0]);
  626. tr.test_eq(2, sa[1]);
  627. tr.test_eq(4, sa[2]);
  628. tr.test_eq(3, ra::shape(a, 0));
  629. tr.test_eq(2, ra::shape(a, 1));
  630. tr.test_eq(4, ra::shape(a, 2));
  631. double check[24];
  632. std::iota(check, check+24, 0);
  633. tr.test(std::equal(check, check+24, a.begin()));
  634. }
  635. tr.section("shape accepts len");
  636. {
  637. ra::Unique<double> a({3, 2, 4}, ra::none);
  638. tr.test_eq(4, shape(a, ra::len-1));
  639. tr.test_eq(3, shape(ra::Small<int, 4, 3, 2> {}, ra::len-2));
  640. }
  641. tr.section("I/O");
  642. {
  643. tr.section("1");
  644. {
  645. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  646. double check[6] = { 1, 4, 2, 5, 3, 6 };
  647. CheckArrayIO(tr, s, check);
  648. }
  649. tr.section("2");
  650. {
  651. ra::Small<double, 3> s { 1, 4, 2 };
  652. double check[3] = { 1, 4, 2 };
  653. CheckArrayIO(tr, s, check);
  654. }
  655. tr.section("3");
  656. {
  657. ra::Small<double> s { 77 };
  658. double check[1] = { 77 };
  659. CheckArrayIO(tr, s, check);
  660. }
  661. tr.section("4. View<> can't allocate, so have no istream >>. Check output only.");
  662. {
  663. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  664. ra::ViewBig<double, 3> r { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  665. double check[11] = { 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  666. CheckArrayOutput(tr, r, check);
  667. }
  668. tr.section("5");
  669. {
  670. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  671. ra::ViewBig<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  672. double check[8] = { 3, 2, 1, 4, 2, 5, 3, 6 };
  673. CheckArrayOutput(tr, r, check);
  674. }
  675. tr.section("6");
  676. {
  677. double rpool[3] = { 1, 2, 3 };
  678. ra::ViewBig<double, 1> r { {ra::Dim {3, 1}}, rpool };
  679. double check[4] = { 3, 1, 2, 3 };
  680. CheckArrayOutput(tr, r, check);
  681. }
  682. tr.section("7");
  683. {
  684. double rpool[1] = { 88 };
  685. ra::ViewBig<double, 0> r { {}, rpool };
  686. double check[1] = { 88 };
  687. CheckArrayOutput(tr, r, check);
  688. tr.test_eq(1, r.size());
  689. // static_assert(sizeof(r)==sizeof(double *), "bad assumption"); [170]
  690. tr.test_eq(88, r);
  691. }
  692. tr.section("8");
  693. {
  694. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  695. ra::ViewBig<double> a { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  696. double check[12] = { 3, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  697. CheckArrayOutput(tr, a, check);
  698. // default steps.
  699. ra::ViewBig<double> b { {2, 2, 2}, rpool };
  700. CheckArrayOutput(tr, b, check);
  701. }
  702. tr.section("9");
  703. {
  704. ra::Unique<double, 3> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  705. std::iota(a.begin(), a.end(), 0);
  706. double check[3+24] = { 3, 2, 4 };
  707. std::iota(check+3, check+3+24, 0);
  708. CheckArrayIO(tr, a, check);
  709. }
  710. tr.section("10");
  711. {
  712. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  713. std::iota(a.begin(), a.end(), 0);
  714. double check[4+24] = { 3, 3, 2, 4 };
  715. std::iota(check+4, check+4+24, 0);
  716. CheckArrayIO(tr, a, check);
  717. }
  718. }
  719. tr.section("ply - xpr types - Scalar");
  720. {
  721. {
  722. auto s = ra::scalar(7);
  723. cout << "s: " << s.c << endl;
  724. }
  725. {
  726. auto s = ra::scalar(ra::Small<int, 2> {11, 12});
  727. cout << "s: " << s.c << endl;
  728. }
  729. {
  730. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  731. std::iota(a.begin(), a.end(), 0);
  732. auto s = ra::scalar(a);
  733. cout << "s: " << s.c << endl;
  734. }
  735. }
  736. tr.section("scalar as reference");
  737. {
  738. int a = 3;
  739. ra::scalar(a) += ra::Small<int, 3> {4, 5, 6};
  740. tr.test_eq(18, a);
  741. // beware: throws away 3+4,3+5, only 3+6 is left. [ma107]
  742. ra::scalar(a) = 3 + ra::Small<int, 3> {4, 5, 6};
  743. tr.test_eq(9, a);
  744. }
  745. tr.section("can use pointer-to-member in expressions");
  746. {
  747. struct A { int a, b; };
  748. std::vector<A> v = {{1, 2}, {3, 4}};
  749. tr.test_eq(4, sum(ra::map(&A::a, v)));
  750. tr.test_eq(6, sum(ra::map(&A::b, v)));
  751. ra::map(&A::a, v) = -ra::map(&A::b, v);
  752. tr.test_eq(-2, v[0].a);
  753. tr.test_eq(-4, v[1].a);
  754. }
  755. return tr.summary();
  756. }