• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 997
  • Last Modified:

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.
0
James Bond
Asked:
James Bond
  • 7
  • 3
1 Solution
 
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now