test_round.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // (C) Copyright John Maddock 2007.
  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. #ifdef _MSC_VER
  6. #define _SCL_SECURE_NO_WARNINGS
  7. #endif
  8. #include <boost/detail/lightweight_test.hpp>
  9. #include <boost/math/special_functions/round.hpp>
  10. #include <boost/math/special_functions/trunc.hpp>
  11. #include <boost/math/special_functions/modf.hpp>
  12. #include <boost/math/special_functions/sign.hpp>
  13. #include <boost/random/mersenne_twister.hpp>
  14. #include "test.hpp"
  15. #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPFI_50) && !defined(TEST_FLOAT128) && !defined(TEST_CPP_BIN_FLOAT)
  16. #define TEST_MPF_50
  17. #define TEST_MPFR_50
  18. #define TEST_MPFI_50
  19. #define TEST_BACKEND
  20. #define TEST_CPP_DEC_FLOAT
  21. #define TEST_FLOAT128
  22. #define TEST_CPP_BIN_FLOAT
  23. #ifdef _MSC_VER
  24. #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
  25. #endif
  26. #ifdef __GNUC__
  27. #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
  28. #endif
  29. #endif
  30. #if defined(TEST_MPF_50)
  31. #include <boost/multiprecision/gmp.hpp>
  32. #endif
  33. #ifdef TEST_MPFR_50
  34. #include <boost/multiprecision/mpfr.hpp>
  35. #endif
  36. #ifdef TEST_MPFI_50
  37. #include <boost/multiprecision/mpfi.hpp>
  38. #endif
  39. #ifdef TEST_BACKEND
  40. #include <boost/multiprecision/concepts/mp_number_archetypes.hpp>
  41. #endif
  42. #ifdef TEST_CPP_DEC_FLOAT
  43. #include <boost/multiprecision/cpp_dec_float.hpp>
  44. #endif
  45. #ifdef TEST_CPP_BIN_FLOAT
  46. #include <boost/multiprecision/cpp_bin_float.hpp>
  47. #endif
  48. #ifdef TEST_FLOAT128
  49. #include <boost/multiprecision/float128.hpp>
  50. #endif
  51. #ifdef BOOST_MSVC
  52. #pragma warning(disable : 4127)
  53. #endif
  54. boost::mt19937 rng;
  55. template <class T>
  56. T get_random()
  57. {
  58. //
  59. // Fill all the bits in T with random values,
  60. // likewise set the exponent to a random value
  61. // that will still fit inside a T, and always
  62. // have a remainder as well as an integer part.
  63. //
  64. int bits = boost::math::tools::digits<T>();
  65. int shift = 0;
  66. int exponent = rng() % (bits - 4);
  67. T result = 0;
  68. while (bits > 0)
  69. {
  70. result += ldexp(static_cast<T>(rng()), shift);
  71. shift += std::numeric_limits<int>::digits;
  72. bits -= std::numeric_limits<int>::digits;
  73. }
  74. return rng() & 1u ? T(-ldexp(frexp(result, &bits), exponent)) : T(ldexp(frexp(result, &bits), exponent));
  75. }
  76. template <class T, class U>
  77. typename boost::disable_if_c<boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u)
  78. {
  79. BOOST_MATH_STD_USING
  80. if (fabs(a - u) > 0.5f)
  81. {
  82. BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
  83. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  84. << std::left << a << u << std::endl;
  85. }
  86. if ((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
  87. {
  88. BOOST_ERROR("Rounded result was towards zero with boost::round");
  89. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  90. << std::left << a << u << std::endl;
  91. }
  92. }
  93. template <class T, class U>
  94. typename boost::enable_if_c<boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u)
  95. {
  96. BOOST_MATH_STD_USING
  97. if (upper(T(fabs(a - u))) > 0.5f)
  98. {
  99. BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
  100. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  101. << std::left << a << u << std::endl;
  102. }
  103. if ((upper(T(fabs(a - u))) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
  104. {
  105. BOOST_ERROR("Rounded result was towards zero with boost::round");
  106. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  107. << std::left << a << u << std::endl;
  108. }
  109. }
  110. //
  111. // We may not have an abs overload for long long so provide a fall back:
  112. //
  113. inline unsigned safe_abs(int const& v)
  114. {
  115. return v < 0 ? static_cast<unsigned>(1u) + static_cast<unsigned>(-(v + 1)) : v;
  116. }
  117. inline unsigned long safe_abs(long const& v)
  118. {
  119. return v < 0 ? static_cast<unsigned long>(1u) + static_cast<unsigned long>(-(v + 1)) : v;
  120. }
  121. inline unsigned long long safe_abs(long long const& v)
  122. {
  123. return v < 0 ? static_cast<unsigned long long>(1u) + static_cast<unsigned long long>(-(v + 1)) : v;
  124. }
  125. template <class T>
  126. inline typename boost::disable_if_c<boost::is_integral<T>::value, T>::type safe_abs(T const& v)
  127. {
  128. return v < 0 ? -v : v;
  129. }
  130. template <class T, class U>
  131. void check_trunc_result(T a, U u)
  132. {
  133. BOOST_MATH_STD_USING
  134. if (fabs(a - u) >= 1)
  135. {
  136. BOOST_ERROR("Rounded result differed by more than 1 from the original");
  137. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  138. << std::left << a << u << std::endl;
  139. }
  140. if (abs(a) < safe_abs(u))
  141. {
  142. BOOST_ERROR("Truncated result had larger absolute value than the original");
  143. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  144. << std::left << a << u << std::endl;
  145. }
  146. if (fabs(static_cast<T>(u)) > fabs(a))
  147. {
  148. BOOST_ERROR("Rounded result was away from zero with boost::trunc");
  149. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  150. << std::left << a << u << std::endl;
  151. }
  152. }
  153. template <class T, class U>
  154. void check_modf_result(T a, T fract, U ipart)
  155. {
  156. BOOST_MATH_STD_USING
  157. if (fract + ipart != a)
  158. {
  159. BOOST_ERROR("Fractional and integer results do not add up to the original value");
  160. std::cerr << "Values were: " << std::setprecision(35) << " "
  161. << std::left << a << ipart << " " << fract << std::endl;
  162. }
  163. if ((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))
  164. {
  165. BOOST_ERROR("Original and fractional parts have differing signs");
  166. std::cerr << "Values were: " << std::setprecision(35) << " "
  167. << std::left << a << ipart << " " << fract << std::endl;
  168. }
  169. if ((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))
  170. {
  171. BOOST_ERROR("Original and integer parts have differing signs");
  172. std::cerr << "Values were: " << std::setprecision(35) << " "
  173. << std::left << a << ipart << " " << ipart << std::endl;
  174. }
  175. if (fabs(a - ipart) >= 1)
  176. {
  177. BOOST_ERROR("Rounded result differed by more than 1 from the original");
  178. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  179. << std::left << a << ipart << std::endl;
  180. }
  181. }
  182. template <class T>
  183. void test()
  184. {
  185. BOOST_MATH_STD_USING
  186. for (int i = 0; i < 1000; ++i)
  187. {
  188. T arg = get_random<T>();
  189. T r = round(arg);
  190. check_within_half(arg, r);
  191. BOOST_TEST(r == round(arg + 0));
  192. r = trunc(arg);
  193. check_trunc_result(arg, r);
  194. BOOST_TEST(r == trunc(arg + 0));
  195. T frac = modf(arg, &r);
  196. check_modf_result(arg, frac, r);
  197. if (abs(r) < (std::numeric_limits<int>::max)())
  198. {
  199. int i = iround(arg);
  200. check_within_half(arg, i);
  201. BOOST_TEST(i == iround(arg + 0));
  202. i = itrunc(arg);
  203. check_trunc_result(arg, i);
  204. BOOST_TEST(i == itrunc(arg + 0));
  205. r = modf(arg, &i);
  206. check_modf_result(arg, r, i);
  207. }
  208. if (abs(r) < (std::numeric_limits<long>::max)())
  209. {
  210. long l = lround(arg);
  211. check_within_half(arg, l);
  212. BOOST_TEST(l == lround(arg + 0));
  213. l = ltrunc(arg);
  214. check_trunc_result(arg, l);
  215. BOOST_TEST(l == ltrunc(arg + 0));
  216. r = modf(arg, &l);
  217. check_modf_result(arg, r, l);
  218. }
  219. #ifdef BOOST_HAS_LONG_LONG
  220. if (abs(r) < (std::numeric_limits<boost::long_long_type>::max)())
  221. {
  222. boost::long_long_type ll = llround(arg);
  223. check_within_half(arg, ll);
  224. BOOST_TEST(ll == llround(arg + 0));
  225. ll = lltrunc(arg);
  226. check_trunc_result(arg, ll);
  227. BOOST_TEST(ll == lltrunc(arg + 0));
  228. r = modf(arg, &ll);
  229. check_modf_result(arg, r, ll);
  230. }
  231. #endif
  232. }
  233. //
  234. // Test boundary cases:
  235. //
  236. if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  237. {
  238. int si = iround(static_cast<T>((std::numeric_limits<int>::max)()));
  239. check_within_half(static_cast<T>((std::numeric_limits<int>::max)()), si);
  240. BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::max)()) + 0));
  241. si = iround(static_cast<T>((std::numeric_limits<int>::min)()));
  242. check_within_half(static_cast<T>((std::numeric_limits<int>::min)()), si);
  243. BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::min)()) + 0));
  244. si = itrunc(static_cast<T>((std::numeric_limits<int>::max)()));
  245. check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)()), si);
  246. BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 0));
  247. si = itrunc(static_cast<T>((std::numeric_limits<int>::min)()));
  248. check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)()), si);
  249. BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::min)()) + 0));
  250. si = iround(static_cast<T>((std::numeric_limits<int>::max)() - 1));
  251. check_within_half(static_cast<T>((std::numeric_limits<int>::max)() - 1), si);
  252. si = iround(static_cast<T>((std::numeric_limits<int>::min)() + 1));
  253. check_within_half(static_cast<T>((std::numeric_limits<int>::min)() + 1), si);
  254. si = itrunc(static_cast<T>((std::numeric_limits<int>::max)() - 1));
  255. check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)() - 1), si);
  256. si = itrunc(static_cast<T>((std::numeric_limits<int>::min)() + 1));
  257. check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)() + 1), si);
  258. }
  259. if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  260. {
  261. long k = lround(static_cast<T>((std::numeric_limits<long>::max)()));
  262. check_within_half(static_cast<T>((std::numeric_limits<long>::max)()), k);
  263. BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
  264. k = lround(static_cast<T>((std::numeric_limits<long>::min)()));
  265. check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k);
  266. BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
  267. k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)()));
  268. check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), k);
  269. BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
  270. k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)()));
  271. check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), k);
  272. BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
  273. k = lround(static_cast<T>((std::numeric_limits<long>::max)() - 1));
  274. check_within_half(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
  275. k = lround(static_cast<T>((std::numeric_limits<long>::min)() + 1));
  276. check_within_half(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
  277. k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)() - 1));
  278. check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
  279. k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)() + 1));
  280. check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
  281. }
  282. #ifndef BOOST_NO_LONG_LONG
  283. if (std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  284. {
  285. boost::long_long_type j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
  286. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
  287. BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::max)()) + 0));
  288. j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
  289. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
  290. BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::min)()) + 0));
  291. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
  292. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
  293. BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::max)()) + 0));
  294. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
  295. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
  296. BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::min)()) + 0));
  297. j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1));
  298. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1), j);
  299. j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1));
  300. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1), j);
  301. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1));
  302. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1), j);
  303. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1));
  304. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1), j);
  305. }
  306. #endif
  307. //
  308. // Finish off by testing the error handlers:
  309. //
  310. T result;
  311. #ifndef BOOST_NO_EXCEPTIONS
  312. BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>(1e20))), boost::math::rounding_error);
  313. BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>(-1e20))), boost::math::rounding_error);
  314. BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>(1e20))), boost::math::rounding_error);
  315. BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>(-1e20))), boost::math::rounding_error);
  316. #ifdef BOOST_HAS_LONG_LONG
  317. BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>(1e20))), boost::math::rounding_error);
  318. BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>(-1e20))), boost::math::rounding_error);
  319. #endif
  320. if (std::numeric_limits<T>::has_infinity)
  321. {
  322. BOOST_CHECK_EQUAL(static_cast<T>(round(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity()); // See C99 Annex F.
  323. BOOST_CHECK_THROW(result = static_cast<T>(iround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  324. BOOST_CHECK_THROW(result = static_cast<T>(iround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  325. BOOST_CHECK_THROW(result = static_cast<T>(lround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  326. BOOST_CHECK_THROW(result = static_cast<T>(lround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  327. #ifdef BOOST_HAS_LONG_LONG
  328. BOOST_CHECK_THROW(result = static_cast<T>(llround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  329. BOOST_CHECK_THROW(result = static_cast<T>(llround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  330. #endif
  331. }
  332. if (std::numeric_limits<T>::has_quiet_NaN)
  333. {
  334. BOOST_CHECK((boost::multiprecision::isnan)(round(std::numeric_limits<T>::quiet_NaN())));
  335. BOOST_CHECK_THROW(result = static_cast<T>(iround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  336. BOOST_CHECK_THROW(result = static_cast<T>(lround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  337. #ifdef BOOST_HAS_LONG_LONG
  338. BOOST_CHECK_THROW(result = static_cast<T>(llround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  339. #endif
  340. }
  341. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>(1e20))), boost::math::rounding_error);
  342. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
  343. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>(1e20))), boost::math::rounding_error);
  344. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
  345. #ifdef BOOST_HAS_LONG_LONG
  346. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>(1e20))), boost::math::rounding_error);
  347. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
  348. #endif
  349. if (std::numeric_limits<T>::has_infinity)
  350. {
  351. BOOST_CHECK_EQUAL(static_cast<T>(trunc(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity());
  352. BOOST_CHECK_EQUAL(static_cast<T>(trunc(-std::numeric_limits<T>::infinity())), -std::numeric_limits<T>::infinity());
  353. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  354. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  355. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  356. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  357. #ifdef BOOST_HAS_LONG_LONG
  358. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  359. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
  360. #endif
  361. }
  362. if (std::numeric_limits<T>::has_quiet_NaN)
  363. {
  364. BOOST_CHECK((boost::multiprecision::isnan)(trunc(std::numeric_limits<T>::quiet_NaN())));
  365. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  366. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  367. #ifdef BOOST_HAS_LONG_LONG
  368. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
  369. #endif
  370. }
  371. if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  372. {
  373. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error);
  374. BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error);
  375. }
  376. if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  377. {
  378. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error);
  379. BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error);
  380. }
  381. #ifndef BOOST_NO_LONG_LONG
  382. if (std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  383. {
  384. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1)), boost::math::rounding_error);
  385. BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1)), boost::math::rounding_error);
  386. }
  387. #endif
  388. if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  389. {
  390. BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error);
  391. BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error);
  392. }
  393. if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  394. {
  395. BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error);
  396. BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error);
  397. }
  398. #ifndef BOOST_NO_LONG_LONG
  399. if (std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  400. {
  401. BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1)), boost::math::rounding_error);
  402. BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1)), boost::math::rounding_error);
  403. }
  404. #endif
  405. #endif
  406. }
  407. int main()
  408. {
  409. #ifdef TEST_MPF_50
  410. test<boost::multiprecision::mpf_float_50>();
  411. test<boost::multiprecision::mpf_float_100>();
  412. #endif
  413. #ifdef TEST_MPFR_50
  414. test<boost::multiprecision::mpfr_float_50>();
  415. test<boost::multiprecision::mpfr_float_100>();
  416. #endif
  417. #ifdef TEST_MPFI_50
  418. test<boost::multiprecision::mpfi_float_50>();
  419. test<boost::multiprecision::mpfi_float_100>();
  420. #endif
  421. #ifdef TEST_CPP_DEC_FLOAT
  422. test<boost::multiprecision::cpp_dec_float_50>();
  423. test<boost::multiprecision::cpp_dec_float_100>();
  424. #ifndef SLOW_COMPLER
  425. // Some "peculiar" digit counts which stress our code:
  426. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<65> > >();
  427. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<64> > >();
  428. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<63> > >();
  429. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<62> > >();
  430. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<61, long long> > >();
  431. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<60, long long> > >();
  432. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<59, long long, std::allocator<char> > > >();
  433. test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<58, long long, std::allocator<char> > > >();
  434. #endif
  435. #endif
  436. #ifdef TEST_CPP_BIN_FLOAT
  437. test<boost::multiprecision::cpp_bin_float_50>();
  438. test<boost::multiprecision::cpp_bin_float_100>();
  439. test<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<35, boost::multiprecision::digit_base_10, std::allocator<char>, boost::long_long_type> > >();
  440. #endif
  441. #ifdef TEST_BACKEND
  442. test<boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype> >();
  443. #endif
  444. #ifdef TEST_FLOAT128
  445. test<boost::multiprecision::float128>();
  446. #endif
  447. return boost::report_errors();
  448. }