test_operators_arithmetic.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright (c) 2018-2019 Cem Bassoy
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // The authors gratefully acknowledge the support of
  8. // Fraunhofer and Google in producing this work
  9. // which started as a Google Summer of Code project.
  10. //
  11. #include <boost/numeric/ublas/tensor.hpp>
  12. #include <boost/test/unit_test.hpp>
  13. #include <boost/multiprecision/cpp_bin_float.hpp>
  14. #include "utility.hpp"
  15. using double_extended = boost::multiprecision::cpp_bin_float_double_extended;
  16. using test_types = zip<int,long,float,double,double_extended>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
  17. struct fixture
  18. {
  19. using extents_type = boost::numeric::ublas::basic_extents<std::size_t>;
  20. fixture()
  21. : extents{
  22. extents_type{}, // 0
  23. extents_type{1,1}, // 1
  24. extents_type{1,2}, // 2
  25. extents_type{2,1}, // 3
  26. extents_type{2,3}, // 4
  27. extents_type{2,3,1}, // 5
  28. extents_type{4,1,3}, // 6
  29. extents_type{1,2,3}, // 7
  30. extents_type{4,2,3}, // 8
  31. extents_type{4,2,3,5}} // 9
  32. {
  33. }
  34. std::vector<extents_type> extents;
  35. };
  36. BOOST_AUTO_TEST_SUITE(test_tensor_arithmetic_operations, * boost::unit_test::depends_on("test_tensor"))
  37. BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_binary_arithmetic_operations, value, test_types, fixture)
  38. {
  39. using namespace boost::numeric;
  40. using value_type = typename value::first_type;
  41. using layout_type = typename value::second_type;
  42. using tensor_type = ublas::tensor<value_type, layout_type>;
  43. auto check = [](auto const& e)
  44. {
  45. auto t = tensor_type (e);
  46. auto t2 = tensor_type (e);
  47. auto r = tensor_type (e);
  48. auto v = value_type {};
  49. std::iota(t.begin(), t.end(), v);
  50. std::iota(t2.begin(), t2.end(), v+2);
  51. r = t + t + t + t2;
  52. for(auto i = 0ul; i < t.size(); ++i)
  53. BOOST_CHECK_EQUAL ( r(i), 3*t(i) + t2(i) );
  54. r = t2 / (t+3) * (t+1) - t2; // r = ( t2/ ((t+3)*(t+1)) ) - t2
  55. for(auto i = 0ul; i < t.size(); ++i)
  56. BOOST_CHECK_EQUAL ( r(i), t2(i) / (t(i)+3)*(t(i)+1) - t2(i) );
  57. r = 3+t2 / (t+3) * (t+1) * t - t2; // r = 3+( t2/ ((t+3)*(t+1)*t) ) - t2
  58. for(auto i = 0ul; i < t.size(); ++i)
  59. BOOST_CHECK_EQUAL ( r(i), 3+t2(i) / (t(i)+3)*(t(i)+1)*t(i) - t2(i) );
  60. r = t2 - t + t2 - t;
  61. for(auto i = 0ul; i < r.size(); ++i)
  62. BOOST_CHECK_EQUAL ( r(i), 4 );
  63. r = tensor_type (e,1) + tensor_type (e,1);
  64. for(auto i = 0ul; i < r.size(); ++i)
  65. BOOST_CHECK_EQUAL ( r(i), 2 );
  66. r = t * t * t * t2;
  67. for(auto i = 0ul; i < t.size(); ++i)
  68. BOOST_CHECK_EQUAL ( r(i), t(i)*t(i)*t(i)*t2(i) );
  69. r = (t2/t2) * (t2/t2);
  70. for(auto i = 0ul; i < t.size(); ++i)
  71. BOOST_CHECK_EQUAL ( r(i), 1 );
  72. };
  73. for(auto const& e : extents)
  74. check(e);
  75. BOOST_CHECK_NO_THROW ( tensor_type t = tensor_type(extents.at(0)) + tensor_type(extents.at(0)) );
  76. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(0)) + tensor_type(extents.at(2)), std::runtime_error );
  77. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(1)) + tensor_type(extents.at(2)), std::runtime_error );
  78. }
  79. BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_unary_arithmetic_operations, value, test_types, fixture)
  80. {
  81. using namespace boost::numeric;
  82. using value_type = typename value::first_type;
  83. using layout_type = typename value::second_type;
  84. using tensor_type = ublas::tensor<value_type, layout_type>;
  85. auto check = [](auto const& e)
  86. {
  87. auto t = tensor_type (e);
  88. auto t2 = tensor_type (e);
  89. auto v = value_type {};
  90. std::iota(t.begin(), t.end(), v);
  91. std::iota(t2.begin(), t2.end(), v+2);
  92. tensor_type r1 = t + 2 + t + 2;
  93. for(auto i = 0ul; i < t.size(); ++i)
  94. BOOST_CHECK_EQUAL ( r1(i), 2*t(i) + 4 );
  95. tensor_type r2 = 2 + t + 2 + t;
  96. for(auto i = 0ul; i < t.size(); ++i)
  97. BOOST_CHECK_EQUAL ( r2(i), 2*t(i) + 4 );
  98. tensor_type r3 = (t-2) + (t-2);
  99. for(auto i = 0ul; i < t.size(); ++i)
  100. BOOST_CHECK_EQUAL ( r3(i), 2*t(i) - 4 );
  101. tensor_type r4 = (t*2) * (3*t);
  102. for(auto i = 0ul; i < t.size(); ++i)
  103. BOOST_CHECK_EQUAL ( r4(i), 2*3*t(i)*t(i) );
  104. tensor_type r5 = (t2*2) / (2*t2) * t2;
  105. for(auto i = 0ul; i < t.size(); ++i)
  106. BOOST_CHECK_EQUAL ( r5(i), (t2(i)*2) / (2*t2(i)) * t2(i) );
  107. tensor_type r6 = (t2/2+1) / (2/t2+1) / t2;
  108. for(auto i = 0ul; i < t.size(); ++i)
  109. BOOST_CHECK_EQUAL ( r6(i), (t2(i)/2+1) / (2/t2(i)+1) / t2(i) );
  110. };
  111. for(auto const& e : extents)
  112. check(e);
  113. BOOST_CHECK_NO_THROW ( tensor_type t = tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(0)) );
  114. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(2)), std::runtime_error );
  115. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(1)) + 2 + tensor_type(extents.at(2)), std::runtime_error );
  116. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + tensor_type(extents.at(1)), std::runtime_error );
  117. BOOST_CHECK_THROW ( tensor_type t = tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(1)), std::runtime_error );
  118. }
  119. BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_assign_arithmetic_operations, value, test_types, fixture)
  120. {
  121. using namespace boost::numeric;
  122. using value_type = typename value::first_type;
  123. using layout_type = typename value::second_type;
  124. using tensor_type = ublas::tensor<value_type, layout_type>;
  125. auto check = [](auto const& e)
  126. {
  127. auto t = tensor_type (e);
  128. auto t2 = tensor_type (e);
  129. auto r = tensor_type (e);
  130. auto v = value_type {};
  131. std::iota(t.begin(), t.end(), v);
  132. std::iota(t2.begin(), t2.end(), v+2);
  133. r = t + 2;
  134. r += t;
  135. r += 2;
  136. for(auto i = 0ul; i < t.size(); ++i)
  137. BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
  138. r = 2 + t;
  139. r += t;
  140. r += 2;
  141. for(auto i = 0ul; i < t.size(); ++i)
  142. BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
  143. for(auto i = 0ul; i < t.size(); ++i)
  144. BOOST_CHECK_EQUAL ( r(i), 2*t(i) + 4 );
  145. r = (t-2);
  146. r += t;
  147. r -= 2;
  148. for(auto i = 0ul; i < t.size(); ++i)
  149. BOOST_CHECK_EQUAL ( r(i), 2*t(i) - 4 );
  150. r = (t*2);
  151. r *= 3;
  152. r *= t;
  153. for(auto i = 0ul; i < t.size(); ++i)
  154. BOOST_CHECK_EQUAL ( r(i), 2*3*t(i)*t(i) );
  155. r = (t2*2);
  156. r /= 2;
  157. r /= t2;
  158. r *= t2;
  159. for(auto i = 0ul; i < t.size(); ++i)
  160. BOOST_CHECK_EQUAL ( r(i), (t2(i)*2) / (2*t2(i)) * t2(i) );
  161. r = (t2/2+1);
  162. r /= (2/t2+1);
  163. r /= t2;
  164. for(auto i = 0ul; i < t.size(); ++i)
  165. BOOST_CHECK_EQUAL ( r(i), (t2(i)/2+1) / (2/t2(i)+1) / t2(i) );
  166. tensor_type q = -r;
  167. for(auto i = 0ul; i < t.size(); ++i)
  168. BOOST_CHECK_EQUAL ( q(i), -r(i) );
  169. tensor_type p = +r;
  170. for(auto i = 0ul; i < t.size(); ++i)
  171. BOOST_CHECK_EQUAL ( p(i), r(i) );
  172. };
  173. for(auto const& e : extents)
  174. check(e);
  175. auto r = tensor_type (extents.at(0));
  176. BOOST_CHECK_NO_THROW ( r += tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(0)) );
  177. BOOST_CHECK_THROW ( r += tensor_type(extents.at(0)) + 2 + tensor_type(extents.at(2)), std::runtime_error );
  178. BOOST_CHECK_THROW ( r += tensor_type(extents.at(1)) + 2 + tensor_type(extents.at(2)), std::runtime_error );
  179. BOOST_CHECK_THROW ( r += tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + tensor_type(extents.at(1)), std::runtime_error );
  180. BOOST_CHECK_THROW ( r += tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(2)) + 2 + tensor_type(extents.at(1)), std::runtime_error );
  181. }
  182. BOOST_AUTO_TEST_SUITE_END()