A limitation in the eval mechanism of gmpxx in GMP? - c++

The GNU MP library provides a C++ interface in gmpxx.h which overloads arithmetic operators (among other functions), to make it easier for developers to write mathematical expressions using arbitrary-precision types, just like expressions that use native numerical types (see this answer).
While running code to write this answer, I came across an unexpected behaviour in how the interface handles expressions containing GMP types: passing a subtraction of mpf_t variables directly as an argument to gmp_printf gives the wrong answer, but saving the subtraction result into an intermediary variable works fine.
C++ code:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpf_class actual = 1. / 6;
mpf_class expected("0.166666666666666666666666666666667");
gmp_printf("diff %.50Ff\n", expected - actual);
mpf_class diff = expected - actual;
gmp_printf("diff %.50Ff\n", diff);
}
The output:
diff 0.16666666666666666666700000000000000000000000000000
diff 0.00000000000000000925185853854297150353000000000000
And, assuming the name testgmpxx.cpp, compile with:
g++ testgmpxx.cpp -o testgmpxx -lgmpxx -lgmp
Is this a limitation in the gmpxx.h eval mechanism? Are there are instances where you can't use GMP types on mathematical expressions?

Related

cout causes compile error when using __float128 (error: ambiguous overload for ‘operator<<’) [duplicate]

In my question about Analysis of float/double precision in 32 decimal digits, one answer said to take a look at __float128.
I used it and the compiler could find it, but I can not print it, since the complier can not find the header quadmath.h.
So my questions are:
__float128 is standard, correct?
How to print it?
Isn't quadmath.h standard?
These answers did not help:
Use extern C
Precision in C++
Printing
The ref also did not help.
Note that I do not want to use any non standard library.
[EDIT]
It would be also useful, if that question had an answer, even if the answer was a negative one.
Work in GNU-Fortran! It allows to run the same program in different precision: single (32 bit), double (64 bit), extended (80 bit) and quad (128 bit). You don't have to do any changes in the program, you simply write 'real' for all floating points. The size of floating points is set by compiler options -freal-4-real-8, -freal-4-real-10 and -freal-4-real-16.
Using the boost library was the best answer for me:
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::multiprecision;
float128 su1= 0.33333333333333333q;
cout << "su1=" << su1 << endl;
Remember to link this library:
-lquadmath
No, it's not standard - neither the type nor the header. That's why the type has a double underscore (reserved name). Apparently, quadmath.h provides a quadmath_snprintf method. In C++ you would have used <<, of course.

Declare a Big Integer in C++ [duplicate]

This question already has answers here:
STL BigInt class implementation
(3 answers)
Closed 7 years ago.
I am trying to run this algorithm in c++ in order to get a big number
#include<iostream>
using namespace std;
int main()
{
int num,factorial=1;
cout<<" Enter Number To Find Its Factorial: ";
cin>>num;
for(int a=1;a<=num;a++)
{
factorial=factorial*a;
}
cout<<"Factorial of Given Number is ="<<factorial<<endl;
return 0;
}
How can I declare a Big Integer like in Java instead of an int?
There is no big-integer support in the C++ standard library. A common choice for big-number arithmetic is GMP. After downloading and installing the library, in your code you would #include <gmpxx.h> and declare mpz_class factorial instead of int factorial, then link against GMP.
Linking with GMP can be done in an IDE, by adding GMP in your editor’s compile settings; or by adding -lgmp to your compilation command (e.g., g++ or clang++).
There is no arbitrary-precision arithmetic in c++ standard library. You'll need to implement it yourself using an array of integers, or use an existing non-standard library.
Try unsigned long long int for just convenience.
I just want to leave it as comment but I have low repu for commenting..
There is no standard support for arbitrary-precision integers. However, a few libraries are available for handling big integers:
GNU MP Bignum Library
InfInt
C++ BigInt class
BigDigits multiple-precision arithmetic (in C)
BigIntegerCPP (only supports addition and multiplication)
C++ Big Integer Library (no longer maintained)

Print __float128, without using quadmath_snprintf

