test_round.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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. #include <pch.hpp>
  6. #include <boost/math/concepts/real_concept.hpp>
  7. #define BOOST_TEST_MAIN
  8. #include <boost/test/unit_test.hpp>
  9. #include <boost/math/tools/test.hpp>
  10. #include <boost/test/tools/floating_point_comparison.hpp>
  11. #include <boost/math/special_functions/round.hpp>
  12. #include <boost/math/special_functions/next.hpp>
  13. #include <boost/math/special_functions/trunc.hpp>
  14. #include <boost/math/special_functions/modf.hpp>
  15. #include <boost/math/special_functions/sign.hpp>
  16. #include <boost/random/mersenne_twister.hpp>
  17. #include <iostream>
  18. #include <iomanip>
  19. boost::mt19937 rng;
  20. template <class T>
  21. T get_random()
  22. {
  23. //
  24. // Fill all the bits in T with random values,
  25. // likewise set the exponent to a random value
  26. // that will still fit inside a T, and always
  27. // have a remainder as well as an integer part.
  28. //
  29. int bits = boost::math::tools::digits<T>();
  30. int shift = 0;
  31. int exponent = rng() % (bits - 4);
  32. T result = 0;
  33. while(bits > 0)
  34. {
  35. result += ldexp(static_cast<T>(rng()), shift);
  36. shift += std::numeric_limits<int>::digits;
  37. bits -= std::numeric_limits<int>::digits;
  38. }
  39. return rng() & 1u ? -ldexp(frexp(result, &bits), exponent) : ldexp(frexp(result, &bits), exponent);
  40. }
  41. template <class T, class U>
  42. void check_within_half(T a, U u)
  43. {
  44. BOOST_MATH_STD_USING
  45. if(fabs(a-u) > 0.5f)
  46. {
  47. BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
  48. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  49. << std::left << a << u << std::endl;
  50. }
  51. if((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
  52. {
  53. BOOST_ERROR("Rounded result was towards zero with boost::round");
  54. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  55. << std::left << a << u << std::endl;
  56. }
  57. }
  58. //
  59. // We may not have an abs overload for long long so provide a fall back:
  60. //
  61. template <class T>
  62. inline T safe_abs(T const& v ...)
  63. {
  64. return v < 0 ? -v : v;
  65. }
  66. template <class T, class U>
  67. void check_trunc_result(T a, U u)
  68. {
  69. BOOST_MATH_STD_USING
  70. if(fabs(a-u) >= 1)
  71. {
  72. BOOST_ERROR("Rounded result differed by more than 1 from the original");
  73. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  74. << std::left << a << u << std::endl;
  75. }
  76. if(abs(a) < safe_abs(u))
  77. {
  78. BOOST_ERROR("Truncated result had larger absolute value than the original");
  79. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  80. << std::left << a << u << std::endl;
  81. }
  82. if(fabs(static_cast<T>(u)) > fabs(a))
  83. {
  84. BOOST_ERROR("Rounded result was away from zero with boost::trunc");
  85. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  86. << std::left << a << u << std::endl;
  87. }
  88. }
  89. template <class T, class U>
  90. void check_modf_result(T a, T fract, U ipart)
  91. {
  92. BOOST_MATH_STD_USING
  93. if(fract + ipart != a)
  94. {
  95. BOOST_ERROR("Fractional and integer results do not add up to the original value");
  96. std::cerr << "Values were: " << std::setprecision(35) << " "
  97. << std::left << a << ipart << " " << fract << std::endl;
  98. }
  99. if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))
  100. {
  101. BOOST_ERROR("Original and fractional parts have differing signs");
  102. std::cerr << "Values were: " << std::setprecision(35) << " "
  103. << std::left << a << ipart << " " << fract << std::endl;
  104. }
  105. if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))
  106. {
  107. BOOST_ERROR("Original and integer parts have differing signs");
  108. std::cerr << "Values were: " << std::setprecision(35) << " "
  109. << std::left << a << ipart << " " << ipart << std::endl;
  110. }
  111. if(fabs(a-ipart) >= 1)
  112. {
  113. BOOST_ERROR("Rounded result differed by more than 1 from the original");
  114. std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
  115. << std::left << a << ipart << std::endl;
  116. }
  117. }
  118. template <class T>
  119. void test_round_number(T arg)
  120. {
  121. BOOST_MATH_STD_USING
  122. #ifdef BOOST_HAS_LONG_LONG
  123. using boost::math::llround; using boost::math::lltrunc;
  124. #endif
  125. T r = round(arg);
  126. check_within_half(arg, r);
  127. r = trunc(arg);
  128. check_trunc_result(arg, r);
  129. T frac = boost::math::modf(arg, &r);
  130. check_modf_result(arg, frac, r);
  131. if(abs(r) < (std::numeric_limits<int>::max)())
  132. {
  133. int i = iround(arg);
  134. check_within_half(arg, i);
  135. i = itrunc(arg);
  136. check_trunc_result(arg, T(i));
  137. r = boost::math::modf(arg, &i);
  138. check_modf_result(arg, r, i);
  139. }
  140. if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  141. {
  142. int si = iround(static_cast<T>((std::numeric_limits<int>::max)()));
  143. check_within_half(static_cast<T>((std::numeric_limits<int>::max)()), si);
  144. si = iround(static_cast<T>((std::numeric_limits<int>::min)()));
  145. check_within_half(static_cast<T>((std::numeric_limits<int>::min)()), si);
  146. si = itrunc(static_cast<T>((std::numeric_limits<int>::max)()));
  147. check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)()), T(si));
  148. si = itrunc(static_cast<T>((std::numeric_limits<int>::min)()));
  149. check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)()), T(si));
  150. }
  151. if(abs(r) < (std::numeric_limits<long>::max)())
  152. {
  153. long l = lround(arg);
  154. check_within_half(arg, l);
  155. l = ltrunc(arg);
  156. check_trunc_result(arg, T(l));
  157. r = boost::math::modf(arg, &l);
  158. check_modf_result(arg, r, l);
  159. }
  160. if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  161. {
  162. long k = lround(static_cast<T>((std::numeric_limits<long>::max)()));
  163. check_within_half(static_cast<T>((std::numeric_limits<long>::max)()), k);
  164. k = lround(static_cast<T>((std::numeric_limits<long>::min)()));
  165. check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k);
  166. k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)()));
  167. check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), T(k));
  168. k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)()));
  169. check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), T(k));
  170. }
  171. #ifdef BOOST_HAS_LONG_LONG
  172. if(abs(r) < (std::numeric_limits<boost::long_long_type>::max)())
  173. {
  174. boost::long_long_type ll = llround(arg);
  175. check_within_half(arg, ll);
  176. ll = lltrunc(arg);
  177. check_trunc_result(arg, T(ll));
  178. r = boost::math::modf(arg, &ll);
  179. check_modf_result(arg, r, ll);
  180. }
  181. if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  182. {
  183. boost::long_long_type j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
  184. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
  185. j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
  186. check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
  187. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
  188. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), T(j));
  189. j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
  190. check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), T(j));
  191. }
  192. #endif
  193. }
  194. template <class T>
  195. void test_round(T, const char* name )
  196. {
  197. BOOST_MATH_STD_USING
  198. #ifdef BOOST_HAS_LONG_LONG
  199. using boost::math::llround; using boost::math::lltrunc;
  200. #endif
  201. std::cout << "Testing rounding with type " << name << std::endl;
  202. for(int i = 0; i < 1000; ++i)
  203. {
  204. T arg = get_random<T>();
  205. test_round_number<T>(arg);
  206. }
  207. //
  208. // Finish off by testing the error handlers:
  209. //
  210. BOOST_MATH_CHECK_THROW(iround(static_cast<T>(1e20)), boost::math::rounding_error);
  211. BOOST_MATH_CHECK_THROW(iround(static_cast<T>(-1e20)), boost::math::rounding_error);
  212. BOOST_MATH_CHECK_THROW(lround(static_cast<T>(1e20)), boost::math::rounding_error);
  213. BOOST_MATH_CHECK_THROW(lround(static_cast<T>(-1e20)), boost::math::rounding_error);
  214. #ifdef BOOST_HAS_LONG_LONG
  215. BOOST_MATH_CHECK_THROW(llround(static_cast<T>(1e20)), boost::math::rounding_error);
  216. BOOST_MATH_CHECK_THROW(llround(static_cast<T>(-1e20)), boost::math::rounding_error);
  217. #endif
  218. if(std::numeric_limits<T>::has_infinity)
  219. {
  220. BOOST_MATH_CHECK_THROW(round(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  221. BOOST_MATH_CHECK_THROW(iround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  222. BOOST_MATH_CHECK_THROW(iround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  223. BOOST_MATH_CHECK_THROW(lround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  224. BOOST_MATH_CHECK_THROW(lround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  225. #ifdef BOOST_HAS_LONG_LONG
  226. BOOST_MATH_CHECK_THROW(llround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  227. BOOST_MATH_CHECK_THROW(llround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  228. #endif
  229. }
  230. if(std::numeric_limits<T>::has_quiet_NaN)
  231. {
  232. BOOST_MATH_CHECK_THROW(round(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  233. BOOST_MATH_CHECK_THROW(iround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  234. BOOST_MATH_CHECK_THROW(lround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  235. #ifdef BOOST_HAS_LONG_LONG
  236. BOOST_MATH_CHECK_THROW(llround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  237. #endif
  238. }
  239. BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>(1e20)), boost::math::rounding_error);
  240. BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
  241. BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>(1e20)), boost::math::rounding_error);
  242. BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
  243. #ifdef BOOST_HAS_LONG_LONG
  244. BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>(1e20)), boost::math::rounding_error);
  245. BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
  246. #endif
  247. if(std::numeric_limits<T>::has_infinity)
  248. {
  249. BOOST_MATH_CHECK_THROW(trunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  250. BOOST_MATH_CHECK_THROW(itrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  251. BOOST_MATH_CHECK_THROW(itrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  252. BOOST_MATH_CHECK_THROW(ltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  253. BOOST_MATH_CHECK_THROW(ltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  254. #ifdef BOOST_HAS_LONG_LONG
  255. BOOST_MATH_CHECK_THROW(lltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  256. BOOST_MATH_CHECK_THROW(lltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
  257. #endif
  258. }
  259. if(std::numeric_limits<T>::has_quiet_NaN)
  260. {
  261. BOOST_MATH_CHECK_THROW(trunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  262. BOOST_MATH_CHECK_THROW(itrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  263. BOOST_MATH_CHECK_THROW(ltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  264. #ifdef BOOST_HAS_LONG_LONG
  265. BOOST_MATH_CHECK_THROW(lltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
  266. #endif
  267. }
  268. if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  269. {
  270. BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 1), boost::math::rounding_error);
  271. BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>((std::numeric_limits<int>::min)()) - 1), boost::math::rounding_error);
  272. }
  273. if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  274. {
  275. BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 1), boost::math::rounding_error);
  276. BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) - 1), boost::math::rounding_error);
  277. }
  278. #ifndef BOOST_NO_LONG_LONG
  279. if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  280. {
  281. BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1), boost::math::rounding_error);
  282. BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1), boost::math::rounding_error);
  283. }
  284. #endif
  285. if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  286. {
  287. BOOST_MATH_CHECK_THROW(iround(static_cast<T>((std::numeric_limits<int>::max)()) + 1), boost::math::rounding_error);
  288. BOOST_MATH_CHECK_THROW(iround(static_cast<T>((std::numeric_limits<int>::min)()) - 1), boost::math::rounding_error);
  289. }
  290. if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  291. {
  292. BOOST_MATH_CHECK_THROW(lround(static_cast<T>((std::numeric_limits<long>::max)()) + 1), boost::math::rounding_error);
  293. BOOST_MATH_CHECK_THROW(lround(static_cast<T>((std::numeric_limits<long>::min)()) - 1), boost::math::rounding_error);
  294. }
  295. #ifndef BOOST_NO_LONG_LONG
  296. if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
  297. {
  298. BOOST_MATH_CHECK_THROW(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1), boost::math::rounding_error);
  299. BOOST_MATH_CHECK_THROW(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1), boost::math::rounding_error);
  300. }
  301. #endif
  302. //
  303. // try non-throwing error handlers:
  304. //
  305. boost::math::policies::policy<boost::math::policies::rounding_error<boost::math::policies::ignore_error> > pol;
  306. if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
  307. {
  308. BOOST_CHECK_EQUAL(iround((std::numeric_limits<int>::max)() + T(1.0), pol), (std::numeric_limits<int>::max)());
  309. BOOST_CHECK_EQUAL(iround((std::numeric_limits<int>::min)() - T(1.0), pol), (std::numeric_limits<int>::min)());
  310. BOOST_CHECK_EQUAL(itrunc((std::numeric_limits<int>::max)() + T(1.0), pol), (std::numeric_limits<int>::max)());
  311. BOOST_CHECK_EQUAL(itrunc((std::numeric_limits<int>::min)() - T(1.0), pol), (std::numeric_limits<int>::min)());
  312. }
  313. if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
  314. {
  315. BOOST_CHECK_EQUAL(lround((std::numeric_limits<long>::max)() + T(1.0), pol), (std::numeric_limits<long>::max)());
  316. BOOST_CHECK_EQUAL(lround((std::numeric_limits<long>::min)() - T(1.0), pol), (std::numeric_limits<long>::min)());
  317. BOOST_CHECK_EQUAL(ltrunc((std::numeric_limits<long>::max)() + T(1.0), pol), (std::numeric_limits<long>::max)());
  318. BOOST_CHECK_EQUAL(ltrunc((std::numeric_limits<long>::min)() - T(1.0), pol), (std::numeric_limits<long>::min)());
  319. }
  320. #ifndef BOOST_NO_LONG_LONG
  321. if(std::numeric_limits<T>::digits >= std::numeric_limits<long long>::digits)
  322. {
  323. BOOST_CHECK_EQUAL(llround((std::numeric_limits<long long>::max)() + T(1.0), pol), (std::numeric_limits<long long>::max)());
  324. BOOST_CHECK_EQUAL(llround((std::numeric_limits<long long>::min)() - T(1.0), pol), (std::numeric_limits<long long>::min)());
  325. BOOST_CHECK_EQUAL(lltrunc((std::numeric_limits<long long>::max)() + T(1.0), pol), (std::numeric_limits<long long>::max)());
  326. BOOST_CHECK_EQUAL(lltrunc((std::numeric_limits<long long>::min)() - T(1.0), pol), (std::numeric_limits<long long>::min)());
  327. }
  328. #endif
  329. // Again with bigger value:
  330. T big = 1e20f;
  331. BOOST_CHECK_EQUAL(iround(big, pol), (std::numeric_limits<int>::max)());
  332. BOOST_CHECK_EQUAL(lround(big, pol), (std::numeric_limits<long>::max)());
  333. BOOST_CHECK_EQUAL(iround(-big, pol), (std::numeric_limits<int>::min)());
  334. BOOST_CHECK_EQUAL(lround(-big, pol), (std::numeric_limits<long>::min)());
  335. BOOST_CHECK_EQUAL(itrunc(big, pol), (std::numeric_limits<int>::max)());
  336. BOOST_CHECK_EQUAL(ltrunc(big, pol), (std::numeric_limits<long>::max)());
  337. BOOST_CHECK_EQUAL(itrunc(-big, pol), (std::numeric_limits<int>::min)());
  338. BOOST_CHECK_EQUAL(ltrunc(-big, pol), (std::numeric_limits<long>::min)());
  339. #ifndef BOOST_NO_LONG_LONG
  340. BOOST_CHECK_EQUAL(llround(big, pol), (std::numeric_limits<long long>::max)());
  341. BOOST_CHECK_EQUAL(llround(-big, pol), (std::numeric_limits<long long>::min)());
  342. BOOST_CHECK_EQUAL(lltrunc(big, pol), (std::numeric_limits<long long>::max)());
  343. BOOST_CHECK_EQUAL(lltrunc(-big, pol), (std::numeric_limits<long long>::min)());
  344. #endif
  345. //
  346. // Special cases that we know can go bad:
  347. //
  348. T half = 0.5f;
  349. half = boost::math::float_prior(half);
  350. test_round_number(half);
  351. half = -0.5f;
  352. half = boost::math::float_next(half);
  353. test_round_number(half);
  354. if(std::numeric_limits<T>::is_specialized)
  355. {
  356. //
  357. // Odd and even integer values:
  358. //
  359. T val;
  360. for(int i = 2; i < std::numeric_limits<T>::max_exponent; ++i)
  361. {
  362. val = ldexp(T(1), i);
  363. test_round_number(val);
  364. ++val;
  365. test_round_number(val);
  366. val = -val;
  367. test_round_number(val);
  368. ++val;
  369. test_round_number(val);
  370. }
  371. }
  372. }
  373. BOOST_AUTO_TEST_CASE( test_main )
  374. {
  375. test_round(0.1F, "float");
  376. test_round(0.1, "double");
  377. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  378. test_round(0.1L, "long double");
  379. test_round(boost::math::concepts::real_concept(0.1), "real_concept");
  380. #else
  381. std::cout << "<note>The long double tests have been disabled on this platform "
  382. "either because the long double overloads of the usual math functions are "
  383. "not available at all, or because they are too inaccurate for these tests "
  384. "to pass.</note>" << std::endl;
  385. #endif
  386. // test rounding of direct predecessor/successor of 0.5/-0.5 for float and double
  387. test_round_number(-0.4999999701976776123046875f);
  388. BOOST_CHECK_EQUAL(boost::math::round(-0.4999999701976776123046875f), 0.0f);
  389. test_round_number(0.4999999701976776123046875f);
  390. BOOST_CHECK_EQUAL(boost::math::round(0.4999999701976776123046875f), 0.0f);
  391. BOOST_CHECK_EQUAL(boost::math::round(-0.499999999999999944488848768742172978818416595458984375), 0.0);
  392. test_round_number(-0.499999999999999944488848768742172978818416595458984375);
  393. BOOST_CHECK_EQUAL(boost::math::round(0.499999999999999944488848768742172978818416595458984375), 0.0);
  394. test_round_number(0.499999999999999944488848768742172978818416595458984375);
  395. // test rounding of integer numbers on the edge of the float/double mantissa width
  396. BOOST_CHECK_EQUAL(boost::math::round(-16777215.0f), -16777215.0f);
  397. test_round_number(-16777215.0f);
  398. BOOST_CHECK_EQUAL(boost::math::round(-16777213.0f), -16777213.0f);
  399. test_round_number(-16777213.0f);
  400. BOOST_CHECK_EQUAL(boost::math::round(-8388611.0f), -8388611.0f);
  401. test_round_number(-8388611.0f);
  402. BOOST_CHECK_EQUAL(boost::math::round(-8388609.0f), -8388609.0f);
  403. test_round_number(-8388609.0f);
  404. BOOST_CHECK_EQUAL(boost::math::round(8388609.0f), 8388609.0f);
  405. test_round_number(8388609.0f);
  406. BOOST_CHECK_EQUAL(boost::math::round(8388611.0f), 8388611.0f);
  407. test_round_number(8388611.0f);
  408. BOOST_CHECK_EQUAL(boost::math::round(16777213.0f), 16777213.0f);
  409. test_round_number(16777213.0f);
  410. BOOST_CHECK_EQUAL(boost::math::round(16777215.0f), 16777215.0f);
  411. test_round_number(16777215.0f);
  412. BOOST_CHECK_EQUAL(boost::math::round(-9007199254740993.0), -9007199254740993.0);
  413. test_round_number(-9007199254740993.0);
  414. BOOST_CHECK_EQUAL(boost::math::round(-9007199254740991.0), -9007199254740991.0);
  415. test_round_number(-9007199254740991.0);
  416. BOOST_CHECK_EQUAL(boost::math::round(-4503599627370499.0), -4503599627370499.0);
  417. test_round_number(-4503599627370499.0);
  418. BOOST_CHECK_EQUAL(boost::math::round(-4503599627370497.0), -4503599627370497.0);
  419. test_round_number(-4503599627370497.0);
  420. BOOST_CHECK_EQUAL(boost::math::round(4503599627370497.0), 4503599627370497.0);
  421. test_round_number(4503599627370497.0);
  422. BOOST_CHECK_EQUAL(boost::math::round(4503599627370499.0), 4503599627370499.0);
  423. test_round_number(4503599627370499.0);
  424. BOOST_CHECK_EQUAL(boost::math::round(9007199254740991.0), 9007199254740991.0);
  425. test_round_number(9007199254740991.0);
  426. BOOST_CHECK_EQUAL(boost::math::round(9007199254740993.0), 9007199254740993.0);
  427. test_round_number(9007199254740993.0);
  428. }