Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

cpp_int

#include <boost/multiprecision/cpp_int.hpp>

namespace boost{ namespace multiprecision{

typedef unspecified-type limb_type;

enum cpp_integer_type    { signed_magnitude, unsigned_magnitude };
enum cpp_int_check_type  { checked, unchecked };

template <unsigned MinBits = 0,
          unsigned MaxBits = 0,
          cpp_integer_type SignType = signed_magnitude,
          cpp_int_check_type Checked = unchecked,
          class Allocator = std::allocator<limb_type> >
class cpp_int_backend;
//
// Expression templates default to et_off if there is no allocator:
//
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked>
struct expression_template_default<cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> >
{ static const expression_template_option value = et_off; };

typedef number<cpp_int_backend<> >              cpp_int;    // arbitrary precision integer
typedef rational_adaptor<cpp_int_backend<> >    cpp_rational_backend;
typedef number<cpp_rational_backend>            cpp_rational; // arbitrary precision rational number

// Fixed precision unsigned types:
typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >   uint128_t;
typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >   uint256_t;
typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >   uint512_t;
typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;

// Fixed precision signed types:
typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >     int128_t;
typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >     int256_t;
typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >     int512_t;
typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >   int1024_t;

// Over again, but with checking enabled this time:
typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> >                 checked_cpp_int;
typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> >       checked_cpp_rational_backend;
typedef number<cpp_rational_backend>                                              checked_cpp_rational;

// Checked fixed precision unsigned types:
typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >     checked_uint128_t;
typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >     checked_uint256_t;
typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >     checked_uint512_t;
typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> >   checked_uint1024_t;

// Fixed precision signed types:
typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >       checked_int128_t;
typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >       checked_int256_t;
typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >       checked_int512_t;
typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >     checked_int1024_t;

}} // namespaces

The cpp_int_backend type is normally used via one of the convenience typedefs given above.

This back-end is the "Swiss Army Knife" of integer types as it can represent both fixed and arbitrary precision integer types, and both signed and unsigned types. There are five template arguments:

MinBits

Determines the number of Bits to store directly within the object before resorting to dynamic memory allocation. When zero, this field is determined automatically based on how many bits can be stored in union with the dynamic storage header: setting a larger value may improve performance as larger integer values will be stored internally before memory allocation is required.

MaxBits

Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type. When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic memory allocation will ever be performed: in this situation the Allocator parameter should be set to type void. Note that this parameter should not be used simply to prevent large memory allocations, not only is that role better performed by the allocator, but fixed precision integers have a tendency to allocate all of MaxBits of storage more often than one would expect.

SignType

Determines whether the resulting type is signed or not. Note that for arbitrary precision types this parameter must be signed_magnitude. For fixed precision types then this type may be either signed_magnitude or unsigned_magnitude.

Checked

This parameter has two values: checked or unchecked. See below.

Allocator

The allocator to use for dynamic memory allocation, or type void if MaxBits == MinBits.

When the template parameter Checked is set to checked then the result is a checked-integer, checked and unchecked integers have the following properties:

Condition

Checked-Integer

Unchecked-Integer

Numeric overflow in fixed precision arithmetic

Throws a std::overflow_error.

Performs arithmetic modulo 2MaxBits

Constructing an integer from a value that can not be represented in the target type

Throws a std::range_error.

Converts the value modulo 2MaxBits, signed to unsigned conversions extract the last MaxBits bits of the 2's complement representation of the input value.

Unsigned subtraction yielding a negative value.

Throws a std::range_error.

Yields the value that would result from treating the unsigned type as a 2's complement signed type.

Attempting a bitwise operation on a negative value.

Throws a std::range_error

Yields the value, but not the bit pattern, that would result from performing the operation on a 2's complement integer type.

Things you should know when using this type:

Example:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

int main()
{
   using namespace boost::multiprecision;

   int128_t v = 1;

   // Do some fixed precision arithmetic:
   for(unsigned i = 1; i <= 20; ++i)
      v *= i;

   std::cout << v << std::endl; // prints 2432902008176640000 (i.e. 20!)

   // Repeat at arbitrary precision:
   cpp_int u = 1;
   for(unsigned i = 1; i <= 100; ++i)
      u *= i;

   // prints 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 (i.e. 100!)
   std::cout << u << std::endl;

   return 0;
}

PrevUpHomeNext