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