ra-0.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  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::View<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::View<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::View<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::View<double, 0> a { {}, &x };
  139. tr.test_eq(1, a.size());
  140. // 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...
  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::View<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::View<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::View<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::equal(pool, pool+6, r.begin()));
  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::View<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::equal(pool, pool+6, r.begin()));
  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::View<double> ra { {{3, 2}, {2, 1}}, a };
  215. ra::View<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. tr.section("[ra11c] STL-type iterators never copy contents");
  246. {
  247. double a[6] = { 0, 0, 0, 0, 0, 0 };
  248. double b[6] = { 1, 2, 3, 4, 5, 6 };
  249. ra::View<double> ra { {{3, 2}, {2, 1}}, a };
  250. ra::View<double> rb { {{3, 2}, {2, 1}}, b };
  251. auto aiter = ra.begin();
  252. {
  253. auto biter = rb.begin();
  254. aiter = biter;
  255. tr.test_eq(0, ra); // ra unchanged
  256. tr.test(std::ranges::equal(rb.begin(), rb.end(), aiter, rb.end())); // aiter changed
  257. }
  258. {
  259. aiter = rb.begin();
  260. tr.test_eq(0, ra); // ra unchanged
  261. tr.test(std::ranges::equal(rb.begin(), rb.end(), aiter, rb.end())); // aiter changed
  262. }
  263. }
  264. tr.section("shape of .iter()");
  265. {
  266. auto test = [&tr](auto && A)
  267. {
  268. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, ra::shape(A));
  269. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(A.iter()));
  270. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(iter<0>(A)));
  271. tr.test_eq(ra::Small<ra::dim_t, 2> {6, 7}, shape(iter<-2>(A)));
  272. tr.test_eq(ra::Small<ra::dim_t, 1> {6}, shape(iter<1>(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, 0> {}, shape(iter<2>(A)));
  275. };
  276. test(ra::Unique<double, 2>({6, 7}, ra::_0 - ra::_1));
  277. test(ra::Unique<double>({6, 7}, ra::_0 - ra::_1));
  278. }
  279. tr.section("STL-type iterators");
  280. {
  281. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  282. ra::View<double, 1> r { {ra::Dim {6, 1}}, rpool };
  283. double spool[6] = { 0, 0, 0, 0, 0, 0 };
  284. ra::View<double> s { {{3, 1}, {2, 3}}, spool };
  285. std::ranges::copy(r.begin(), r.end(), s.begin());
  286. double cpool[6] = { 1, 3, 5, 2, 4, 6 };
  287. tr.test(std::equal(cpool, cpool+6, spool));
  288. }
  289. tr.section("storage types");
  290. {
  291. double pool[6] = { 1, 2, 3, 4, 5, 6 };
  292. ra::Shared<double> s({3, 2}, pool, 6);
  293. tr.test_eq(2, s.rank());
  294. tr.test(std::equal(pool, pool+6, s.begin()));
  295. ra::Unique<double> u({3, 2}, pool, 6);
  296. tr.test_eq(2, u.rank());
  297. tr.test(std::equal(pool, pool+6, u.begin()));
  298. ra::Big<double> o({3, 2}, pool, 6);
  299. tr.test_eq(2, o.rank());
  300. tr.test(std::equal(pool, pool+6, o.begin()));
  301. }
  302. tr.section("copy between arrays, construct from iterator pair");
  303. {
  304. // copy from Fortran order to C order.
  305. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  306. double check[6] = { 1, 4, 2, 5, 3, 6 };
  307. ra::View<double> r { {{3, 1}, {2, 3}}, rpool };
  308. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  309. tr.test(std::equal(check, check+6, r.begin()));
  310. ra::Unique<double> u({3, 2}, r.begin(), r.size());
  311. std::ranges::copy(u.begin(), u.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  312. tr.test(std::equal(check, check+6, u.begin()));
  313. // Small steps are tested in test/small-0.cc, test/small-1.cc.
  314. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  315. std::copy(s.begin(), s.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  316. tr.test(std::equal(check, check+6, s.begin()));
  317. // construct Small from pointers / iterators. These still work by prefix match.
  318. // use std::copy() after construction for row major fill.
  319. double rrcheck[6] = { 1, 1, 2, 2, 3, 3 };
  320. auto check_ptr
  321. = [&](auto && rr)
  322. {
  323. ra::Small<double, 3, 2> z(ra::ptr(rr));
  324. std::copy(z.begin(), z.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  325. tr.test(std::equal(rrcheck, rrcheck+6, z.begin()));
  326. };
  327. {
  328. std::vector<double> rr { 1, 2, 3, 4, 5, 6 };
  329. check_ptr(rr.begin());
  330. }
  331. {
  332. double rr[6] { 1, 2, 3, 4, 5, 6 };
  333. check_ptr((double *)rr);
  334. }
  335. {
  336. ra::Unique<double, 1> rr = { 1, 2, 3, 4, 5, 6 };
  337. check_ptr(rr.begin());
  338. }
  339. }
  340. // In this case, the View + shape provides the driver.
  341. tr.section("construct View from shape + driverless xpr");
  342. {
  343. {
  344. int checkb[6] = { 0, 0, 1, 1, 2, 2 };
  345. ra::Unique<int, 2> b({3, 2}, ra::_0);
  346. tr.test(std::equal(checkb, checkb+6, b.begin()));
  347. }
  348. // This requires the driverless xpr dyn(scalar, tensorindex) to be constructible.
  349. {
  350. int checkb[6] = { 3, 3, 4, 4, 5, 5 };
  351. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a+b; }, ra::scalar(3), start(ra::_0)));
  352. tr.test(std::equal(checkb, checkb+6, b.begin()));
  353. }
  354. {
  355. int checkb[6] = { 0, -1, 1, 0, 2, 1 };
  356. ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, start(ra::_0), start(ra::_1)));
  357. tr.test(std::equal(checkb, checkb+6, b.begin()));
  358. }
  359. // TODO Check this is an error (chosen driver is ra::iota<2>(), that can't drive) [ra42]
  360. // {
  361. // ra::Unique<int, 2> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::iota<2>(), ra::iota<1>()));
  362. // cout << b << endl;
  363. // }
  364. // TODO Could this be made to bomb at compile time? [ra42]
  365. // {
  366. // ra::Unique<int> b({3, 2}, ra::expr([](int a, int b) { return a-b; }, ra::iota<2>(), ra::iota<1>()));
  367. // cout << b << endl;
  368. // }
  369. }
  370. tr.section("construct View from shape + xpr");
  371. {
  372. double checka[6] = { 9, 9, 9, 9, 9, 9 };
  373. ra::Unique<double, 2> a({3, 2}, ra::scalar(9));
  374. tr.test(std::equal(checka, checka+6, a.begin()));
  375. double checkb[6] = { 11, 11, 22, 22, 33, 33 };
  376. ra::Unique<double, 2> b({3, 2}, ra::Small<double, 3> { 11, 22, 33 });
  377. tr.test(std::equal(checkb, checkb+6, b.begin()));
  378. }
  379. tr.section("construct Unique from Unique");
  380. {
  381. double check[6] = { 2, 3, 1, 4, 8, 9 };
  382. ra::Unique<double, 2> a({3, 2}, { 2, 3, 1, 4, 8, 9 });
  383. // ra::Unique<double, 2> b(a); // error; need temp
  384. ra::Unique<double, 2> c(ra::Unique<double, 2>({3, 2}, { 2, 3, 1, 4, 8, 9 })); // ok; from actual temp
  385. tr.test(std::equal(check, check+6, c.begin()));
  386. ra::Unique<double, 2> d(std::move(a)); // ok; from fake temp
  387. tr.test(std::equal(check, check+6, d.begin()));
  388. }
  389. tr.section("construct from xpr having its own shape");
  390. {
  391. ra::Unique<double, 0> a(ra::scalar(33));
  392. ra::Unique<double> b(ra::scalar(44));
  393. // b.rank() is runtime, so b()==44. and the test arguments become array xprs
  394. tr.test_eq(0, b.rank());
  395. tr.test_eq(1, b.size());
  396. tr.test_eq(44, b());
  397. b = 55.;
  398. cout << "b: " << b << endl;
  399. // see above for b.rank().
  400. tr.test_eq(0, b.rank());
  401. tr.test_eq(1, b.size());
  402. tr.test_eq(55., b());
  403. }
  404. tr.section("rank 0 -> scalar with storage type");
  405. {
  406. auto rank0test0 = [](double & a) { a *= 2; };
  407. auto rank0test1 = [](double const & a) { return a*2; };
  408. ra::Unique<double, 0> a(ra::scalar(33));
  409. tr.test_eq(1, a.size());
  410. // static_assert(sizeof(a())==sizeof(double *), "bad assumption"); // [170]
  411. rank0test0(a);
  412. tr.test_eq(66, a);
  413. double b = rank0test1(a);
  414. tr.test_eq(66, a);
  415. tr.test_eq(132, b);
  416. }
  417. tr.section("rank 0 -> scalar with storage type, explicit size");
  418. {
  419. auto rank0test0 = [](double & a) { a *= 2; };
  420. auto rank0test1 = [](double const & a) { return a*2; };
  421. ra::Unique<double, 0> a({}, ra::scalar(33));
  422. tr.test_eq(1, a.size());
  423. // static_assert(sizeof(a())==sizeof(double *), "bad assumption"); // [170]
  424. rank0test0(a);
  425. tr.test_eq(66, a);
  426. double b = rank0test1(a);
  427. tr.test_eq(66, a);
  428. tr.test_eq(132, b);
  429. }
  430. tr.section("constructors from data in initializer_list");
  431. {
  432. double checka[6] = { 2, 3, 1, 4, 8, 9 };
  433. {
  434. ra::Unique<double, 2> a({2, 3}, { 2, 3, 1, 4, 8, 9 });
  435. tr.test_eq(2, a.dimv[0].len);
  436. tr.test_eq(3, a.dimv[1].len);
  437. tr.test(std::equal(a.begin(), a.end(), checka));
  438. }
  439. {
  440. ra::Unique<double> a { 2, 3, 1, 4, 8, 9 };
  441. tr.test_eq(6, a.size());
  442. tr.test_eq(1, a.rank());
  443. tr.test(std::equal(a.begin(), a.end(), checka));
  444. ra::Unique<double> b ({ 2, 3, 1, 4, 8, 9 });
  445. tr.test_eq(6, b.size());
  446. tr.test_eq(1, b.rank());
  447. tr.test(std::equal(b.begin(), b.end(), checka));
  448. }
  449. {
  450. ra::Unique<double, 1> a { 2, 3, 1, 4, 8, 9 };
  451. tr.test_eq(6, a.size());
  452. tr.test_eq(1, a.rank());
  453. tr.test(std::equal(a.begin(), a.end(), checka));
  454. ra::Unique<double, 1> b ({ 2, 3, 1, 4, 8, 9 });
  455. tr.test_eq(6, b.size());
  456. tr.test_eq(1, b.rank());
  457. tr.test(std::equal(b.begin(), b.end(), checka));
  458. }
  459. }
  460. tr.section("row-major assignment from initializer_list, rank 2");
  461. {
  462. ra::Unique<double, 2> a({3, 2}, ra::none);
  463. a = { 2, 3, 1, 4, 8, 9 };
  464. tr.test_eq(2, a(0, 0));
  465. tr.test_eq(3, a(0, 1));
  466. tr.test_eq(1, a(1, 0));
  467. tr.test_eq(4, a(1, 1));
  468. tr.test_eq(8, a(2, 0));
  469. tr.test_eq(9, a(2, 1));
  470. auto b = transpose({1, 0}, a);
  471. b = { 2, 3, 1, 4, 8, 9 };
  472. tr.test_eq(2, b(0, 0));
  473. tr.test_eq(3, b(0, 1));
  474. tr.test_eq(1, b(0, 2));
  475. tr.test_eq(4, b(1, 0));
  476. tr.test_eq(8, b(1, 1));
  477. tr.test_eq(9, b(1, 2));
  478. tr.test_eq(2, a(0, 0));
  479. tr.test_eq(4, a(0, 1));
  480. tr.test_eq(3, a(1, 0));
  481. tr.test_eq(8, a(1, 1));
  482. tr.test_eq(1, a(2, 0));
  483. tr.test_eq(9, a(2, 1));
  484. auto c = transpose({1, 0}, a);
  485. tr.test(a.data()==c.data()); // pointers are not ra::scalars. Dunno if this deserves fixing.
  486. tr.test_eq(a.len(0), c.len(1));
  487. tr.test_eq(a.len(1), c.len(0));
  488. tr.test_eq(b, c);
  489. }
  490. tr.section("row-major assignment from initializer_list, rank 1");
  491. {
  492. ra::Big<double, 1> a({5}, ra::none);
  493. a = { 2, 3, 1, 4, 8 };
  494. tr.test_eq(2, a(0));
  495. tr.test_eq(3, a(1));
  496. tr.test_eq(1, a(2));
  497. tr.test_eq(4, a(3));
  498. tr.test_eq(8, a(4));
  499. }
  500. tr.section("subscripts");
  501. {
  502. tr.section("View fixed rank == 0");
  503. {
  504. double x = 99;
  505. ra::View<double, 0> y(ra::Small<int, 0>{}, &x);
  506. tr.test_eq(99, y());
  507. tr.test_eq(99, y);
  508. double u = 77.;
  509. ra::View<double, 0> v(ra::Small<int, 0>{}, &u);
  510. y = v;
  511. tr.test_eq(77, u);
  512. tr.test_eq(77, v);
  513. tr.test_eq(77, x);
  514. tr.test_eq(77, y);
  515. }
  516. tr.section("View fixed rank > 0");
  517. {
  518. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  519. ra::View<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  520. cout << "org" << endl;
  521. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  522. {
  523. double rcheck[6] = { 1, 4, 2, 5, 3, 6 };
  524. auto r0 = r();
  525. tr.test(std::ranges::equal(r0.begin(), r0.end(), rcheck, rcheck+6));
  526. ra::Small<int, 0> i0 {};
  527. tr.info("ra::Small<int, 0> rank").test_eq(1, i0.rank());
  528. auto r0a = r.at(ra::Small<int, 0> {});
  529. tr.info("fix size").test(std::ranges::equal(r0a.begin(), r0a.end(), rcheck, rcheck+6));
  530. auto r0b = r.at(ra::Big<int, 1> {});
  531. tr.info("fix rank").test(std::ranges::equal(r0b.begin(), r0b.end(), rcheck, rcheck+6));
  532. auto r0c = r.at(0+ra::Big<int, 1> {});
  533. tr.info("fix rank expr").test(std::ranges::equal(r0c.begin(), r0c.end(), rcheck, rcheck+6));
  534. auto r0d = r.at(0+ra::Big<int>({0}, {}));
  535. tr.info("r0d: [", r0d, "]").test(std::ranges::equal(r0d.begin(), r0d.end(), rcheck, rcheck+6));
  536. }
  537. {
  538. double rcheck[2] = { 2, 5 };
  539. auto r1 = r(1);
  540. tr.test_eq(rcheck, r1);
  541. tr.strictshape().test_eq(rcheck, r.at(ra::Small<int, 1> {1}));
  542. tr.strictshape().test_eq(rcheck, r.at(ra::Big<int, 1> {1}));
  543. tr.strictshape().test_eq(rcheck, r.at(0+ra::Big<int, 1> {1}));
  544. tr.strictshape().test_eq(rcheck, r.at(0+ra::Big<int> {1}));
  545. }
  546. {
  547. auto r2 = r(1, 1);
  548. tr.test_eq(5, r2);
  549. tr.info("r2a 1)").test_eq(5, r.at(ra::Small<int, 2> {1, 1}));
  550. tr.info("r2a 2)").test_eq(5, r.at(ra::Big<int, 1> {1, 1}));
  551. tr.info("r2a 3)").test_eq(5, r.at(0+ra::Big<int, 1> {1, 1}));
  552. tr.info("r2a 4)").test_eq(5, r.at(0+ra::Big<int> {1, 1}));
  553. }
  554. }
  555. // TODO Subscript a rank>1 array, multiple selectors, mixed beatable & unbeatable selectors.
  556. tr.section("View fixed rank, unbeatable subscripts");
  557. {
  558. ra::Unique<double, 1> a = {1, 2, 3, 4};
  559. ra::Unique<int, 1> i = {3, 1, 2};
  560. cout << a(i) << endl;
  561. ra::Unique<double, 1> ai = a(i);
  562. tr.test_eq(i.size(), ai.size());
  563. tr.test_eq(a[i[0]], ai[0]);
  564. tr.test_eq(a[i[1]], ai[1]);
  565. tr.test_eq(a[i[2]], ai[2]);
  566. a(i) = ra::Unique<double, 1> {7, 8, 9};
  567. cout << a << endl;
  568. tr.test_eq(4, a.size());
  569. tr.test_eq(1, a[0]);
  570. tr.test_eq(a[i[0]], 7);
  571. tr.test_eq(a[i[1]], 8);
  572. tr.test_eq(a[i[2]], 9);
  573. }
  574. tr.section("View var rank");
  575. {
  576. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  577. ra::View<double> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  578. tr.test_eq(2, r.rank());
  579. cout << "org" << endl;
  580. std::ranges::copy(r.begin(), r.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  581. double rcheck0[6] = { 1, 4, 2, 5, 3, 6 };
  582. auto r0 = r();
  583. auto r0a = r.at(ra::Small<int, 0> {});
  584. tr.test_eq(2, r0a.rank());
  585. tr.test_eq(2, r0.rank());
  586. cout << "r0" << endl;
  587. std::ranges::copy(r0.begin(), r0.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  588. tr.test(std::ranges::equal(r0.begin(), r0.end(), rcheck0, rcheck0+6));
  589. tr.test(std::ranges::equal(r0a.begin(), r0a.end(), rcheck0, rcheck0+6));
  590. double rcheck1[2] = { 2, 5 };
  591. auto r1 = r(1);
  592. auto r1a = r.at(ra::Small<int, 1> {1});
  593. tr.test_eq(1, r1a.rank());
  594. tr.test_eq(1, r1.rank());
  595. cout << "r1" << endl;
  596. std::ranges::copy(r1.begin(), r1.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  597. tr.test(std::ranges::equal(r1.begin(), r1.end(), rcheck1, rcheck1+2));
  598. tr.test(std::ranges::equal(r1a.begin(), r1a.end(), rcheck1, rcheck1+2));
  599. double rcheck2[1] = { 5 };
  600. auto r2 = r(1, 1);
  601. auto r2a = r.at(ra::Small<int, 2> {1, 1});
  602. tr.test_eq(0, r2a.rank());
  603. cout << "r2" << endl;
  604. std::ranges::copy(r2.begin(), r2.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  605. tr.test(std::ranges::equal(r2.begin(), r2.end(), rcheck2, rcheck2+1));
  606. tr.test(std::ranges::equal(r2a.begin(), r2a.end(), rcheck2, rcheck2+1));
  607. }
  608. // TODO Make sure that this is double & = 99, etc. and not View<double, 0> = 99, etc.
  609. tr.section("assign to rank-0 result of subscript");
  610. {
  611. double check[6] = {99, 88, 77, 66, 55, 44};
  612. ra::Unique<double> a({2, 3}, 11.);
  613. a(0, 0) = 99; a(0, 1) = 88; a(0, 2) = 77;
  614. a(1, 0) = 66; a(1, 1) = 55; a(1, 2) = 44;
  615. std::copy(a.begin(), a.end(), std::ostream_iterator<double>(cout, " ")); cout << endl;
  616. tr.test(std::equal(check, check+6, a.begin()));
  617. }
  618. }
  619. tr.section("construct from shape");
  620. {
  621. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  622. std::iota(a.begin(), a.end(), 0);
  623. auto sa = ra::shape(a);
  624. tr.test_eq(3, sa[0]);
  625. tr.test_eq(2, sa[1]);
  626. tr.test_eq(4, sa[2]);
  627. tr.test_eq(3, ra::shape(a, 0));
  628. tr.test_eq(2, ra::shape(a, 1));
  629. tr.test_eq(4, ra::shape(a, 2));
  630. double check[24];
  631. std::iota(check, check+24, 0);
  632. tr.test(std::equal(check, check+24, a.begin()));
  633. }
  634. tr.section("I/O");
  635. {
  636. tr.section("1");
  637. {
  638. ra::Small<double, 3, 2> s { 1, 4, 2, 5, 3, 6 };
  639. double check[6] = { 1, 4, 2, 5, 3, 6 };
  640. CheckArrayIO(tr, s, check);
  641. }
  642. tr.section("2");
  643. {
  644. ra::Small<double, 3> s { 1, 4, 2 };
  645. double check[3] = { 1, 4, 2 };
  646. CheckArrayIO(tr, s, check);
  647. }
  648. tr.section("3");
  649. {
  650. ra::Small<double> s { 77 };
  651. double check[1] = { 77 };
  652. CheckArrayIO(tr, s, check);
  653. }
  654. tr.section("4. View<> can't allocate, so have no istream >>. Check output only.");
  655. {
  656. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  657. ra::View<double, 3> r { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  658. double check[11] = { 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  659. CheckArrayOutput(tr, r, check);
  660. }
  661. tr.section("5");
  662. {
  663. double rpool[6] = { 1, 2, 3, 4, 5, 6 };
  664. ra::View<double, 2> r { {ra::Dim {3, 1}, ra::Dim {2, 3}}, rpool };
  665. double check[8] = { 3, 2, 1, 4, 2, 5, 3, 6 };
  666. CheckArrayOutput(tr, r, check);
  667. }
  668. tr.section("6");
  669. {
  670. double rpool[3] = { 1, 2, 3 };
  671. ra::View<double, 1> r { {ra::Dim {3, 1}}, rpool };
  672. double check[4] = { 3, 1, 2, 3 };
  673. CheckArrayOutput(tr, r, check);
  674. }
  675. tr.section("7");
  676. {
  677. double rpool[1] = { 88 };
  678. ra::View<double, 0> r { {}, rpool };
  679. double check[1] = { 88 };
  680. CheckArrayOutput(tr, r, check);
  681. tr.test_eq(1, r.size());
  682. // static_assert(sizeof(r)==sizeof(double *), "bad assumption"); [170]
  683. tr.test_eq(88, r);
  684. }
  685. tr.section("8");
  686. {
  687. double rpool[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  688. ra::View<double> a { {ra::Dim {2, 4}, ra::Dim {2, 2}, ra::Dim {2, 1}}, rpool };
  689. double check[12] = { 3, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8 };
  690. CheckArrayOutput(tr, a, check);
  691. // default steps.
  692. ra::View<double> b { {2, 2, 2}, rpool };
  693. CheckArrayOutput(tr, b, check);
  694. }
  695. tr.section("9");
  696. {
  697. ra::Unique<double, 3> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  698. std::iota(a.begin(), a.end(), 0);
  699. double check[3+24] = { 3, 2, 4 };
  700. std::iota(check+3, check+3+24, 0);
  701. CheckArrayIO(tr, a, check);
  702. }
  703. tr.section("10");
  704. {
  705. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  706. std::iota(a.begin(), a.end(), 0);
  707. double check[4+24] = { 3, 3, 2, 4 };
  708. std::iota(check+4, check+4+24, 0);
  709. CheckArrayIO(tr, a, check);
  710. }
  711. }
  712. tr.section("ply - xpr types - Scalar");
  713. {
  714. {
  715. auto s = ra::scalar(7);
  716. cout << "s: " << s.c << endl;
  717. }
  718. {
  719. auto s = ra::scalar(ra::Small<int, 2> {11, 12});
  720. cout << "s: " << s.c << endl;
  721. }
  722. {
  723. ra::Unique<double> a(std::vector<ra::dim_t> {3, 2, 4}, ra::none);
  724. std::iota(a.begin(), a.end(), 0);
  725. auto s = ra::scalar(a);
  726. cout << "s: " << s.c << endl;
  727. }
  728. }
  729. tr.section("scalar as reference");
  730. {
  731. int a = 3;
  732. ra::scalar(a) += ra::Small<int, 3> {4, 5, 6};
  733. tr.test_eq(18, a);
  734. // beware: throws away 3+4,3+5, only 3+6 is left. [ma107]
  735. ra::scalar(a) = 3 + ra::Small<int, 3> {4, 5, 6};
  736. tr.test_eq(9, a);
  737. }
  738. tr.section("can use pointer-to-member in expressions");
  739. {
  740. struct A { int a, b; };
  741. std::vector<A> v = {{1, 2}, {3, 4}};
  742. tr.test_eq(4, sum(ra::map(&A::a, v)));
  743. tr.test_eq(6, sum(ra::map(&A::b, v)));
  744. ra::map(&A::a, v) = -ra::map(&A::b, v);
  745. tr.test_eq(-2, v[0].a);
  746. tr.test_eq(-4, v[1].a);
  747. }
  748. return tr.summary();
  749. }