In my question about Analysis of float/double precision in 32 decimal digits, one answer said to take a look at __float128.
I used it and the compiler could find it, but I can not print it, since the complier can not find the header quadmath.h.
So my questions are:
__float128 is standard, correct?
How to print it?
Isn't quadmath.h standard?
These answers did not help:
Use extern C
Precision in C++
Printing
The ref also did not help.
Note that I do not want to use any non standard library.
[EDIT]
It would be also useful, if that question had an answer, even if the answer was a negative one.
Work in GNU-Fortran! It allows to run the same program in different precision: single (32 bit), double (64 bit), extended (80 bit) and quad (128 bit). You don't have to do any changes in the program, you simply write 'real' for all floating points. The size of floating points is set by compiler options -freal-4-real-8, -freal-4-real-10 and -freal-4-real-16.
Using the boost library was the best answer for me:
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions/gamma.hpp>
using namespace boost::multiprecision;
float128 su1= 0.33333333333333333q;
cout << "su1=" << su1 << endl;
Remember to link this library:
-lquadmath
No, it's not standard - neither the type nor the header. That's why the type has a double underscore (reserved name). Apparently, quadmath.h provides a quadmath_snprintf method. In C++ you would have used <<, of course.

C++11 round off error using pow() and std::complex

Running the following
#include <iostream>
#include <complex>
int main()
{
std::complex<double> i (0,1);
std::complex<double> comp =pow(i, 2 );
std::cout<<comp<<std::endl;
return 0;
}
gives me the expected result (-1,0) without c++11. However, compiling with c++11 gives the highly annoying (-1,1.22461e-016).
What to do, and what is best practice?
Of course this can be fixed manually by flooring etc., but I would appreciate to know the proper way of addressing the problem.
SYSTEM: Win8.1, using Desktop Qt 5.1.1 (Qt Creator) with MinGW 4.8 32 bit. Using c++11 by adding the flag QMAKE_CXXFLAGS += -std=c++11 in the Qt Creator .pro file.
In C++11 we have a few new overloads of pow(std::complex). GCC has two nonstandard overloads on top of that, one for raising to an int and one for raising to an unsigned int.
One of the new standard overloads (namely std::complex</*Promoted*/> pow(const std::complex<T> &, const U &)) causes an ambiguity when calling pow(i, 2) with the non-standard ones. Their solution is to #ifdef the non-standard ones out in the presence of C++11 and you go from calling the specialized function (which uses successive squaring) to the generic method (which uses pow(double,double) and std::polar).
You need to get into a different mode when you are using floating point numbers. Floating points are APPROXIMATIONS of real numbers.
1.22461e-016 is
0.0000000000000000122461
An engineer would say that IS zero. You will always get such variations (unless you stick to operations on sums of powers of 2 with the same general range.
A value as simple 0.1 cannot be represented exactly with floating point numbers.
The general problem you present has to parts:
1. Dealing with floating point numbers in processing
2. Displaying flooding point numbers.
For the processing, I would wager that doing:
comp = i * i ;
Would give you want you want.
Pow (x, y) is going to do
exp (log (x) * y)
For output, switch to using an F format.

Using Boost.Units and Boost.Multiprecision

I am attempting to write a molecular dynamics program, and I thought that Boost.Units was a logical choice for the variables, and I also decided that Boost.Multiprecision offered a better option than double or long double with respect to round off errors. A combination of the two seems fairly straight forward until I attempt to use a constant, then it breaks down.
#include <boost/multiprecision/gmp.hpp>
#include <boost/units/io.hpp>
#include <boost/units/pow.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/codata/physico-chemical_constants.hpp>
namespace units = boost::units;
namespace si = boost::si;
namespace mp = boost::multiprecision;
units::quantity<si::mass, mp::mpf_float_50> mass = 1.0 * si::kilogram;
units::quantity<si::temperature, mp::mpf_float_50> temperature = 300. * si::kelvin;
auto k_B = si::constants::codata::k_B; // Boltzmann constant
units::quantity<si::velocity, mp::mpf_float_50> velocity = units::root<2>(temperature * k_B / mass);
std::cout << velocity << std::endl;
The output will be 1 M S^-1. If I use long double in lieu of mp::mpf_float_50, then the result is 2.87818e-11 m s^-1. I know that the problem likes within the conversion between the constant and the other data because the constant defaults to a double. I have thought about creating my own Boltzmann constant, but I prefer to use the predefined value if possible.
My question, therefore, is how do I go about using Boost.Multiprecision when I have predefined constants from Boost.Units? If I must concede to using double or long double, then I will, but I suspect that a way exists to convert or utilize the other on the constants.
I am working with Mac OS X 10.7, Xcode 4.6.2, Clang 3.2, Boost 1.53.0 and the C++11 extensions.
I appreciate any help that can be offered.
I'd advise you not to use multiple precision arithmetic for molecular dynamics simulations because the time-step integration will be painfully slow. If the goal is to preserve total energy as much as possible, then just use Verlet or any other symplectic integrator. Multiple precision arithmetic (or long double, or compensated summation with plain double) may be useful for aggregating ensemble averages, though.
Besides, if you write your simulation code using dimensionless (reduced) units you will also get rid of the dependency on Boost.Units.