boost/multiprecision/float128
I'm new to boost. I am trying to use the float128 type for calculating sqrts as a larger part of code, however I am not sure the values obtained are accurate to float128 precision. I have tried running the example for printing log(2) found here, I find the same for sqrt: http://www.boost.org/doc/libs/1_57_0/libs/multiprecision/doc/html/boost_mult... However, the value printed log(2) only agrees to 16 decimal places, i.e. double precision. The value I obtain is 0.693147180559945286226763982995180413 rather than 0.693147180559945309417232121458176575 I'm using: g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15) with boost 1.57.0. Any advice as to what I am doing incorrectly? My compile line is: g++ -I ~/$BOOSTLIB new.cpp -lquadmath -o new Thanks,
From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Cooper, Bridgette R D Sent: 30 April 2016 12:32 To: boost-users@lists.boost.org Subject: [Boost-users] boost/multiprecision/float128 I'm new to boost. I am trying to use the float128 type for calculating sqrts as a larger part of code, however I am not sure the values obtained are accurate to float128 precision. I have tried running the example for printing log(2) found here, I find the same for sqrt: http://www.boost.org/doc/libs/1_57_0/libs/multiprecision/doc/html/boost_mult... However, the value printed log(2) only agrees to 16 decimal places, i.e. double precision. The value I obtain is 0.693147180559945286226763982995180413 rather than 0.693147180559945309417232121458176575 I'm using: g++ (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15) with boost 1.57.0. Any advice as to what I am doing incorrectly? My compile line is: g++ -I ~/$BOOSTLIB new.cpp -lquadmath -o new You don't give your exact code but I suspect that you have fallen into what is an annoying (but unavoidable) pit that is eagerly awaiting the unwary. (Been there, done that - more than once!) You need to ensure that *all* values processed really are float128 or other multiprecision types by construction or casting, for example log(float128(2)). (Otherwise computation will take place in double precision and only then be converted to float128 and printed, as you observe). HTH Paul
Hi Paul,
For a moment I thought that worked. It certainly does for log(2). I distinctly get two different values (with the first giving the "correct" value) if I try:
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(float128(2.q)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(2.q) << std::endl;
However, this isn't true for sqrt still. I checked by calculating the sqrt(pi) and comparing to
https://github.com/ned14/boost-trunk/blob/master/libs/multiprecision/test/te...
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
These two lines give me identical results and again only match the first 16 digits.
pie is defined as float128 and I copy/pasted the 100 digit value from the same test_sqrt.cpp given above.
Thanks for your help.
________________________________
From: Boost-users
On 30/04/2016 18:38, Cooper, Bridgette R D wrote:
Hi Paul,
For a moment I thought that worked. It certainly does for log(2). I distinctly get two different values (with the first giving the "correct" value) if I try:
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(float128(2.q)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(2.q) << std::endl;
However, this isn't true for sqrt still. I checked by calculating the sqrt(pi) and comparing to
https://github.com/ned14/boost-trunk/blob/master/libs/multiprecision/test/te...
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
These two lines give me identical results and again only match the first 16 digits.
pie is defined as float128 and I copy/pasted the 100 digit value from the same test_sqrt.cpp given above.
I suspect an error in your declaration of pie, using this: using namespace boost::multiprecision; __float128 pie = boost::math::constants::pi<__float128>(); std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl; I see as output: 1.77245385090551602729816748334114514 1.77245385090551588191942755656782538 John.
Thanks John,
That seems to have worked for sqrt(pi). I'm also pretty new to c++ (I mostly code in fortran) which is probably where a lot of my confusions lie. I don't understand why I don't get the right answer with the declaration of pie I had before. In the real code I want to write I use sqrt of a float128 a lot and I want to be sure I am definitely not loosing precision as my overall calculation is extremely sensitive to precision. So how should I be declaring variables? I notice you had __float128. Does this do something different than just writing float128? I was already using using namespace boost::multi precision.
________________________________________
From: Boost-users
Hi Paul,
For a moment I thought that worked. It certainly does for log(2). I distinctly get two different values (with the first giving the "correct" value) if I try:
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(float128(2.q)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(2.q) << std::endl;
However, this isn't true for sqrt still. I checked by calculating the sqrt(pi) and comparing to
https://github.com/ned14/boost-trunk/blob/master/libs/multiprecision/test/te...
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
These two lines give me identical results and again only match the first 16 digits.
pie is defined as float128 and I copy/pasted the 100 digit value from the same test_sqrt.cpp given above.
I suspect an error in your declaration of pie, using this: using namespace boost::multiprecision; __float128 pie = boost::math::constants::pi<__float128>(); std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl; I see as output: 1.77245385090551602729816748334114514 1.77245385090551588191942755656782538 John. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 30/04/2016 20:10, Cooper, Bridgette R D wrote:
Thanks John,
That seems to have worked for sqrt(pi). I'm also pretty new to c++ (I mostly code in fortran) which is probably where a lot of my confusions lie. I don't understand why I don't get the right answer with the declaration of pie I had before. In the real code I want to write I use sqrt of a float128 a lot and I want to be sure I am definitely not loosing precision as my overall calculation is extremely sensitive to precision. So how should I be declaring variables? I notice you had __float128. Does this do something different than just writing float128? I was already using using namespace boost::multi precision.
Without seeing your code, I can't say where you went wrong, but in general: * Make sure you declare variables with the correct type - float128 in your case. * Make sure you declare literals with the correct suffix - otherwise they'll be treated as type double - so make sure they have a Q suffix in your case. * All the std lib functions, plus all the constants, and special functions from Boost.Math should then just work. * Make sure std lib functions are called unqualified so that the correct overload is found via ADL, ie sqrt(variable) not std::sqrt(variable). * In general, try not to reinvent stuff - using constants from Boost.Math is probably less error prone than declaring your own, likewise the special functions etc. Now for the __float128/float128 confusion: __float128 is the compiler supplied hardware type, it's an extension to C++ and there is only minimal support for it in normal C++ (no IO streams or numeric_limits support, function names in libquadmath all have different names to the std ones etc.) So you can program that type directly but it's harder work. Type float128 is a thin wrapper around __float128 and makes it C++ and generic code friendly. Another example: using namespace boost::multiprecision; float128 pi1 = boost::math::constants::pi<float128>(); // returns constant of type float128 float128 pi2 = boost::math::constants::pi<__float128>(); // constant of type __float128 gets converted to float128 on the assignment float128 pi3 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348Q; // DIY constant std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi1) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi2) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi3) << std::endl; // compare to ready rolled constant from Boost.Math: std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << boost::math::constants::root_pi<float128>() << std::endl; Outputs: 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 Note that the casts within the sqrt call aren't needed since all the variables are the correct type to begin with. HTH, John.
________________________________________ From: Boost-users
on behalf of John Maddock Sent: Saturday, April 30, 2016 7:25:27 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] boost/multiprecision/float128 On 30/04/2016 18:38, Cooper, Bridgette R D wrote:
Hi Paul,
For a moment I thought that worked. It certainly does for log(2). I distinctly get two different values (with the first giving the "correct" value) if I try:
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(float128(2.q)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(2.q) << std::endl;
However, this isn't true for sqrt still. I checked by calculating the sqrt(pi) and comparing to
https://github.com/ned14/boost-trunk/blob/master/libs/multiprecision/test/te...
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
These two lines give me identical results and again only match the first 16 digits.
pie is defined as float128 and I copy/pasted the 100 digit value from the same test_sqrt.cpp given above.
I suspect an error in your declaration of pie, using this:
using namespace boost::multiprecision; __float128 pie = boost::math::constants::pi<__float128>(); std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
I see as output:
1.77245385090551602729816748334114514 1.77245385090551588191942755656782538
John. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks very much John. That was extremely helpful and I think I understand a little more now.
Bridgette
________________________________________
From: Boost-users
Thanks John,
That seems to have worked for sqrt(pi). I'm also pretty new to c++ (I mostly code in fortran) which is probably where a lot of my confusions lie. I don't understand why I don't get the right answer with the declaration of pie I had before. In the real code I want to write I use sqrt of a float128 a lot and I want to be sure I am definitely not loosing precision as my overall calculation is extremely sensitive to precision. So how should I be declaring variables? I notice you had __float128. Does this do something different than just writing float128? I was already using using namespace boost::multi precision.
Without seeing your code, I can't say where you went wrong, but in general: * Make sure you declare variables with the correct type - float128 in your case. * Make sure you declare literals with the correct suffix - otherwise they'll be treated as type double - so make sure they have a Q suffix in your case. * All the std lib functions, plus all the constants, and special functions from Boost.Math should then just work. * Make sure std lib functions are called unqualified so that the correct overload is found via ADL, ie sqrt(variable) not std::sqrt(variable). * In general, try not to reinvent stuff - using constants from Boost.Math is probably less error prone than declaring your own, likewise the special functions etc. Now for the __float128/float128 confusion: __float128 is the compiler supplied hardware type, it's an extension to C++ and there is only minimal support for it in normal C++ (no IO streams or numeric_limits support, function names in libquadmath all have different names to the std ones etc.) So you can program that type directly but it's harder work. Type float128 is a thin wrapper around __float128 and makes it C++ and generic code friendly. Another example: using namespace boost::multiprecision; float128 pi1 = boost::math::constants::pi<float128>(); // returns constant of type float128 float128 pi2 = boost::math::constants::pi<__float128>(); // constant of type __float128 gets converted to float128 on the assignment float128 pi3 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348Q; // DIY constant std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi1) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi2) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pi3) << std::endl; // compare to ready rolled constant from Boost.Math: std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << boost::math::constants::root_pi<float128>() << std::endl; Outputs: 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 1.77245385090551602729816748334114514 Note that the casts within the sqrt call aren't needed since all the variables are the correct type to begin with. HTH, John.
________________________________________ From: Boost-users
on behalf of John Maddock Sent: Saturday, April 30, 2016 7:25:27 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] boost/multiprecision/float128 On 30/04/2016 18:38, Cooper, Bridgette R D wrote:
Hi Paul,
For a moment I thought that worked. It certainly does for log(2). I distinctly get two different values (with the first giving the "correct" value) if I try:
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(float128(2.q)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << log(2.q) << std::endl;
However, this isn't true for sqrt still. I checked by calculating the sqrt(pi) and comparing to
https://github.com/ned14/boost-trunk/blob/master/libs/multiprecision/test/te...
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl;
std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
These two lines give me identical results and again only match the first 16 digits.
pie is defined as float128 and I copy/pasted the 100 digit value from the same test_sqrt.cpp given above.
I suspect an error in your declaration of pie, using this:
using namespace boost::multiprecision; __float128 pie = boost::math::constants::pi<__float128>(); std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(float128(pie)) << std::endl; std::cout << std::setprecision(std::numeric_limits<float128>::max_digits10) << sqrt(pie) << std::endl;
I see as output:
1.77245385090551602729816748334114514 1.77245385090551588191942755656782538
John. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Cooper, Bridgette R D
-
John Maddock
-
Paul A. Bristow