io.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - IO, formatting.
  3. // (c) Daniel Llorens - 2013-2024
  4. // This library is free software; you can redistribute it and/or modify it under
  5. // the terms of the GNU Lesser General Public License as published by the Free
  6. // Software Foundation; either version 3 of the License, or (at your option) any
  7. // later version.
  8. #include <iostream>
  9. #include "ra/test.hh"
  10. using std::cout, std::endl, std::flush, ra::TestRecorder;
  11. using int3 = ra::Small<int, 3>;
  12. using int2 = ra::Small<int, 2>;
  13. template <class AA, class CC>
  14. void
  15. iocheck(TestRecorder & tr, AA && a, CC && check)
  16. {
  17. std::ostringstream o;
  18. o << a;
  19. cout << "\nwritten: " << o.str() << endl;
  20. std::istringstream i(o.str());
  21. std::decay_t<CC> c;
  22. i >> c;
  23. cout << "\nread: " << c << endl;
  24. tr.test_eq(shape(check), shape(c));
  25. tr.test_eq(check, c);
  26. }
  27. struct Q
  28. {
  29. int x = 1;
  30. };
  31. std::ostream & operator<<(std::ostream & o, Q && q)
  32. {
  33. return (o << q.x);
  34. }
  35. int main()
  36. {
  37. TestRecorder tr;
  38. tr.section("common arrays or slices");
  39. {
  40. ra::Unique<int, 2> a({5, 3}, ra::_0 - ra::_1);
  41. ra::Unique<int, 2> ref({5, 3}, a); // TODO how about an explicit copy() function?
  42. iocheck(tr.info("output of Unique (1)"), a, ref);
  43. iocheck(tr.info("output of Unique (1)"), a, ref);
  44. }
  45. {
  46. ra::Big<int, 1> a = {1};
  47. ra::Big<int, 1> ref = {1};
  48. iocheck(tr.info("Big of rank 1"), a, ref);
  49. }
  50. tr.section("IO format parameters against default (I)");
  51. {
  52. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  53. std::ostringstream o;
  54. o << ra::withshape << format_array(A, { .sep0="|", .sepn="-" } );
  55. tr.test_eq(std::string("2 2\n1|2-3|4"), o.str());
  56. }
  57. tr.section("IO format parameters against default (II)");
  58. {
  59. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  60. std::ostringstream o;
  61. o << ra::noshape << format_array(A, { .sep0="|", .sepn="-" });
  62. tr.test_eq(std::string("1|2-3|4"), o.str());
  63. }
  64. tr.section("IO format parameters against default (IIb)");
  65. {
  66. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  67. std::ostringstream o;
  68. o << ra::format_t { .shape=ra::noshape, .sep0="|", .sepn="-" } << A;
  69. tr.test_eq(std::string("1|2-3|4"), o.str());
  70. }
  71. tr.section("IO format parameters against default (IIc)");
  72. {
  73. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  74. std::ostringstream o;
  75. o << ra::noshape << ra::format_t { .sep0="|", .sepn="-" } << A;
  76. tr.test_eq(std::string("1|2-3|4"), o.str());
  77. }
  78. tr.section("IO format parameters against default (III)");
  79. {
  80. ra::Big<int, 4> A({2, 2, 2, 2}, ra::_0 + ra::_1 + ra::_2 + ra::_3);
  81. {
  82. std::ostringstream o;
  83. o << "\n" << format_array(A, ra::cstyle) << endl;
  84. tr.test_seq(
  85. R"---(
  86. {{{{0, 1},
  87. {1, 2}},
  88. {{1, 2},
  89. {2, 3}}},
  90. {{{1, 2},
  91. {2, 3}},
  92. {{2, 3},
  93. {3, 4}}}}
  94. )---"
  95. , o.str());
  96. }
  97. {
  98. std::ostringstream o;
  99. auto style = ra::cstyle;
  100. style.shape = ra::withshape;
  101. o << "\n" << style << A << endl;
  102. tr.test_seq(
  103. R"---(
  104. 2 2 2 2
  105. {{{{0, 1},
  106. {1, 2}},
  107. {{1, 2},
  108. {2, 3}}},
  109. {{{1, 2},
  110. {2, 3}},
  111. {{2, 3},
  112. {3, 4}}}}
  113. )---"
  114. , o.str());
  115. }
  116. {
  117. std::ostringstream o;
  118. o << "\n" << format_array(A, ra::jstyle) << endl;
  119. tr.test_seq(
  120. R"---(
  121. 2 2 2 2
  122. 0 1
  123. 1 2
  124. 1 2
  125. 2 3
  126. 1 2
  127. 2 3
  128. 2 3
  129. 3 4
  130. )---"
  131. , o.str());
  132. }
  133. {
  134. std::ostringstream o;
  135. o << "\n" << format_array(A, ra::lstyle) << endl;
  136. tr.test_seq(
  137. R"---(
  138. ((((0 1)
  139. (1 2))
  140. ((1 2)
  141. (2 3)))
  142. (((1 2)
  143. (2 3))
  144. ((2 3)
  145. (3 4))))
  146. )---"
  147. , o.str());
  148. }
  149. {
  150. std::ostringstream o;
  151. auto style = ra::lstyle;
  152. style.align = false;
  153. o << "\n" << format_array(A, style) << endl;
  154. tr.test_seq(
  155. R"---(
  156. ((((0 1)
  157. (1 2))
  158. ((1 2)
  159. (2 3)))
  160. (((1 2)
  161. (2 3))
  162. ((2 3)
  163. (3 4))))
  164. )---"
  165. , o.str());
  166. }
  167. {
  168. std::ostringstream o;
  169. o << "\n" << format_array(A, ra::pstyle) << endl;
  170. tr.test_seq(
  171. R"---(
  172. [[[[0, 1],
  173. [1, 2]],
  174. [[1, 2],
  175. [2, 3]]],
  176. [[[1, 2],
  177. [2, 3]],
  178. [[2, 3],
  179. [3, 4]]]]
  180. )---"
  181. , o.str());
  182. }
  183. }
  184. tr.section("IO manip without FormatArray");
  185. {
  186. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  187. std::ostringstream o;
  188. o << ra::withshape << A;
  189. tr.test_eq(std::string("2 2\n1 2\n3 4"), o.str());
  190. }
  191. tr.section("IO manip without FormatArray");
  192. {
  193. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  194. std::ostringstream o;
  195. o << ra::noshape << A;
  196. tr.test_eq(std::string("1 2\n3 4"), o.str());
  197. }
  198. tr.section("[ra02a] printing Expr");
  199. {
  200. iocheck(tr.info("output of expr (1)"),
  201. ra::expr([](double i) { return -i; }, start(ra::Small<double, 3>{0, 1, 2})),
  202. ra::Small<double, 3>{0, -1, -2});
  203. iocheck(tr.info("output of expr (2)"),
  204. ra::expr([](double i) { return -i; }, start(ra::Small<double, 3, 2, 3> (ra::_0 - ra::_1 + ra::_2))),
  205. (ra::Small<double, 3, 2, 3> (-(ra::_0 - ra::_1 + ra::_2))));
  206. }
  207. {
  208. ra::Unique<int, 2> a({2, 3}, { 1, 2, 3, 4, 5, 6 });
  209. iocheck(tr.info("output of expr (3)"),
  210. ra::expr([](int i) { return -i; }, a.iter()),
  211. ra::Unique<int, 2>({2, 3}, { -1, -2, -3, -4, -5, -6 }));
  212. }
  213. tr.section("[ra02b] printing array iterators");
  214. {
  215. ra::Unique<int, 2> a({3, 2}, { 1, 2, 3, 4, 5, 6 });
  216. iocheck(tr.info("output of array through its iterator"), a.iter(), a);
  217. // note that transpose({1, 0}, ...) will have dynamic rank, so the type expected from read must also.
  218. iocheck(tr.info("output of transposed array through its iterator"),
  219. transpose({1, 0}, a).iter(),
  220. ra::Unique<int>({2, 3}, { 1, 3, 5, 2, 4, 6 }));
  221. }
  222. tr.section("[ra02c] printing array iterators");
  223. {
  224. ra::Small<int, 3, 2> a { 1, 2, 3, 4, 5, 6 };
  225. iocheck(tr.info("output of array through its iterator"), a.iter(), a);
  226. iocheck(tr.info("output of transposed array through its iterator"),
  227. transpose<1, 0>(a).iter(),
  228. ra::Small<int, 2, 3> { 1, 3, 5, 2, 4, 6 });
  229. }
  230. tr.section("IO can handle undef len iota, too");
  231. {
  232. iocheck(tr.info("output of expr (1)"),
  233. ra::expr([](double i, auto j) { return -i*double(j); }, ra::Small<double, 3>{0, 1, 2}.iter(), ra::iota<0>()),
  234. ra::Small<double, 3>{0, -1, -4});
  235. }
  236. tr.section("IO of var rank expression");
  237. {
  238. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  239. ra::Unique<int> B({2, 2}, {1, 2, 3, 4});
  240. iocheck(tr.info("var rank expr"), A+B, ra::Unique<int>({2, 2}, { 2, 4, 6, 8 }));
  241. }
  242. tr.section("IO of nested type");
  243. {
  244. ra::Small<ra::Big<double, 1>, 3> g = { { 1 }, { 1, 2 }, { 1, 2, 3 } };
  245. iocheck(tr.info("nested type"), g, g);
  246. }
  247. // this behavior depends on [ra13] (std::string is scalar) and the specializations of ostream<< in ply.hh.
  248. tr.section("Non-ra types in format()");
  249. {
  250. std::ostringstream o;
  251. o << ra::format(std::string("once"), " ", std::array {1, 2, 3});
  252. tr.info(o.str()).test_eq(std::string("once 1 2 3"), o.str());
  253. }
  254. tr.section("regression against lack of forwarding in ra::format(...)");
  255. {
  256. std::ostringstream o;
  257. o << ra::format(Q { 33 });
  258. tr.test_eq(std::string("33"), o.str());
  259. }
  260. tr.section("empty array");
  261. {
  262. ra::Big<int, 1> pick;
  263. std::ostringstream o;
  264. o << format_array(pick, ra::cstyle);
  265. tr.test_eq(std::string("{}"), o.str());
  266. }
  267. tr.section("rank 0");
  268. {
  269. ra::Big<int, 0> pick = 7;
  270. std::ostringstream o;
  271. o << format_array(pick);
  272. tr.test_eq(std::string("7"), o.str());
  273. }
  274. return tr.summary();
  275. }