test-compatibility.C 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // (c) Daniel Llorens - 2014, 2017
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file test-compatibility.C
  7. /// @brief Using std:: and ra:: together.
  8. #include <iostream>
  9. #include "ra/test.H"
  10. #include "ra/big.H"
  11. #include "ra/operators.H"
  12. #include "ra/io.H"
  13. #include "ra/mpdebug.H"
  14. using std::cout; using std::endl; using std::flush;
  15. int main()
  16. {
  17. TestRecorder tr;
  18. tr.section("Tests for std:: types");
  19. {
  20. tr.section("ra::start() on vector types");
  21. {
  22. auto ref = std::array<int, 4> {{12, 77, 44, 1}};
  23. tr.test_eq(2, expr([](int i) { return i; },
  24. ra::start(std::vector<int> {1, 2, 3})).at(ra::Small<int, 1>{1}));
  25. tr.test_eq(ra::start(ref), expr([](int i) { return i; }, ra::start(std::array<int, 4> {{12, 77, 44, 1}})));
  26. // [a1] these require ra::start and ra::Expr to forward in the constructor (only on linux gcc-5.2,
  27. // weirdly). Clue of why is in the ra::Unique case below.
  28. tr.test_eq(ra::start(ref), expr([](int i) { return i; }, ra::start(ra::Big<int, 1> {12, 77, 44, 1})));
  29. tr.test_eq(ra::start(ref), expr([](int i) { return i; }, ra::start(std::vector<int> {12, 77, 44, 1})));
  30. // these require ra::start and ra::Expr constructors to forward (otherwise CTE), but this makes
  31. // sense, as argname is otherwise always an lref.
  32. ply_ravel(expr([](int i) { std::cout << "Bi: " << i << std::endl; return i; },
  33. ra::start(ra::Unique<int, 1> {12, 77, 44, 1})));
  34. // BUG This still gives a CTE (ra::start for ra::vector does work --that uses Unique<>.iter())
  35. // because info(A && a) { start(a) <- makes a copy of a: Expr, which copies its internal tuple,
  36. // which has a value (not ref) Unique. }.
  37. // Fix could be to make start(is_iterator) true forward, but that doesn't work for Iota, etc. (see test-optimize.C).
  38. // tr.test_eq(ra::vector(ref), expr([](int i) { return i; }, ra::vector(ra::Unique<int, 1> {12, 77, 44, 1})));
  39. }
  40. tr.section("frame match ra::start on 1st axis");
  41. {
  42. std::vector<int> const a = { 1, 2, 3 };
  43. ra::Big<int, 2> b ({3, 2}, ra::start(a));
  44. tr.test_eq(a[0], b(0));
  45. tr.test_eq(a[1], b(1));
  46. tr.test_eq(a[2], b(2));
  47. }
  48. // TODO actually whether unroll is avoided depends on ply, have a way to require it.
  49. // Cf [tr0-01] in test-ra-0.C.
  50. tr.section("[trc01] frame match ra::start on 1st axis, forbid unroll");
  51. {
  52. std::vector<int> const a = { 1, 2, 3 };
  53. ra::Big<int, 3> b ({3, 4, 2}, ra::unspecified);
  54. transpose({0, 2, 1}, b) = ra::start(a);
  55. tr.test_eq(a[0], b(0));
  56. tr.test_eq(a[1], b(1));
  57. tr.test_eq(a[2], b(2));
  58. }
  59. tr.section("frame match ra::start on some axis other than 1st");
  60. {
  61. {
  62. ra::Big<int, 1> const a = { 10, 20, 30 };
  63. ra::Big<int, 1> const b = { 1, 2 };
  64. ra::Big<int, 2> c = map(ra::wrank<0, 1>([](int a, int b) { return a + b; }), a, b);
  65. tr.test_eq(ra::Big<int, 2>({3, 2}, {11, 12, 21, 22, 31, 32}), c);
  66. }
  67. {
  68. std::vector<int> const a = { 10, 20, 30 };
  69. std::vector<int> const b = { 1, 2 };
  70. ra::Big<int, 2> c = map(ra::wrank<0, 1>([](int a, int b) { return a + b; }), a, b);
  71. tr.test_eq(ra::Big<int, 2>({3, 2}, {11, 12, 21, 22, 31, 32}), c);
  72. }
  73. }
  74. tr.section("= operators on ra::start");
  75. {
  76. std::vector<int> a { 1, 2, 3 };
  77. ra::start(a) *= 3;
  78. tr.test_eq(ra::start(std::vector<int> { 3, 6, 9 }), ra::start(a));
  79. }
  80. tr.section("automatic conversion of foreign vectors in mixed ops");
  81. {
  82. std::vector<int> a { 1, 2, 3 };
  83. ra::Big<int, 1> b { 10, 20, 30 };
  84. tr.test_eq(ra::start({11, 22, 33}), a+b);
  85. }
  86. }
  87. tr.section("builtin arrays as foreign arrays");
  88. {
  89. int const a[] = {1, 2, 3};
  90. tr.info("builtin array is enough to drive").test_eq(ra::start({1, 3, 5}), (ra::_0 + a));
  91. int const b[][3] = {{1, 2, 3}, {4, 5, 6}};
  92. tr.info("builtin array handles 2 dimensions").test_eq(ra::Small<int, 2, 3>{1, 1, 1, 5, 5, 5}, (ra::_0 + b - ra::_1));
  93. int const c[2][2][2][2] = {{{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}}, {{{8, 9}, {10, 11}}, {{12, 13}, {14, 15}}}};
  94. tr.info("builtin array handles 4 dimensions").test_eq(ra::Small<int, 2, 2, 2, 2>(ra::_0*8 + ra::_1*4 + ra::_2*2 + ra::_3), c);
  95. // ra::start(c) = 99; // FIXME test that this fails at ct.
  96. }
  97. tr.section("operators take foreign types");
  98. {
  99. std::vector<int> x = {1, 2, 3};
  100. tr.test_eq(6, sum(ra::start(x)));
  101. tr.test_eq(6, ra::sum(x));
  102. }
  103. tr.section("spot use of scalar");
  104. {
  105. struct W { int x; };
  106. ra::Big<W, 1> w = { {1}, {2} };
  107. tr.test_eq(ra::start({8, 9}), map([](auto && a, auto && b) { return a.x + b.x; }, w, ra::scalar(W {7})));
  108. }
  109. {
  110. int o[4];
  111. using O = decltype(o);
  112. O p[2];
  113. int q[2][4];
  114. cout << mp::type_name<decltype(o)>() << endl;
  115. cout << mp::type_name<decltype(p)>() << endl;
  116. cout << mp::type_name<decltype(q)>() << endl;
  117. cout << mp::type_name<decltype(ra::start(q))>() << endl;
  118. cout << mp::type_name<std::remove_all_extents_t<decltype(q)>>() << endl;
  119. }
  120. {
  121. int o[2];
  122. int p[3][2];
  123. int q[4][3][2];
  124. int r[][2] = {{1, 2}, {3, 4}};
  125. static_assert(std::is_same<ra::builtin_array_sizes_t<decltype(o)>,
  126. mp::int_list<2>>::value);
  127. static_assert(std::is_same<ra::builtin_array_sizes_t<decltype(p)>,
  128. mp::int_list<3, 2>>::value);
  129. static_assert(std::is_same<ra::builtin_array_sizes_t<decltype(q)>,
  130. mp::int_list<4, 3, 2>>::value);
  131. static_assert(std::is_same<ra::builtin_array_sizes_t<decltype(r)>,
  132. mp::int_list<2, 2>>::value);
  133. static_assert(std::rank<decltype(r)>::value==2);
  134. }
  135. tr.section("example from the manual [ma106]");
  136. {
  137. int p[] = {1, 2, 3};
  138. int * z = p;
  139. ra::Big<int, 1> q {1, 2, 3};
  140. q += p; // ok, q is ra::, p is foreign object with size info
  141. tr.test_eq(ra::start({2, 4, 6}), q);
  142. ra::start(p) += q; // can't redefine operator+=(int[]), foreign needs ra::start()
  143. tr.test_eq(ra::start({3, 6, 9}), p);
  144. // z += q; // error: raw pointer needs ra::ptr()
  145. ra::ptr(z) += p; // ok, size is determined by foreign object p
  146. tr.test_eq(ra::start({6, 12, 18}), p);
  147. }
  148. return tr.summary();
  149. }