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.
James BondSoftware ProfessionalAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

phoffricCommented:
>> 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?
0
James BondSoftware ProfessionalAuthor Commented:
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.
0
phoffricCommented:
>> 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);
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

phoffricCommented:
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.
0
phoffricCommented:
On Ubuntu 12.04 using g++ version 4.6.3 and boost 1.56, I got the following to compile and run with no errors:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

using namespace std;
using boost::multiprecision::int1024_t;

int1024_t Factorial(int num);

int main()
{
//    constexpr int1024_t ce = 51090942171709440000;  // might work in C++11
    int1024_t r = int1024_t("51090942171709440000"); // use string constructor
    int1024_t f = Factorial(21);
    cout << r << "  " << f << endl;
    
    // Here's a variation of your approach that I alluded to earlier
    int1024_t x(5109094217170944000); // remove a 0
    x *= 10; // put the 0 back in
    int1024_t w(x);
    cout << x << "  " << w << "   " <<  w - x << "  "  << w - r << endl;
    cout << sizeof(w) << 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

output:
51090942171709440000  51090942171709440000
51090942171709440000  51090942171709440000   0  0
144

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
James BondSoftware ProfessionalAuthor Commented:
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.
0
phoffricCommented:
What happens if you copy the code and build it on  your setup?
0
phoffricCommented:
sizeof(r) = 144
0
James BondSoftware ProfessionalAuthor Commented:
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.
0
phoffricCommented:
>> 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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.