Pra Sys
asked on
Boost library multiprecision feature in C++ - Can not convert integer constant
Hi,
I was doing some test programming with Boost C++ library and was trying use new feature of multiprecision as given below -
error: conversion from '<unnamed-signed:128>' to non-scalar type 'boost::multiprecision::in t1024_t {aka boost::multiprecision::num ber<boost: :multiprec ision::bac kends::cpp _int_backe nd<1024u, 1024u, (boost::multiprecision::cp p_integer_ type)1u, (boost::multiprecision::cp p_int_chec k_type)0u, void> >}' requested
But if instead of assigning value directly to variable i, if I assign function call factorial(21) then it calculates and prints the same big integer value correctly? Why such a behavior?? sizeof operator returns 136 bytes.
I was doing some test programming with Boost C++ library and was trying use new feature of multiprecision as given below -
#include <\boost\multiprecision\cpp_int.hpp>
#include <iostream>
using boost::multiprecision::int1024_t;
using namespace std;
int1024_t Factorial(int num);
int main()
{
int1024_t i = 51090942171709440000;//Factorial(21);
cout << i << " " << sizeof(i) << endl;
}
int1024_t Factorial(int num)
{
int1024_t fact = 1;
for(int i=num; i>1; --i)
{
fact *= i;
}
return fact;
}
However, when I run this program it gives me below error - error: conversion from '<unnamed-signed:128>' to non-scalar type 'boost::multiprecision::in
But if instead of assigning value directly to variable i, if I assign function call factorial(21) then it calculates and prints the same big integer value correctly? Why such a behavior?? sizeof operator returns 136 bytes.
ASKER
I looked at couple of places. I think we cant post other website links here. But you can check this. It is same anyways.
http://www.boost.org/doc/libs/1_54_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/egs/factorials.html
It uses cpp_int which is of less byte size than int1024_t. I tried using cpp_int as well but same behaviour. In the code above, I am not using basic integral type anywhere which is not sufficient to store such a large number. Thats the reason why I was looking for BigNum implementation and found boost multiprecision. I am not sure why direct assignment is not allowed whereas function return value is being accepted.
http://www.boost.org/doc/libs/1_54_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/egs/factorials.html
It uses cpp_int which is of less byte size than int1024_t. I tried using cpp_int as well but same behaviour. In the code above, I am not using basic integral type anywhere which is not sufficient to store such a large number. Thats the reason why I was looking for BigNum implementation and found boost multiprecision. I am not sure why direct assignment is not allowed whereas function return value is being accepted.
>> whereas function return value is being accepted
I explained that the function does return the type that is required, so I am not surprised with the return value being accepted.
Looking for official boost documentation, I found int1024_t here.
http://www.boost.org/doc/libs/1_55_0/boost/multiprecision/cpp_int.hpp
and I see that it is a typedef of number.
http://www.boost.org/doc/libs/1_55_0/boost/multiprecision/number.hpp
And I see that number& operator*=(parameters) is defined, so no doubt, one of them accepts an int for the RHS.
Just wondering whether this works (I would think not since the = initialization did not work):
int1024_t i(51090942171709440000);
I explained that the function does return the type that is required, so I am not surprised with the return value being accepted.
Looking for official boost documentation, I found int1024_t here.
http://www.boost.org/doc/libs/1_55_0/boost/multiprecision/cpp_int.hpp
and I see that it is a typedef of number.
http://www.boost.org/doc/libs/1_55_0/boost/multiprecision/number.hpp
And I see that number& operator*=(parameters) is defined, so no doubt, one of them accepts an int for the RHS.
Just wondering whether this works (I would think not since the = initialization did not work):
int1024_t i(51090942171709440000);
Also, try appending an L (or better, LL, if it compiles) to the large integer.
long long largeVal = 51090942171709440000L;
Then try:
int1024_t I(largeVal);
If I have time next week, I will try to download boost and see if I can get something to compile. A quick search shows initialization to only small integers.
Wonder if you were to remove those trailing 0's (and possibly other factorizations), whether you could initialize with a smaller number (say a long rather than your long long); and then multiply back in the small factors.
long long largeVal = 51090942171709440000L;
Then try:
int1024_t I(largeVal);
If I have time next week, I will try to download boost and see if I can get something to compile. A quick search shows initialization to only small integers.
Wonder if you were to remove those trailing 0's (and possibly other factorizations), whether you could initialize with a smaller number (say a long rather than your long long); and then multiply back in the small factors.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ok. So as per your experiment, direct assignment to such a large number won't work right? Also what was the size when you used string constructor? I doubt it was 144. I dont have same setup as yours to do exact experiment. Will try to do it on windows 8, minGw g++ and Boost 1.56.
What happens if you copy the code and build it on your setup?
sizeof(r) = 144
ASKER
Sorry for delayed response.
I get same output -
51090942171709440000 51090942171709440000
51090942171709440000 51090942171709440000 0 0
144
I also tried uncommenting below line of your code and enabling C++11 support, but it didnt work. Got usual error.
// constexpr int1024_t ce = 51090942171709440000; // might work in C++11
I think using string constructor works but is an overhead compared to having direct assignment possible.
I get same output -
51090942171709440000 51090942171709440000
51090942171709440000 51090942171709440000 0 0
144
I also tried uncommenting below line of your code and enabling C++11 support, but it didnt work. Got usual error.
// constexpr int1024_t ce = 51090942171709440000; // might work in C++11
I think using string constructor works but is an overhead compared to having direct assignment possible.
>> I think using string constructor works but is an overhead compared to having direct assignment possible.
Agreed. Of course, the string constructor should allow you to enter a number well beyond a 64-bit word.
If performance in instantiating objects is a problem, then just force the construction of a large number to occur before the main() function is called. Then all the overhead is done once in startup.
Agreed. Of course, the string constructor should allow you to enter a number well beyond a 64-bit word.
If performance in instantiating objects is a problem, then just force the construction of a large number to occur before the main() function is called. Then all the overhead is done once in startup.
You are trying to assign a scalar integer to your variable, i, which is not a scalar type.
Factorial returns a int1024_t, so no problem there. Inside of Factorial() is a binary operation *= which operates on int1024_t and int. Apparently * is overloaded within boost::multiprecision::int
Could you post the link you are using that documents int1024_t?