io.C 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file io.C
  3. /// @brief IO checks for ra::.
  4. // (c) Daniel Llorens - 2013-2014
  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 "ra/io.H"
  12. #include "ra/operators.H"
  13. #include "ra/complex.H"
  14. #include "ra/test.H"
  15. #include "ra/view-ops.H"
  16. #include "test/old.H"
  17. using std::cout, std::endl, std::flush;
  18. template <int i> using TI = ra::TensorIndex<i>;
  19. using int3 = ra::Small<int, 3>;
  20. using int2 = ra::Small<int, 2>;
  21. // TestRecorder wants its args to be array elements.
  22. namespace ra { template <> constexpr bool is_scalar_def<std::string> = true; }
  23. template <class AA, class CC>
  24. void iocheck(TestRecorder & tr, AA && a, CC && check)
  25. {
  26. std::ostringstream o;
  27. o << a;
  28. cout << "\nwritten: " << o.str() << endl;
  29. std::istringstream i(o.str());
  30. std::decay_t<CC> c;
  31. i >> c;
  32. cout << "\nread: " << c << endl;
  33. // TODO start() outside b/c where(bool, vector, vector) not handled. ra::where(bool, scalar, scalar) should work at least.
  34. // TODO specific check in TestRecorder
  35. tr.test_eq(ra::start(shape(check)), ra::start(shape(c)));
  36. tr.test_eq(check, c);
  37. }
  38. int main()
  39. {
  40. TestRecorder tr;
  41. tr.section("IO format parameters against default (I)");
  42. {
  43. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  44. std::ostringstream o;
  45. o << ra::withshape << format_array(A, "|", "-");
  46. tr.test_eq(std::string("2 2\n1|2-3|4"), o.str());
  47. }
  48. tr.section("IO format parameters against default (II)");
  49. {
  50. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  51. std::ostringstream o;
  52. o << ra::noshape << format_array(A, "|", "-");
  53. tr.test_eq(std::string("1|2-3|4"), o.str());
  54. }
  55. tr.section("IO manip without FormatArray");
  56. {
  57. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  58. std::ostringstream o;
  59. o << ra::withshape << A;
  60. tr.test_eq(std::string("2 2\n1 2\n3 4"), o.str());
  61. }
  62. tr.section("IO manip without FormatArray");
  63. {
  64. ra::Big<int, 2> A({2, 2}, {1, 2, 3, 4});
  65. std::ostringstream o;
  66. o << ra::noshape << A;
  67. tr.test_eq(std::string("1 2\n3 4"), o.str());
  68. }
  69. tr.section("common arrays or slices");
  70. {
  71. ra::Unique<int, 2> a({5, 3}, ra::_0 - ra::_1);
  72. ra::Unique<int, 2> ref({5, 3}, a); // TODO how about an explicit copy() function?
  73. iocheck(tr.info("output of Unique (1)"), a, ref);
  74. iocheck(tr.info("output of Unique (1)"), a, ref);
  75. }
  76. tr.section("[ra02a] printing Expr");
  77. {
  78. iocheck(tr.info("output of expr (1)"),
  79. ra::expr([](double i) { return -i; }, start(ra::Small<double, 3>{0, 1, 2})),
  80. ra::Small<double, 3>{0, -1, -2});
  81. iocheck(tr.info("output of expr (2)"),
  82. ra::expr([](double i) { return -i; }, start(ra::Small<double, 3, 2, 3> (ra::_0 - ra::_1 + ra::_2))),
  83. (ra::Small<double, 3, 2, 3> (-(ra::_0 - ra::_1 + ra::_2))));
  84. }
  85. {
  86. ra::Unique<int, 2> a({2, 3}, { 1, 2, 3, 4, 5, 6 });
  87. iocheck(tr.info("output of expr (3)"),
  88. ra::expr([](int i) { return -i; }, a.iter()),
  89. ra::Unique<int, 2>({2, 3}, { -1, -2, -3, -4, -5, -6 }));
  90. }
  91. tr.section("[ra02b] printing array iterators");
  92. {
  93. ra::Unique<int, 2> a({3, 2}, { 1, 2, 3, 4, 5, 6 });
  94. iocheck(tr.info("output of array through its iterator"), a.iter(), a);
  95. // note that transpose({1, 0}, ...) will have dynamic rank, so the type expected from read must also.
  96. iocheck(tr.info("output of transposed array through its iterator"),
  97. transpose({1, 0}, a).iter(),
  98. ra::Unique<int>({2, 3}, { 1, 3, 5, 2, 4, 6 }));
  99. }
  100. tr.section("[ra02c] printing array iterators");
  101. {
  102. ra::Small<int, 3, 2> a { 1, 2, 3, 4, 5, 6 };
  103. iocheck(tr.info("output of array through its iterator"), a.iter(), a);
  104. iocheck(tr.info("output of transposed array through its iterator"),
  105. transpose<1, 0>(a).iter(),
  106. ra::Small<int, 2, 3> { 1, 3, 5, 2, 4, 6 });
  107. }
  108. tr.section("IO can handle tensorindex, too");
  109. {
  110. iocheck(tr.info("output of expr (1)"),
  111. ra::expr([](double i, auto j) { return -i*double(j); }, ra::Small<double, 3>{0, 1, 2}.iter(), TI<0>()),
  112. ra::Small<double, 3>{0, -1, -4});
  113. }
  114. tr.section("IO works with old OldTensorIndex (uses ply_index-like traversal)");
  115. {
  116. iocheck(tr.info("output of expr (1)"),
  117. ra::expr([](double i, auto j) { return -i*double(j); }, ra::Small<double, 3>{0, 1, 2}.iter(), ra::OldTensorIndex<0>()),
  118. ra::Small<double, 3>{0, -1, -4});
  119. }
  120. tr.section("IO of var rank expression");
  121. {
  122. ra::Small<int, 2, 2> A {1, 2, 3, 4};
  123. ra::Unique<int> B({2, 2}, {1, 2, 3, 4});
  124. iocheck(tr.info("var rank expr"), A+B, ra::Unique<int>({2, 2}, { 2, 4, 6, 8 }));
  125. }
  126. tr.section("IO of nested type");
  127. {
  128. ra::Small<ra::Big<double, 1>, 3> g = { { 1 }, { 1, 2 }, { 1, 2, 3 } };
  129. iocheck(tr.info("nested type"), g, g);
  130. }
  131. return tr.summary();
  132. }