constexpr_arithmetric_test.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // (C) Copyright John Maddock 2019.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include <boost/config.hpp>
  6. #include <boost/multiprecision/number.hpp>
  7. #include <limits>
  8. // clang-format off
  9. template <class T, class U>
  10. BOOST_CXX14_CONSTEXPR T do_test_constexpr_add_subtract(T a, U b)
  11. {
  12. a = +b;
  13. if constexpr(std::numeric_limits<U>::is_signed && std::numeric_limits<T>::is_signed)
  14. b = -b;
  15. a += b;
  16. a += a;
  17. a -= b;
  18. a -= a;
  19. ++a;
  20. --a;
  21. T bb(b);
  22. a += bb++;
  23. a += bb--;
  24. a = a + b;
  25. a += a - b;
  26. if constexpr(std::numeric_limits<U>::is_signed && std::numeric_limits<T>::is_signed)
  27. a -= b - -a;
  28. a += b + a;
  29. if constexpr(std::numeric_limits<T>::is_signed)
  30. {
  31. a = -a;
  32. if constexpr(std::numeric_limits<U>::is_signed)
  33. a -= b;
  34. }
  35. return a;
  36. }
  37. template <class T>
  38. BOOST_CXX14_CONSTEXPR T test_constexpr_add_subtract(T a)
  39. {
  40. a += do_test_constexpr_add_subtract(a, a);
  41. a += do_test_constexpr_add_subtract(a, static_cast<unsigned char>(2));
  42. a += do_test_constexpr_add_subtract(a, static_cast<signed char>(2));
  43. a += do_test_constexpr_add_subtract(a, static_cast<char>(2));
  44. a += do_test_constexpr_add_subtract(a, static_cast<short>(2));
  45. a += do_test_constexpr_add_subtract(a, static_cast<unsigned short>(2));
  46. a += do_test_constexpr_add_subtract(a, static_cast<int>(2));
  47. a += do_test_constexpr_add_subtract(a, static_cast<unsigned int>(2));
  48. a += do_test_constexpr_add_subtract(a, static_cast<long>(2));
  49. a += do_test_constexpr_add_subtract(a, static_cast<unsigned long>(2));
  50. a += do_test_constexpr_add_subtract(a, static_cast<long long>(2));
  51. a += do_test_constexpr_add_subtract(a, static_cast<unsigned long long>(2));
  52. #ifdef BOOST_HAS_INT128
  53. a += do_test_constexpr_add_subtract(a, static_cast<__int128>(2));
  54. a += do_test_constexpr_add_subtract(a, static_cast<unsigned __int128>(2));
  55. a -= do_test_constexpr_add_subtract(a, static_cast<__int128>(2));
  56. a -= do_test_constexpr_add_subtract(a, static_cast<unsigned __int128>(2));
  57. #endif
  58. if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
  59. {
  60. a += do_test_constexpr_add_subtract(a, static_cast<float>(2));
  61. a += do_test_constexpr_add_subtract(a, static_cast<double>(2));
  62. a += do_test_constexpr_add_subtract(a, static_cast<long double>(2));
  63. #ifdef BOOST_HAS_FLOAT128
  64. a += do_test_constexpr_add_subtract(a, static_cast<__float128>(2));
  65. #endif
  66. }
  67. return a;
  68. }
  69. template <class T, class U>
  70. BOOST_CXX14_CONSTEXPR T do_test_constexpr_mul_divide(T a, U b)
  71. {
  72. a *= b;
  73. a = a * b;
  74. if constexpr(std::numeric_limits<T>::is_signed && std::numeric_limits<U>::is_signed)
  75. {
  76. a *= -b;
  77. a = a * -b;
  78. }
  79. a /= b;
  80. a = a / b;
  81. if constexpr(std::numeric_limits<T>::is_signed && std::numeric_limits<U>::is_signed)
  82. {
  83. a /= -b;
  84. a = a / -b;
  85. }
  86. if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_integer && boost::multiprecision::number_category<U>::value == boost::multiprecision::number_kind_integer)
  87. {
  88. a %= b;
  89. a = a % b;
  90. }
  91. return a;
  92. }
  93. template <class T>
  94. BOOST_CXX14_CONSTEXPR T test_constexpr_mul_divide(T a)
  95. {
  96. a += do_test_constexpr_mul_divide(a, a);
  97. a += do_test_constexpr_mul_divide(a, static_cast<unsigned char>(2));
  98. a += do_test_constexpr_mul_divide(a, static_cast<signed char>(2));
  99. a += do_test_constexpr_mul_divide(a, static_cast<char>(2));
  100. a += do_test_constexpr_mul_divide(a, static_cast<short>(2));
  101. a += do_test_constexpr_mul_divide(a, static_cast<unsigned short>(2));
  102. a += do_test_constexpr_mul_divide(a, static_cast<int>(2));
  103. a += do_test_constexpr_mul_divide(a, static_cast<unsigned int>(2));
  104. a += do_test_constexpr_mul_divide(a, static_cast<long>(2));
  105. a += do_test_constexpr_mul_divide(a, static_cast<unsigned long>(2));
  106. a += do_test_constexpr_mul_divide(a, static_cast<long long>(2));
  107. a += do_test_constexpr_mul_divide(a, static_cast<unsigned long long>(2));
  108. #ifdef BOOST_HAS_INT128
  109. a += do_test_constexpr_mul_divide(a, static_cast<__int128>(2));
  110. a += do_test_constexpr_mul_divide(a, static_cast<unsigned __int128>(2));
  111. a -= do_test_constexpr_mul_divide(a, static_cast<__int128>(2));
  112. a -= do_test_constexpr_mul_divide(a, static_cast<unsigned __int128>(2));
  113. #endif
  114. if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
  115. {
  116. a += do_test_constexpr_mul_divide(a, static_cast<float>(2));
  117. a += do_test_constexpr_mul_divide(a, static_cast<double>(2));
  118. a += do_test_constexpr_mul_divide(a, static_cast<long double>(2));
  119. #ifdef BOOST_HAS_FLOAT128
  120. a += do_test_constexpr_mul_divide(a, static_cast<__float128>(2));
  121. #endif
  122. }
  123. return a;
  124. }
  125. template <class T, class U>
  126. BOOST_CXX14_CONSTEXPR T do_test_constexpr_bitwise(T a, U b)
  127. {
  128. a |= b;
  129. a &= b;
  130. a <<= 2;
  131. a ^= b;
  132. a = a | b;
  133. a = a & b;
  134. a <<= 2;
  135. a = a ^ b;
  136. if constexpr (std::numeric_limits<T>::is_signed == false)
  137. {
  138. a = ~a;
  139. a >>= std::numeric_limits<T>::digits - 3;
  140. }
  141. a <<= 5;
  142. a = a << 2;
  143. a >>= 5;
  144. a = a >> 2;
  145. return a;
  146. }
  147. template <class T>
  148. BOOST_CXX14_CONSTEXPR T test_constexpr_bitwise(T a)
  149. {
  150. a += do_test_constexpr_bitwise(a, a);
  151. a += do_test_constexpr_bitwise(a, static_cast<unsigned char>(2));
  152. a += do_test_constexpr_bitwise(a, static_cast<signed char>(2));
  153. a += do_test_constexpr_bitwise(a, static_cast<char>(2));
  154. a += do_test_constexpr_bitwise(a, static_cast<short>(2));
  155. a += do_test_constexpr_bitwise(a, static_cast<unsigned short>(2));
  156. a += do_test_constexpr_bitwise(a, static_cast<int>(2));
  157. a += do_test_constexpr_bitwise(a, static_cast<unsigned int>(2));
  158. a += do_test_constexpr_bitwise(a, static_cast<long>(2));
  159. a += do_test_constexpr_bitwise(a, static_cast<unsigned long>(2));
  160. a += do_test_constexpr_bitwise(a, static_cast<long long>(2));
  161. a += do_test_constexpr_bitwise(a, static_cast<unsigned long long>(2));
  162. #ifdef BOOST_HAS_INT128
  163. a += do_test_constexpr_bitwise(a, static_cast<__int128>(2));
  164. a += do_test_constexpr_bitwise(a, static_cast<unsigned __int128>(2));
  165. #endif
  166. return a;
  167. }
  168. template <class T, class U>
  169. BOOST_CXX14_CONSTEXPR T do_test_constexpr_logical(T a, U b)
  170. {
  171. T result(0);
  172. if(a || b)
  173. ++result;
  174. if(b || a)
  175. ++result;
  176. if(a && b)
  177. ++result;
  178. if(b && a)
  179. ++result;
  180. if(a)
  181. ++result;
  182. if(!a)
  183. ++result;
  184. return result;
  185. }
  186. template <class T>
  187. BOOST_CXX14_CONSTEXPR T test_constexpr_logical(T a)
  188. {
  189. a += do_test_constexpr_logical(a, a);
  190. a += do_test_constexpr_logical(a, static_cast<unsigned char>(2));
  191. a += do_test_constexpr_logical(a, static_cast<signed char>(2));
  192. a += do_test_constexpr_logical(a, static_cast<char>(2));
  193. a += do_test_constexpr_logical(a, static_cast<short>(2));
  194. a += do_test_constexpr_logical(a, static_cast<unsigned short>(2));
  195. a += do_test_constexpr_logical(a, static_cast<int>(2));
  196. a += do_test_constexpr_logical(a, static_cast<unsigned int>(2));
  197. a += do_test_constexpr_logical(a, static_cast<long>(2));
  198. a += do_test_constexpr_logical(a, static_cast<unsigned long>(2));
  199. a += do_test_constexpr_logical(a, static_cast<long long>(2));
  200. a += do_test_constexpr_logical(a, static_cast<unsigned long long>(2));
  201. #ifdef BOOST_HAS_INT128
  202. a += do_test_constexpr_logical(a, static_cast<__int128>(2));
  203. a += do_test_constexpr_logical(a, static_cast<unsigned __int128>(2));
  204. a -= do_test_constexpr_logical(a, static_cast<__int128>(2));
  205. a -= do_test_constexpr_logical(a, static_cast<unsigned __int128>(2));
  206. #endif
  207. return a;
  208. }
  209. template <class T, class U>
  210. BOOST_CXX14_CONSTEXPR T do_test_constexpr_compare(T a, U b)
  211. {
  212. T result(0);
  213. if(a == b)
  214. ++result;
  215. if(b == a)
  216. ++result;
  217. if(a != b)
  218. ++result;
  219. if(b != a)
  220. ++result;
  221. if(a < b)
  222. ++result;
  223. if(b < a)
  224. ++result;
  225. if(a <= b)
  226. ++result;
  227. if(b <= a)
  228. ++result;
  229. if(a > b)
  230. ++result;
  231. if(b > a)
  232. ++result;
  233. if(a >= b)
  234. ++result;
  235. if(b >= a)
  236. ++result;
  237. T u(b);
  238. if(u == a)
  239. ++result;
  240. return result;
  241. }
  242. template <class T>
  243. BOOST_CXX14_CONSTEXPR T test_constexpr_compare(T a)
  244. {
  245. a += do_test_constexpr_compare(a, a);
  246. a += do_test_constexpr_compare(a, static_cast<unsigned char>(2));
  247. a += do_test_constexpr_compare(a, static_cast<signed char>(2));
  248. a += do_test_constexpr_compare(a, static_cast<char>(2));
  249. a += do_test_constexpr_compare(a, static_cast<short>(2));
  250. a += do_test_constexpr_compare(a, static_cast<unsigned short>(2));
  251. a += do_test_constexpr_compare(a, static_cast<int>(2));
  252. a += do_test_constexpr_compare(a, static_cast<unsigned int>(2));
  253. a += do_test_constexpr_compare(a, static_cast<long>(2));
  254. a += do_test_constexpr_compare(a, static_cast<unsigned long>(2));
  255. a += do_test_constexpr_compare(a, static_cast<long long>(2));
  256. a += do_test_constexpr_compare(a, static_cast<unsigned long long>(2));
  257. #ifdef BOOST_HAS_INT128
  258. a += do_test_constexpr_compare(a, static_cast<__int128>(2));
  259. a += do_test_constexpr_compare(a, static_cast<unsigned __int128>(2));
  260. a -= do_test_constexpr_compare(a, static_cast<__int128>(2));
  261. a -= do_test_constexpr_compare(a, static_cast<unsigned __int128>(2));
  262. #endif
  263. if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
  264. {
  265. a += do_test_constexpr_compare(a, static_cast<float>(2));
  266. a += do_test_constexpr_compare(a, static_cast<double>(2));
  267. a += do_test_constexpr_compare(a, static_cast<long double>(2));
  268. #ifdef BOOST_HAS_FLOAT128
  269. a += do_test_constexpr_compare(a, static_cast<__float128>(2));
  270. #endif
  271. }
  272. return a;
  273. }
  274. // clang-format on