Link to home
Start Free TrialLog in
Avatar of Pra Sys
Pra SysFlag for India

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 -

#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;
}

Open in new window

However, when I run this program it gives me below error -

error: conversion from '<unnamed-signed:128>' to non-scalar type 'boost::multiprecision::int1024_t {aka boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<1024u, 1024u, (boost::multiprecision::cpp_integer_type)1u, (boost::multiprecision::cpp_int_check_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.
Avatar of phoffric
phoffric

>> conversion from '<unnamed-signed:128>' to non-scalar type
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::int1024_t to allow for that operation.

Could you post the link you are using that documents int1024_t?
Avatar of Pra Sys

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.
>> 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);
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.
ASKER CERTIFIED SOLUTION
Avatar of phoffric
phoffric

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Pra Sys

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
Avatar of Pra Sys

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 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.