test_mpfr_mpc_precisions.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright Christopher Kormanyos 2002 - 2011.
  3. // Copyright 2011 John Maddock. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
  6. //
  7. // This work is based on an earlier work:
  8. // "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
  9. // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
  10. #ifdef _MSC_VER
  11. #define _SCL_SECURE_NO_WARNINGS
  12. #endif
  13. #include <boost/detail/lightweight_test.hpp>
  14. #include "test.hpp"
  15. #include <boost/multiprecision/mpfr.hpp>
  16. #include <boost/multiprecision/mpc.hpp>
  17. template <class T>
  18. T make_rvalue_copy(const T a)
  19. {
  20. return a;
  21. }
  22. int main()
  23. {
  24. using namespace boost::multiprecision;
  25. //
  26. // Test change of default precision:
  27. //
  28. mpfr_float::default_precision(100);
  29. mpfr_float a("0.1");
  30. BOOST_CHECK_EQUAL(a.precision(), 100);
  31. mpfr_float::default_precision(20);
  32. {
  33. // test assignment from lvalue:
  34. mpfr_float b(2);
  35. BOOST_CHECK_EQUAL(b.precision(), 20);
  36. b = a;
  37. BOOST_CHECK_EQUAL(b.precision(), a.precision());
  38. }
  39. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  40. {
  41. // test assignment from rvalue:
  42. mpfr_float b(2);
  43. BOOST_CHECK_EQUAL(b.precision(), 20);
  44. b = make_rvalue_copy(a);
  45. BOOST_CHECK_EQUAL(b.precision(), a.precision());
  46. }
  47. #endif
  48. mpfr_float::default_precision(20);
  49. {
  50. // test construct from lvalue:
  51. mpfr_float b(a);
  52. BOOST_CHECK_EQUAL(b.precision(), 100);
  53. }
  54. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  55. {
  56. // test construct from rvalue:
  57. mpfr_float b(make_rvalue_copy(a));
  58. BOOST_CHECK_EQUAL(b.precision(), 100);
  59. }
  60. #endif
  61. mpc_complex::default_precision(100);
  62. mpc_complex ca("0.1");
  63. BOOST_CHECK_EQUAL(ca.precision(), 100);
  64. mpc_complex::default_precision(20);
  65. {
  66. // test assignment from lvalue:
  67. mpc_complex b(2);
  68. BOOST_CHECK_EQUAL(b.precision(), 20);
  69. b = ca;
  70. BOOST_CHECK_EQUAL(b.precision(), ca.precision());
  71. }
  72. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  73. {
  74. // test assignment from rvalue:
  75. mpc_complex b(2);
  76. BOOST_CHECK_EQUAL(b.precision(), 20);
  77. b = make_rvalue_copy(ca);
  78. BOOST_CHECK_EQUAL(b.precision(), ca.precision());
  79. }
  80. #endif
  81. {
  82. // test construct from lvalue:
  83. mpc_complex b(ca);
  84. BOOST_CHECK_EQUAL(b.precision(), ca.precision());
  85. }
  86. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  87. {
  88. // test construct from rvalue:
  89. mpc_complex b(make_rvalue_copy(ca));
  90. BOOST_CHECK_EQUAL(b.precision(), ca.precision());
  91. }
  92. #endif
  93. // real and imaginary:
  94. BOOST_CHECK_EQUAL(ca.real().precision(), 100);
  95. BOOST_CHECK_EQUAL(ca.imag().precision(), 100);
  96. BOOST_CHECK_EQUAL(real(ca).precision(), 100);
  97. BOOST_CHECK_EQUAL(imag(ca).precision(), 100);
  98. //
  99. // Construction at specific precision:
  100. //
  101. {
  102. mpfr_float f150(mpfr_float(), 150u);
  103. BOOST_CHECK_EQUAL(f150.precision(), 150);
  104. mpc_complex f150c(mpc_complex(), 150u);
  105. BOOST_CHECK_EQUAL(f150c.precision(), 150);
  106. mpc_complex f150cc(mpfr_float(), mpfr_float(), 150u);
  107. BOOST_CHECK_EQUAL(f150cc.precision(), 150);
  108. }
  109. {
  110. mpfr_float f150(2, 150);
  111. BOOST_CHECK_EQUAL(f150.precision(), 150);
  112. }
  113. {
  114. mpfr_float f150("1.2", 150);
  115. BOOST_CHECK_EQUAL(f150.precision(), 150);
  116. }
  117. //
  118. // Copying precision:
  119. //
  120. {
  121. mpc_complex c(ca.backend().data());
  122. BOOST_CHECK_EQUAL(c.precision(), 100);
  123. mpc_complex_100 c100(2);
  124. mpc_complex d(c100);
  125. BOOST_CHECK_EQUAL(d.precision(), 100);
  126. mpfr_float_100 f100(2);
  127. mpc_complex e(f100);
  128. BOOST_CHECK_EQUAL(d.precision(), 100);
  129. }
  130. //
  131. // Check that the overloads for precision don't mess up 2-arg
  132. // construction:
  133. //
  134. {
  135. mpc_complex c(2, 3u);
  136. BOOST_CHECK_EQUAL(c.real(), 2);
  137. BOOST_CHECK_EQUAL(c.imag(), 3);
  138. }
  139. //
  140. // 3-arg complex number construction with 3rd arg a precision:
  141. //
  142. {
  143. mpc_complex c(2, 3, 100);
  144. BOOST_CHECK_EQUAL(c.precision(), 100);
  145. mpfr_float_50 x(2), y(3);
  146. mpc_complex z(x, y, 100);
  147. BOOST_CHECK_EQUAL(c.precision(), 100);
  148. }
  149. //
  150. // From https://github.com/boostorg/multiprecision/issues/65
  151. //
  152. {
  153. mpfr_float a(2);
  154. a.precision(100);
  155. BOOST_CHECK_EQUAL(a, 2);
  156. BOOST_CHECK_EQUAL(a.precision(), 100);
  157. }
  158. {
  159. mpc_complex a(2, 3);
  160. a.precision(100);
  161. BOOST_CHECK_EQUAL(a.real(), 2);
  162. BOOST_CHECK_EQUAL(a.imag(), 3);
  163. BOOST_CHECK_EQUAL(a.precision(), 100);
  164. }
  165. {
  166. mpc_complex::default_precision(1000);
  167. mpfr_float::default_precision(1000);
  168. mpc_complex a("1.324719827394086120398419082734980126734089612309871092830981236748901273498071240986123094861246981263481263489016238947147129807419028748901273409127349087124612576129076541203975704195690418570914657910465091256016501650916509165097164509164509761409561097561097650791650971465097165097162059761209561029756019265019726509126509172650971625097162450971309756104975610274650917825018740981274098127409182375701465172340923847120836540491320467127043127893281461230951097260126309812374091265091824981231236409851274",
  169. "-0.80743891267394610982659071452346156102764312401571972642394120395608291471029347812645125986123123904123471209381289471230512983491286102875870192091283712396550981723409812740981263471230498715096104897123094710923879065981740928740981271801391209238470129560941870129387409812883437894183883841283700483832883218128438938184289148239164079329657861209381892037483468937489237419236509823723705612893489712412306531274812364980127304981648712483248732");
  170. mpc_complex::default_precision(40);
  171. mpfr_float::default_precision(40);
  172. BOOST_CHECK_EQUAL(a, a);
  173. }
  174. //
  175. // string_view with explicit precision:
  176. //
  177. #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
  178. {
  179. std::string s("222");
  180. std::string_view v(s.c_str(), 1);
  181. mpfr_float f(v, 100);
  182. BOOST_CHECK_EQUAL(f, 2);
  183. BOOST_CHECK_EQUAL(f.precision(), 100);
  184. }
  185. {
  186. std::string x("222"), y("333");
  187. std::string_view vx(x.c_str(), 1), vy(y.c_str(), 1);
  188. mpc_complex c(vx, vy, 100);
  189. BOOST_CHECK_EQUAL(c.real(), 2);
  190. BOOST_CHECK_EQUAL(c.imag(), 3);
  191. BOOST_CHECK_EQUAL(c.precision(), 100);
  192. }
  193. #endif
  194. {
  195. mpc_complex::default_precision(100);
  196. mpfr_float::default_precision(100);
  197. mpfr_float a(1);
  198. mpfr_float b(2);
  199. mpc_complex::default_precision(50);
  200. mpfr_float::default_precision(50);
  201. mpc_complex z(a, b);
  202. BOOST_CHECK_EQUAL(z.precision(), 100);
  203. }
  204. // Swap:
  205. {
  206. mpfr_float x(2, 100); // 100 digits precision.
  207. mpfr_float y(3, 50); // 50 digits precision.
  208. swap(x, y);
  209. BOOST_CHECK_EQUAL(x, 3);
  210. BOOST_CHECK_EQUAL(y, 2);
  211. BOOST_CHECK_EQUAL(x.precision(), 50);
  212. BOOST_CHECK_EQUAL(y.precision(), 100);
  213. x.swap(y);
  214. BOOST_CHECK_EQUAL(x, 2);
  215. BOOST_CHECK_EQUAL(y, 3);
  216. BOOST_CHECK_EQUAL(x.precision(), 100);
  217. BOOST_CHECK_EQUAL(y.precision(), 50);
  218. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  219. x = std::move(mpfr_float(y));
  220. BOOST_CHECK_EQUAL(x, y);
  221. BOOST_CHECK_EQUAL(x.precision(), y.precision());
  222. #endif
  223. }
  224. {
  225. mpc_complex x(2, 3, 100); // 100 digits precision.
  226. mpc_complex y(3, 4, 50); // 50 digits precision.
  227. swap(x, y);
  228. BOOST_CHECK_EQUAL(x.real(), 3);
  229. BOOST_CHECK_EQUAL(x.imag(), 4);
  230. BOOST_CHECK_EQUAL(y.real(), 2);
  231. BOOST_CHECK_EQUAL(y.imag(), 3);
  232. BOOST_CHECK_EQUAL(x.precision(), 50);
  233. BOOST_CHECK_EQUAL(y.precision(), 100);
  234. x.swap(y);
  235. BOOST_CHECK_EQUAL(x.real(), 2);
  236. BOOST_CHECK_EQUAL(x.imag(), 3);
  237. BOOST_CHECK_EQUAL(y.real(), 3);
  238. BOOST_CHECK_EQUAL(y.imag(), 4);
  239. BOOST_CHECK_EQUAL(x.precision(), 100);
  240. BOOST_CHECK_EQUAL(y.precision(), 50);
  241. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  242. x = std::move(mpc_complex(y));
  243. BOOST_CHECK_EQUAL(x, y);
  244. BOOST_CHECK_EQUAL(x.precision(), y.precision());
  245. #endif
  246. }
  247. {
  248. mpfr_float c(4), d(8), e(9), f;
  249. f = (c + d) * d / e;
  250. mpfr_float g((c + d) * d / e);
  251. }
  252. {
  253. mpfr_float::default_precision(100);
  254. mpfr_float f1;
  255. f1 = 3;
  256. BOOST_CHECK_EQUAL(f1.precision(), 100);
  257. f1 = 3.5;
  258. BOOST_CHECK_EQUAL(f1.precision(), 100);
  259. mpfr_float f2(3.5);
  260. BOOST_CHECK_EQUAL(f2.precision(), 100);
  261. mpfr_float f3("5.1");
  262. BOOST_CHECK_EQUAL(f3.precision(), 100);
  263. mpfr_float::default_precision(50);
  264. mpfr_float f4(f3, 50);
  265. BOOST_CHECK_EQUAL(f4.precision(), 50);
  266. f4.assign(f1, f4.precision());
  267. BOOST_CHECK_EQUAL(f4.precision(), 50);
  268. }
  269. {
  270. //
  271. // Overloads of Math lib functions, discovered while fixing
  272. // https://github.com/boostorg/multiprecision/issues/91
  273. //
  274. mpfr_float::default_precision(100);
  275. mpfr_float f1;
  276. f1 = 3;
  277. BOOST_CHECK_EQUAL(f1.precision(), 100);
  278. mpfr_float::default_precision(20);
  279. BOOST_CHECK_EQUAL(asinh(f1).precision(), 100);
  280. BOOST_CHECK_EQUAL(acosh(f1).precision(), 100);
  281. BOOST_CHECK_EQUAL(atanh(f1).precision(), 100);
  282. BOOST_CHECK_EQUAL(cbrt(f1).precision(), 100);
  283. BOOST_CHECK_EQUAL(erf(f1).precision(), 100);
  284. BOOST_CHECK_EQUAL(erfc(f1).precision(), 100);
  285. BOOST_CHECK_EQUAL(expm1(f1).precision(), 100);
  286. BOOST_CHECK_EQUAL(lgamma(f1).precision(), 100);
  287. BOOST_CHECK_EQUAL(tgamma(f1).precision(), 100);
  288. BOOST_CHECK_EQUAL(log1p(f1).precision(), 100);
  289. }
  290. return boost::report_errors();
  291. }