view-ops.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/test - View operations
  3. // (c) Daniel Llorens - 2013-2015, 2019
  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 CheckReverse(TestRecorder & tr, A && a)
  16. {
  17. std::iota(a.begin(), a.end(), 1);
  18. cout << "a: " << a << endl;
  19. auto b0 = reverse(a, 0);
  20. auto c0 = a(ra::iota(ra::len, ra::len-1, -1));
  21. cout << "b: " << b0 << endl;
  22. cout << "c: " << b0 << endl;
  23. double check0[24] = { 17, 18, 19, 20, 21, 22, 23, 24,
  24. 9, 10, 11, 12, 13, 14, 15, 16,
  25. 1, 2, 3, 4, 5, 6, 7, 8 };
  26. tr.test(std::equal(check0, check0+24, b0.begin()));
  27. tr.test_eq(b0, c0);
  28. auto b1 = reverse(a, 1);
  29. auto c1 = a(ra::dots<1>, ra::iota(ra::len, ra::len-1, -1));
  30. cout << "b: " << b1 << endl;
  31. cout << "c: " << c1 << endl;
  32. double check1[24] = { 5, 6, 7, 8, 1, 2, 3, 4,
  33. 13, 14, 15, 16, 9, 10, 11, 12,
  34. 21, 22, 23, 24, 17, 18, 19, 20 };
  35. tr.test(std::equal(check1, check1+24, b1.begin()));
  36. tr.test_eq(b1, c1);
  37. auto b2 = reverse(a, 2);
  38. auto c2 = a(ra::dots<2>, ra::iota(ra::len, ra::len-1, -1));
  39. cout << "b: " << b2 << endl;
  40. cout << "c: " << c2 << endl;
  41. double check2[24] = { 4, 3, 2, 1, 8, 7, 6, 5,
  42. 12, 11, 10, 9, 16, 15, 14, 13,
  43. 20, 19, 18, 17, 24, 23, 22, 21 };
  44. tr.test(std::equal(check2, check2+24, b2.begin()));
  45. tr.test_eq(b2, c2);
  46. }
  47. template <class A>
  48. void CheckTranspose1(TestRecorder & tr, A && a)
  49. {
  50. {
  51. std::iota(a.begin(), a.end(), 1);
  52. cout << "a: " << a << endl;
  53. auto b = transpose(ra::Small<int, 2>{1, 0}, a);
  54. cout << "b: " << b << endl;
  55. double check[6] = {1, 3, 5, 2, 4, 6};
  56. tr.test(std::ranges::equal(b.begin(), b.end(), check, check+6));
  57. }
  58. {
  59. std::iota(a.begin(), a.end(), 1);
  60. cout << "a: " << a << endl;
  61. auto b = transpose<1, 0>(a);
  62. cout << "b: " << b << endl;
  63. double check[6] = {1, 3, 5, 2, 4, 6};
  64. tr.test(std::ranges::equal(b.begin(), b.end(), check, check+6));
  65. }
  66. }
  67. int main()
  68. {
  69. TestRecorder tr(std::cout);
  70. tr.section("reverse array types");
  71. {
  72. CheckReverse(tr, ra::Unique<double>({ 3, 2, 4 }, ra::none));
  73. CheckReverse(tr, ra::Unique<double, 3>({ 3, 2, 4 }, ra::none));
  74. }
  75. tr.section("transpose of 0 rank");
  76. {
  77. {
  78. ra::Unique<double, 0> a({}, 99);
  79. auto b = transpose(ra::Small<int, 0> {}, a);
  80. tr.test_eq(0, b.rank());
  81. tr.test_eq(99, b());
  82. tr.test(is_c_order(a));
  83. tr.test(is_c_order(b));
  84. }
  85. {
  86. ra::Unique<double, 0> a({}, 99);
  87. auto b = transpose(a);
  88. tr.test_eq(0, b.rank());
  89. tr.test_eq(99, b());
  90. }
  91. // FIXME this doesn't work because init_list {} competes with mp::int_list<>.
  92. // {
  93. // ra::Unique<double, 0> a({}, 99);
  94. // auto b = transpose({}, a);
  95. // tr.test_eq(0, b.rank());
  96. // tr.test_eq(99, b());
  97. // }
  98. {
  99. ra::Unique<double, 0> a({}, 99);
  100. auto b = transpose<>(a);
  101. tr.test_eq(0, b.rank());
  102. tr.test_eq(99, b());
  103. }
  104. }
  105. tr.section("transpose A");
  106. {
  107. CheckTranspose1(tr, ra::Unique<double>({ 3, 2 }, ra::none));
  108. CheckTranspose1(tr, ra::Unique<double, 2>({ 3, 2 }, ra::none));
  109. }
  110. tr.section("transpose B");
  111. {
  112. auto transpose_test = [&tr](auto && b)
  113. {
  114. tr.test_eq(1, b.rank());
  115. tr.test_eq(2, b.size());
  116. tr.test_eq(1, b[0]);
  117. tr.test_eq(4, b[1]);
  118. };
  119. ra::Unique<double> a({3, 2}, ra::_0*2 + ra::_1 + 1);
  120. tr.test(is_c_order(a));
  121. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, a)); // dyn rank to dyn rank
  122. transpose_test(transpose<0, 0>(a)); // dyn rank to static rank
  123. ra::Unique<double, 2> b({3, 2}, ra::_0*2 + ra::_1*1 + 1);
  124. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, b)); // static rank to dyn rank
  125. transpose_test(transpose<0, 0>(b)); // static rank to static rank
  126. auto bt = transpose<0, 0>(b);
  127. tr.info("dimv ", bt.dimv, " step ", bt.step(0), " len ", bt.len(0)).test(!is_c_order(bt));
  128. tr.info("dimv ", bt.dimv, " step ", bt.step(0), " len ", bt.len(0)).test(!is_c_order_dimv(bt.dimv));
  129. }
  130. tr.section("transpose C");
  131. {
  132. auto transpose_test = [&tr](auto && b)
  133. {
  134. tr.test_eq(1, b.rank());
  135. tr.test_eq(2, b.size());
  136. tr.test_eq(1, b[0]);
  137. tr.test_eq(5, b[1]);
  138. };
  139. ra::Unique<double> a({2, 3}, ra::_0*3 + ra::_1 + 1);
  140. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, a)); // dyn rank to dyn rank
  141. transpose_test(transpose<0, 0>(a)); // dyn rank to static rank
  142. ra::Unique<double, 2> b({2, 3}, ra::_0*3 + ra::_1 + 1);
  143. transpose_test(transpose(ra::Small<int, 2> { 0, 0 }, b)); // static rank to dyn rank
  144. transpose_test(transpose<0, 0>(b)); // static rank to static rank
  145. }
  146. tr.section("transpose D");
  147. {
  148. auto transpose_test = [&tr](auto && b)
  149. {
  150. tr.test_eq(1, b.rank());
  151. tr.test_eq(2, b.size());
  152. tr.test_eq(1, b[0]);
  153. tr.test_eq(5, b[1]);
  154. };
  155. ra::Unique<double> a({2, 3}, ra::_0*3 + ra::_1 + 1);
  156. transpose_test(transpose({ 0, 0 }, a)); // dyn rank to dyn rank
  157. }
  158. tr.section("transpose E");
  159. {
  160. ra::Unique<double> a({3}, {1, 2, 3});
  161. tr.test_eq(a-a(ra::insert<1>), a-transpose({1}, a));
  162. }
  163. tr.section("transpose F");
  164. {
  165. ra::Unique<double> a({3}, {1, 2, 3});
  166. tr.test_eq(a-a(ra::insert<1>), a-transpose<1>(a));
  167. }
  168. tr.section("transpose G");
  169. {
  170. ra::Unique<double, 1> a({3}, {1, 2, 3});
  171. tr.test_eq(a-a(ra::insert<1>), a-transpose<1>(a));
  172. }
  173. // FIXME Small cannot have BAD sizes yet.
  174. // tr.section("transpose K");
  175. // {
  176. // ra::Small<double, 3> a = {1, 2, 3};
  177. // cout << transpose<1>(a) << endl;
  178. // }
  179. tr.section("transpose Q [ma117]");
  180. {
  181. ra::Small<int, 2> axes = {0, 1};
  182. ra::Unique<double, 2> a = {{1, 2, 3}, {4, 5, 6}};
  183. cout << "A: " << transpose(axes, a) << endl;
  184. axes = {1, 0};
  185. cout << "B: " << transpose(axes, a) << endl;
  186. }
  187. tr.section("free ravel?");
  188. {
  189. ra::Unique<double, 2> a = {{1, 2, 3}, {4, 5, 6}};
  190. tr.test(is_c_order(a, false));
  191. auto b = transpose<1, 0>(a);
  192. tr.test(!is_c_order(b, false));
  193. }
  194. // trailing singleton dimensions
  195. {
  196. ra::Unique<double, 2> a = {{1, 2, 3}, {4, 5, 6}};
  197. ra::View<double, 2> c{{{2, 1}, {1, 3}}, a.data()};
  198. tr.test(is_c_order(c, false));
  199. tr.test_eq(ra::Small<int, 2>{1, 2}, ravel_free(c));
  200. }
  201. // singleton dimensions elsewhere
  202. {
  203. ra::Unique<double, 1> a = ra::iota(30);
  204. ra::View<double, 3> c{{{2, 10}, {1, 8}, {5, 2}}, a.data()};
  205. tr.test(is_c_order(c, false));
  206. tr.test_eq(ra::iota(10, 0, 2), ravel_free(c));
  207. }
  208. return tr.summary();
  209. }