explode-0.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file explode-0.cc
  3. /// @brief Tests for explode() and collapse().
  4. // (c) Daniel Llorens - 2013-2016
  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 <numeric>
  10. #include <iostream>
  11. #include <iterator>
  12. #include "ra/test.hh"
  13. #include "mpdebug.hh"
  14. using std::cout, std::endl, std::flush, ra::TestRecorder;
  15. using real = double;
  16. using complex = std::complex<double>;
  17. using ra::real_part, ra::imag_part;
  18. int main()
  19. {
  20. TestRecorder tr(std::cout);
  21. tr.section("explode");
  22. {
  23. ra::Big<int, 2> A({2, 3}, ra::_0 - ra::_1);
  24. auto B = ra::explode<ra::Small<int, 3>>(A);
  25. tr.test_eq(3, ra::size_s<decltype(B(0))>());
  26. tr.test_eq(ra::Small<int, 3> {0, -1, -2}, B(0));
  27. tr.test_eq(ra::Small<int, 3> {1, 0, -1}, B(1));
  28. B(1) = 9;
  29. tr.test_eq(ra::Small<int, 3> {0, -1, -2}, B(0));
  30. tr.test_eq(ra::Small<int, 3> {9, 9, 9}, B(1));
  31. }
  32. // note that dynamic-rank operator() returns a rank 0 array (since the rank
  33. // cannot be known at compile time). So we have to peel that back.
  34. {
  35. ra::Big<int> A({2, 3}, ra::_0 - ra::_1);
  36. auto B = ra::explode<ra::Small<int, 3>>(A);
  37. tr.test_eq(3, ra::size_s<decltype(*(B(0).data()))>());
  38. tr.test_eq(ra::scalar(ra::Small<int, 3> {0, -1, -2}), B(0));
  39. tr.test_eq(ra::scalar(ra::Small<int, 3> {1, 0, -1}), B(1));
  40. B(1) = 9;
  41. tr.test_eq(ra::scalar(ra::Small<int, 3> {0, -1, -2}), B(0));
  42. tr.test_eq(ra::scalar(ra::Small<int, 3> {9, 9, 9}), B(1));
  43. }
  44. tr.section("explode<complex>");
  45. {
  46. ra::Big<real, 3> A({2, 3, 2}, ra::_0 - ra::_1 + ra::_2);
  47. auto B = ra::explode<complex>(A);
  48. tr.test_eq(2, B.rank());
  49. tr.test_eq(ra::Small<real, 2, 3> {0, -1, -2, 1, 0, -1}, real_part(B));
  50. tr.test_eq(ra::Small<real, 2, 3> {1, 0, -1, 2, 1, 0}, imag_part(B));
  51. imag_part(B(1)) = 9;
  52. tr.test_eq(ra::Small<real, 2, 3> {0, -1, -2, 1, 0, -1}, A(ra::all, ra::all, 0));
  53. tr.test_eq(ra::Small<real, 2, 3> {1, 0, -1, 9, 9, 9}, A(ra::all, ra::all, 1));
  54. }
  55. {
  56. ra::Big<real> A({2, 3, 2}, ra::_0 - ra::_1 + ra::_2);
  57. auto B = ra::explode<complex>(A);
  58. tr.test_eq(2, B.rank());
  59. tr.test_eq(ra::Small<real, 2, 3> {0, -1, -2, 1, 0, -1}, real_part(B));
  60. tr.test_eq(ra::Small<real, 2, 3> {1, 0, -1, 2, 1, 0}, imag_part(B));
  61. imag_part(B(1)) = 9;
  62. tr.test_eq(ra::Small<real, 2, 3> {0, -1, -2, 1, 0, -1}, A(ra::all, ra::all, 0));
  63. tr.test_eq(ra::Small<real, 2, 3> {1, 0, -1, 9, 9, 9}, A(ra::all, ra::all, 1));
  64. }
  65. tr.section("collapse");
  66. {
  67. tr.section("sub is real to super complex");
  68. {
  69. auto test_sub_real = [&tr](auto && A)
  70. {
  71. A = ra::cast<double>(ra::_0)*complex(4, 1) + ra::cast<double>(ra::_1)*complex(1, 4);
  72. auto B = ra::collapse<double>(A);
  73. tr.test_eq(real_part(A), B(ra::all, ra::all, 0));
  74. tr.test_eq(imag_part(A), B(ra::all, ra::all, 1));
  75. };
  76. test_sub_real(ra::Unique<complex, 2>({4, 4}, ra::none));
  77. test_sub_real(ra::Unique<complex>({4, 4}, ra::none));
  78. }
  79. tr.section("sub is int to super Small of rank 1");
  80. {
  81. using r2 = ra::Small<int, 2>;
  82. auto test_sub_small2 = [&tr](auto && A)
  83. {
  84. A = map([](int i, int j) { return r2 {i+j, i-j}; }, ra::_0, ra::_1);
  85. auto B = ra::collapse<int>(A);
  86. tr.test_eq(B(ra::all, ra::all, 0), map([](auto && a) { return a(0); }, A));
  87. tr.test_eq(B(ra::all, ra::all, 1), map([](auto && a) { return a(1); }, A));
  88. };
  89. test_sub_small2(ra::Unique<r2, 2>({4, 4}, ra::none));
  90. test_sub_small2(ra::Unique<r2>({4, 4}, ra::none));
  91. }
  92. tr.section("sub is int to super Small of rank 2");
  93. {
  94. using super = ra::Small<int, 2, 3>;
  95. auto test_sub_small23 = [&tr](auto && A)
  96. {
  97. A = map([](int i, int j) { return super(i-j+ra::_0-ra::_1); }, ra::_0, ra::_1);
  98. auto B = ra::collapse<int>(A);
  99. for (int i=0; i<super::len(0); ++i) {
  100. for (int j=0; j<super::len(1); ++j) {
  101. tr.test_eq(B(ra::all, ra::all, i, j), map([i, j](auto && a) { return a(i, j); }, A));
  102. }
  103. }
  104. };
  105. test_sub_small23(ra::Unique<super, 2>({2, 2}, ra::none));
  106. test_sub_small23(ra::Unique<super>({2, 2}, ra::none));
  107. }
  108. tr.section("sub is Small of rank 1 to super Small of rank 2");
  109. {
  110. using super = ra::Small<int, 2, 3>;
  111. auto test_sub_small23 = [&tr](auto && A)
  112. {
  113. A = map([](int i, int j) { return super(i-j+ra::_0-ra::_1); }, ra::_0, ra::_1);
  114. using sub = ra::Small<int, 3>;
  115. auto B = ra::collapse<sub>(A);
  116. // TODO sub() is used to cover a problem with where() and SmallView/SmallArray, since they convert to each other
  117. tr.test_eq(B(ra::all, ra::all, 0), map([](auto && a) { return sub(a(0)); }, A));
  118. tr.test_eq(B(ra::all, ra::all, 1), map([](auto && a) { return sub(a(1)); }, A));
  119. };
  120. test_sub_small23(ra::Unique<super, 2>({2, 2}, ra::none));
  121. test_sub_small23(ra::Unique<super>({2, 2}, ra::none));
  122. }
  123. tr.section("sub is real to super complex Small of rank 2");
  124. {
  125. using super = ra::Small<complex, 2, 2>;
  126. auto test_sub_real = [&tr](auto && A)
  127. {
  128. A = map([](complex a) { return super { a, conj(a), -conj(a), -a }; },
  129. ra::cast<double>(ra::_0)*complex(4, 1) + ra::cast<double>(ra::_1)*complex(1, 4));
  130. auto B = ra::collapse<double>(A);
  131. for (int i=0; i<super::len(0); ++i) {
  132. for (int j=0; j<super::len(1); ++j) {
  133. tr.test_eq(B(ra::all, ra::all, i, j, 0), map([i, j](auto && a) { return real_part(a(i, j)); }, A));
  134. tr.test_eq(B(ra::all, ra::all, i, j, 1), map([i, j](auto && a) { return imag_part(a(i, j)); }, A));
  135. }
  136. }
  137. };
  138. test_sub_real(ra::Unique<super, 2>({4, 4}, ra::none));
  139. test_sub_real(ra::Unique<super>({4, 4}, ra::none));
  140. }
  141. }
  142. tr.section("old tests");
  143. {
  144. tr.section("super rank 1");
  145. {
  146. auto test = [&tr](auto && A)
  147. {
  148. using T = ra::Small<double, 2>;
  149. auto B = ra::explode<T>(A);
  150. for (int i=0; i<3; ++i) {
  151. tr.test_eq(i*2, ((T &)(B(i)))(0));
  152. tr.test_eq(i*2+1, ((T &)(B(i)))(1));
  153. }
  154. };
  155. test(ra::Unique<double, 2>({4, 2}, ra::_0*2 + ra::_1));
  156. test(ra::Unique<double>({4, 2}, ra::_0*2 + ra::_1));
  157. }
  158. tr.section("super rank 0");
  159. {
  160. #define TEST(CHECK_RANK_S) \
  161. [&tr](auto && A) \
  162. { \
  163. using T = complex; \
  164. auto convtest = [](T & x) -> T & { return x; }; \
  165. auto B = ra::explode_<T, 1>(A); \
  166. static_assert(rank_s(B)==CHECK_RANK_S, "bad static rank"); \
  167. cout << B << endl; \
  168. for (int i=0; i<3; ++i) { \
  169. tr.test_eq(i*2, real_part((T &)(B(i)))); \
  170. tr.test_eq(i*2+1, imag_part((T &)(B(i)))); \
  171. tr.test_eq(i*2, convtest(B(i)).real()); \
  172. tr.test_eq(i*2+1, convtest(B(i)).imag()); \
  173. } \
  174. }
  175. TEST(ra::ANY)(ra::Unique<double>({4, 2}, ra::_0*2 + ra::_1));
  176. TEST(1)(ra::Unique<double, 2>({4, 2}, ra::_0*2 + ra::_1));
  177. }
  178. tr.section("super rank 2");
  179. {
  180. auto test = [&tr](auto && A)
  181. {
  182. using T = ra::Small<double, 2, 2>;
  183. auto B = ra::explode<T>(A);
  184. tr.test_eq(1, B.rank());
  185. tr.test_eq(T { 0, 1, 2, 3 }, (T &)(B[0]));
  186. tr.test_eq(T { 4, 5, 6, 7 }, (T &)(B[1]));
  187. tr.test_eq(T { 8, 9, 10, 11 }, (T &)(B[2]));
  188. tr.test_eq(T { 12, 13, 14, 15}, (T &)(B[3]));
  189. };
  190. test(ra::Unique<double, 3>({4, 2, 2}, ra::_0*4 + ra::_1*2 + ra::_2));
  191. test(ra::Unique<double>({4, 2, 2}, ra::_0*4 + ra::_1*2 + ra::_2));
  192. }
  193. }
  194. tr.section("explode for Small");
  195. {
  196. ra::Small<double, 2, 3> a(ra::_0 + 10*ra::_1);
  197. auto c = ra::explode<ra::Small<double, 3>>(a);
  198. using lens = std::decay_t<decltype(c)>::lens;
  199. using steps = std::decay_t<decltype(c)>::steps;
  200. tr.info(ra::mp::print_int_list<lens> {}).test(std::is_same_v<ra::mp::int_list<2>, lens>);
  201. tr.info(ra::mp::print_int_list<steps> {}).test(std::is_same_v<ra::mp::int_list<1>, steps>);
  202. tr.test_eq(ra::scalar(a[0].data()), ra::scalar(c[0].data()));
  203. tr.test_eq(ra::scalar(a[1].data()), ra::scalar(c[1].data()));
  204. c[1] = { 3, 2, 1 };
  205. tr.test_eq(ra::Small<double, 3> { 0, 10, 20 }, c[0]);
  206. tr.test_eq(ra::Small<double, 3> { 0, 10, 20 }, a[0]);
  207. tr.test_eq(ra::Small<double, 3> { 3, 2, 1 }, a[1]);
  208. }
  209. return tr.summary();
  210. }