[/
Copyright 2011 John Maddock.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[library Boost.Multiprecision
[quickbook 1.5]
[copyright 2002-2012 John Maddock and Christopher Kormanyos]
[purpose Multiprecision Number library]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
[authors [Maddock, John], [Kormanyos, Christopher]]
[/last-revision $Date: 2011-07-08 18:51:46 +0100 (Fri, 08 Jul 2011) $]
]
[include html4_symbols.qbk]
[import ../example/gmp_snips.cpp]
[import ../example/mpfr_snips.cpp]
[import ../example/cpp_dec_float_snips.cpp]
[import ../example/tommath_snips.cpp]
[import ../example/cpp_int_snips.cpp]
[import ../example/random_snips.cpp]
[import ../example/safe_prime.cpp]
[import ../example/mixed_integer_arithmetic.cpp]
[template mpfr[] [@http://www.mpfr.org MPFR]]
[template gmp[] [@http://gmplib.org GMP]]
[template mpf_class[] [@http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats mpf_class]]
[template mpfr_class[] [@http://math.berkeley.edu/~wilken/code/gmpfrxx/ mpfr_class]]
[template mpreal[] [@http://www.holoborodko.com/pavel/mpfr/ mpreal]]
[template mpir[] [@http://mpir.org/ MPIR]]
[template tommath[] [@http://libtom.org/?page=features&newsitems=5&whatfile=ltm libtommath]]
[template super[x]''''''[x]'''''']
[template sub[x]''''''[x]'''''']
[template equation[name] '''
''']
[def __cpp_int [link boost_multiprecision.tut.ints.cpp_int cpp_int]]
[def __gmp_int [link boost_multiprecision.tut.ints.gmp_int gmp_int]]
[def __tom_int [link boost_multiprecision.tut.ints.tom_int tom_int]]
[def __gmp_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]]
[def __mpf_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]]
[def __mpfr_float_backend [link boost_multiprecision.tut.floats.mpfr_float mpfr_float]]
[def __cpp_dec_float [link boost_multiprecision.tut.floats.cpp_dec_float cpp_dec_float]]
[def __gmp_rational [link boost_multiprecision.tut.rational.gmp_rational gmp_rational]]
[def __cpp_rational [link boost_multiprecision.tut.rational.cpp_rational cpp_rational]]
[def __tommath_rational [link boost_multiprecision.tut.rational.tommath_rational tommath_rational]]
[section:intro Introduction]
The Multiprecision Library provides [link boost_multiprecision.tut.ints integer],
[link boost_multiprecision.tut.rational rational]
and [link boost_multiprecision.tut.floats floating-point] types in C++ that have more
range and precision than C++'s ordinary built-in types.
The big number types in Multiprecision can be used with a wide
selection of basic mathematical operations, elementary transcendental
functions as well as the functions in Boost.Math.
The Multiprecision types can also interoperate with the
built-in types in C++ using clearly defined conversion rules.
This allows Boost.Multiprecision to be used for all
kinds of mathematical calculations involving integer,
rational and floating-point types requiring extended
range and precision.
Multiprecision consists of a generic interface to the
mathematics of large numbers as well as a selection of
big number back ends, with support for integer, rational and
floating-point types. Boost.Multiprecision provides a selection
of back ends provided off-the-rack in including
interfaces to GMP, MPFR, MPIR, TomMath as well as
its own collection of Boost-licensed, header-only back ends for
integers, rationals and floats. In addition, user-defined back ends
can be created and used with the interface of Multiprecision,
provided the class implementation adheres to the necessary
[link boost_multiprecision.ref.backendconc concepts].
Depending upon the number type, precision may be arbitrarily large
(limited only by available memory), fixed at compile time
(for example 50 or 100 decimal digits), or a variable controlled at run-time
by member functions. The types are expression-template-enabled for
better performance than naive user-defined types.
The Multiprecision library comes in two distinct parts:
* An expression-template-enabled front-end `number`
that handles all the operator overloading, expression evaluation optimization, and code reduction.
* A selection of back-ends that implement the actual arithmetic operations, and need conform only to the
reduced interface requirements of the front-end.
Separation of front-end and back-end allows use of highly refined, but restricted license libraries
where possible, but provides Boost license alternatives for users who must have a portable
unconstrained license. Which is to say some back-ends rely on 3rd party libraries, but a header-only Boost license version is always
available (if somewhat slower).
Should you just wish to cut to the chase and use a fully Boost-licensed number type, then skip to
__cpp_int for multiprecision integers, __cpp_dec_float for multiprecision floating point types
and __cpp_rational for rational types.
The library is often used via one of the predefined typedefs: for example if you wanted an [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision]
integer type using [gmp] as the underlying implementation then you could use:
#include // Defines the wrappers around the GMP library's types
boost::multiprecision::mpz_int myint; // Arbitrary precision integer type.
Alternatively, you can compose your own multiprecision type, by combining `number` with one of the
predefined back-end types. For example, suppose you wanted a 300 decimal digit floating-point type
based on the [mpfr] library. In this case, there's no predefined typedef with that level of precision,
so instead we compose our own:
#include // Defines the Backend type that wraps MPFR
namespace mp = boost::multiprecision; // Reduce the typing a bit later...
typedef mp::number > my_float;
my_float a, b, c; // These variables have 300 decimal digits precision
We can repeat the above example, but with the expression templates disabled (for faster compile times, but slower runtimes)
by passing a second template argument to `number`:
#include // Defines the Backend type that wraps MPFR
namespace mp = boost::multiprecision; // Reduce the typing a bit later...
typedef mp::number, et_off> my_float;
my_float a, b, c; // These variables have 300 decimal digits precision
We can also mix arithmetic operations between different types, provided there is an unambiguous implicit conversion from one
type to the other:
#include
namespace mp = boost::multiprecision; // Reduce the typing a bit later...
mp::int128_t a(3), b(4);
mp::int512_t c(50), d;
d = c * a; // OK, result of mixed arithmetic is an int512_t
Conversions are also allowed:
d = a; // OK, widening conversion.
d = a * b; // OK, can convert from an expression template too.
However conversions that are inherently lossy are either declared explicit or else forbidden altogether:
d = 3.14; // Error implicit conversion from float not allowed.
d = static_cast(3.14); // OK explicit construction is allowed
Mixed arithmetic will fail if the conversion is either ambiguous or explicit:
number, et_off> a(2);
number, et_on> b(3);
b = a * b; // Error, implicit conversion could go either way.
b = a * 3.14; // Error, no operator overload if the conversion would be explicit.
[h4 Move Semantics]
On compilers that support rvalue-references, class `number` is move-enabled if the underlying backend is.
In addition the non-expression template operator overloads (see below) are move aware and have overloads
that look something like:
template
number operator + (number&& a, const number& b)
{
return std::move(a += b);
}
These operator overloads ensure that many expressions can be evaluated without actually generating any temporaries.
However, there are still many simple expressions such as:
a = b * c;
Which don't noticeably benefit from move support. Therefore, optimal performance comes from having both
move-support, and expression templates enabled.
Note that while "moved-from" objects are left in a sane state, they have an unspecified value, and the only permitted
operations on them are destruction or the assignment of a new value. Any other operation should be considered
a programming error and all of our backends will trigger an assertion if any other operation is attempted. This behavior
allows for optimal performance on move-construction (i.e. no allocation required, we just take ownership of the existing
object's internal state), while maintaining usability in the standard library containers.
[h4 Expression Templates]
Class `number` is expression-template-enabled: that means that rather than having a multiplication
operator that looks like this:
template
number operator * (const number& a, const number& b)
{
number result(a);
result *= b;
return result;
}
Instead the operator looks more like this:
template
``['unmentionable-type]`` operator * (const number& a, const number& b);
Where the "unmentionable" return type is an implementation detail that, rather than containing the result
of the multiplication, contains instructions on how to compute the result. In effect it's just a pair
of references to the arguments of the function, plus some compile-time information that stores what the operation
is.
The great advantage of this method is the ['elimination of temporaries]: for example the "naive" implementation
of `operator*` above, requires one temporary for computing the result, and at least another one to return it. It's true
that sometimes this overhead can be reduced by using move-semantics, but it can't be eliminated completely. For example,
lets suppose we're evaluating a polynomial via Horner's method, something like this:
T a[7] = { /* some values */ };
//....
y = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0];
If type `T` is a `number`, then this expression is evaluated ['without creating a single temporary value]. In contrast,
if we were using the [mpfr_class] C++ wrapper for [mpfr] - then this expression would result in no less than 11
temporaries (this is true even though [mpfr_class] does use expression templates to reduce the number of temporaries somewhat). Had
we used an even simpler wrapper around [mpfr] like [mpreal] things would have been even worse and no less that 24 temporaries
are created for this simple expression (note - we actually measure the number of memory allocations performed rather than
the number of temporaries directly, note also that the [mpf_class] wrapper that will be supplied with GMP-5.1 reduces the number of
temporaries to pretty much zero). Note that if we compile with expression templates disabled and rvalue-reference support
on, then actually still have no wasted memory allocations as even though temporaries are created, their contents are moved
rather than copied.
[footnote The actual number generated will depend on the compiler, how well it optimises the code, and whether it supports
rvalue references. The number of 11 temporaries was generated with Visual C++ 10]
[important
Expression templates can radically reorder the operations in an expression, for example:
a = (b * c) * a;
Will get transformed into:
a *= c;
a *= b;
If this is likely to be an issue for a particular application, then they should be disabled.
]
This library also extends expression template support to standard library functions like `abs` or `sin` with `number`
arguments. This means that an expression such as:
y = abs(x);
can be evaluated without a single temporary being calculated. Even expressions like:
y = sin(x);
get this treatment, so that variable 'y' is used as "working storage" within the implementation of `sin`,
thus reducing the number of temporaries used by one. Of course, should you write:
x = sin(x);
Then we clearly can't use `x` as working storage during the calculation, so then a temporary variable
is created in this case.
Given the comments above, you might be forgiven for thinking that expression-templates are some kind of universal-panacea:
sadly though, all tricks like this have their downsides. For one thing, expression template libraries
like this one, tend to be slower to compile than their simpler cousins, they're also harder to debug
(should you actually want to step through our code!), and rely on compiler optimizations being turned
on to give really good performance. Also, since the return type from expressions involving `number`s
is an "unmentionable implementation detail", you have to be careful to cast the result of an expression
to the actual number type when passing an expression to a template function. For example, given:
template
void my_proc(const T&);
Then calling:
my_proc(a+b);
Will very likely result in obscure error messages inside the body of `my_proc` - since we've passed it
an expression template type, and not a number type. Instead we probably need:
my_proc(my_number_type(a+b));
Having said that, these situations don't occur that often - or indeed not at all for non-template functions.
In addition, all the functions in the Boost.Math library will automatically convert expression-template arguments
to the underlying number type without you having to do anything, so:
mpfr_float_100 a(20), delta(0.125);
boost::math::gamma_p(a, a + delta);
Will work just fine, with the `a + delta` expression template argument getting converted to an `mpfr_float_100`
internally by the Boost.Math library.
One other potential pitfall that's only possible in C++11: you should never store an expression template using:
auto my_expression = a + b - c;
unless you're absolutely sure that the lifetimes of `a`, `b` and `c` will outlive that of `my_expression`.
And finally... the performance improvements from an expression template library like this are often not as
dramatic as the reduction in number of temporaries would suggest. For example if we compare this library with
[mpfr_class] and [mpreal], with all three using the underlying [mpfr] library at 50 decimal digits precision then
we see the following typical results for polynomial execution:
[table Evaluation of Order 6 Polynomial.
[[Library] [Relative Time] [Relative number of memory allocations]]
[[number] [1.0 (0.00957s)] [1.0 (2996 total)]]
[[[mpfr_class]] [1.1 (0.0102s)] [4.3 (12976 total)]]
[[[mpreal]] [1.6 (0.0151s)] [9.3 (27947 total)]]
]
As you can see, the execution time increases a lot more slowly than the number of memory allocations. There are
a number of reasons for this:
* The cost of extended-precision multiplication and division is so great, that the times taken for these tend to
swamp everything else.
* The cost of an in-place multiplication (using `operator*=`) tends to be more than an out-of-place
`operator*` (typically `operator *=` has to create a temporary workspace to carry out the multiplication, where
as `operator*` can use the target variable as workspace). Since the expression templates carry out their
magic by converting out-of-place operators to in-place ones, we necessarily take this hit. Even so the
transformation is more efficient than creating the extra temporary variable, just not by as much as
one would hope.
Finally, note that `number` takes a second template argument, which, when set to `et_off` disables all
the expression template machinery. The result is much faster to compile, but slower at runtime.
We'll conclude this section by providing some more performance comparisons between these three libraries,
again, all are using [mpfr] to carry out the underlying arithmetic, and all are operating at the same precision
(50 decimal digits):
[table Evaluation of Boost.Math's Bessel function test data
[[Library] [Relative Time] [Relative Number of Memory Allocations]]
[[mpfr_float_50] [1.0 (5.78s)] [1.0 (1611963)]]
[[number, et_off>[br](but with rvalue reference support)]
[1.1 (6.29s)] [2.64 (4260868)]]
[[[mpfr_class]] [1.1 (6.28s)] [2.45 (3948316)]]
[[[mpreal]] [1.65 (9.54s)] [8.21 (13226029)]]
]
[table Evaluation of Boost.Math's Non-Central T distribution test data
[[Library][Relative Time][Relative Number of Memory Allocations]]
[[number] [1.0 (263s)][1.0 (127710873)]]
[[number, et_off>[br](but with rvalue reference support)]
[1.0 (260s)][1.2 (156797871)]]
[[[mpfr_class]] [1.1 (287s)][2.1 (268336640)]]
[[[mpreal]] [1.5 (389s)][3.6 (466960653)]]
]
The above results were generated on Win32 compiling with Visual C++ 2010, all optimizations on (/Ox),
with MPFR 3.0 and MPIR 2.3.0.
[endsect]
[section:tut Tutorial]
In order to use this library you need to make two choices:
* What kind of number do I want ([link boost_multiprecision.tut.ints integer],
[link boost_multiprecision.tut.floats floating point] or [link boost_multiprecision.tut.rational rational]).
* Which back-end do I want to perform the actual arithmetic (Boost-supplied, GMP, MPFR, Tommath etc)?
[section:ints Integer Types]
The following back-ends provide integer arithmetic:
[table
[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
[[`cpp_int`][boost/multiprecision/cpp_int.hpp][2][None]
[Very versatile, Boost licensed, all C++ integer type which support both [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] and fixed precision integer types.][Slower than [gmp], though typically not as slow as [tommath]]]
[[`gmp_int`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
[[`tom_int`][boost/multiprecision/tommath.hpp][2][[tommath]][Public domain back-end with no licence restrictions.][Slower than [gmp].]]
]
[section:cpp_int cpp_int]
`#include `
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 >
class cpp_int_backend;
//
// Expression templates default to et_off if there is no allocator:
//
template
struct expression_template_default >
{ static const expression_template_option value = et_off; };
typedef number > cpp_int; // arbitrary precision integer
typedef rational_adapter > cpp_rational_backend;
typedef number cpp_rational; // arbitrary precision rational number
// Fixed precision unsigned types:
typedef number > uint128_t;
typedef number > uint256_t;
typedef number > uint512_t;
typedef number > uint1024_t;
// Fixed precision signed types:
typedef number > int128_t;
typedef number > int256_t;
typedef number > int512_t;
typedef number > int1024_t;
// Over again, but with checking enabled this time:
typedef number > checked_cpp_int;
typedef rational_adapter > checked_cpp_rational_backend;
typedef number checked_cpp_rational;
// Checked fixed precision unsigned types:
typedef number > checked_uint128_t;
typedef number > checked_uint256_t;
typedef number > checked_uint512_t;
typedef number > checked_uint1024_t;
// Fixed precision signed types:
typedef number > checked_int128_t;
typedef number > checked_int256_t;
typedef number > checked_int512_t;
typedef number > 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
[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision]
integer types, and both signed and unsigned types. There are five template arguments:
[variablelist
[[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
[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic 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:
[table
[[Condition][Checked-Integer][Unchecked-Integer]]
[[Numeric overflow in fixed precision arithmetic][Throws a `std::overflow_error`.][Performs arithmetic modulo 2[super MaxBits]]]
[[Constructing an integer from a value that can not be represented in the target type][Throws a `std::range_error`.]
[Converts the value modulo 2[super MaxBits], 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:
* Default constructed `cpp_int_backend`s have the value zero.
* Division by zero results in a `std::overflow_error` being thrown.
* Construction from a string that contains invalid non-numeric characters results in a `std::runtime_error` being thrown.
* Since the precision of `cpp_int_backend` is necessarily limited when the allocator parameter is void,
care should be taken to avoid numeric overflow when using this type
unless you actually want modulo-arithmetic behavior.
* The type uses a sign-magnitude representation internally, so type `int128_t` has 128-bits of precision plus an extra sign bit.
In this respect the behaviour of these types differs from built-in 2's complement types. In might be tempting to use a
127-bit type instead, and indeed this does work, but behaviour is still slightly different from a 2's complement built-in type
as the min and max values are identical (apart from the sign), where as they differ by one for a true 2's complement type.
That said it should be noted that there's no requirement for built-in types to be 2's complement either - it's simply that this
is the most common format by far.
* Attempting to print negative values as either an Octal or Hexadecimal string results in a `std::runtime_error` being thrown,
this is a direct consequence of the sign-magnitude representation.
* The fixed precision types `[checked_][u]intXXX_t` have expression template support turned off - it seems to make little
difference to the performance of these types either way - so we may as well have the faster compile times by turning
the feature off.
* Unsigned types support subtraction - the result is "as if" a 2's complement operation had been performed as long as they are not
['checked-integers] (see above).
In other words they behave pretty much as a built in integer type would in this situation. So for example if we were using
`uint128_t` then `uint128_t(1)-4` would result in the value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD`
of type `uint128_t`. However, had this operation been performed on `checked_uint128_t` then a `std::range_error` would have
been thrown.
* Unary negation of unsigned types results in a compiler error (static assertion).
* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
* When used at fixed precision, the size of this type is always one machine word larger than you would expect for an N-bit integer:
the extra word stores both the sign, and how many machine words in the integer are actually in use.
The latter is an optimisation for larger fixed precision integers, so that a 1024-bit integer has almost the same performance
characterists as a 128-bit integer, rather than being 4 times slower for addition and 16 times slower for multiplication
(assuming the values involved would always fit in 128 bits).
Typically this means you can use
an integer type wide enough for the "worst case senario" with only minor performance degradation even if most of the time
the arithmetic could in fact be done with a narrower type.
* When used at fixed precision and MaxBits is smaller than the number of bits in the largest native integer type, then
internally `cpp_int_backend` switches to a "trivial" implementation where it is just a thin wrapper around a single
integer. Note that it will still be slightly slower than a bare native integer, as it emulates a
signed-magnitude representation rather than simply using the platforms native sign representation: this ensures
there is no step change in behavior as a cpp_int grows in size.
[h5 Example:]
[cpp_int_eg]
[endsect]
[section:gmp_int gmp_int]
`#include `
namespace boost{ namespace multiprecision{
class gmp_int;
typedef number mpz_int;
}} // namespaces
The `gmp_int` back-end is used via the typedef `boost::multiprecision::mpz_int`. It acts as a thin wrapper around the [gmp] `mpz_t`
to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision.
As well as the usual conversions from arithmetic and string types, type `mpz_int` is copy constructible and assignable from:
* The [gmp] native types: `mpf_t`, `mpz_t`, `mpq_t`.
* Instances of `number` that are wrappers around those types: `number >`, `number`.
It's also possible to access the underlying `mpz_t` via the `data()` member function of `gmp_int`.
Things you should know when using this type:
* No changes are made to the GMP library's global settings - so you can safely mix this type with
existing code that uses [gmp].
* Default constructed `gmp_int`s have the value zero (this is GMP's default behavior).
* Formatted IO for this type does not support octal or hexadecimal notation for negative values,
as a result performing formatted output on this type when the argument is negative and either of the flags
`std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
as a valid integer.
* Division by zero results in a `std::overflow_error` being thrown.
* Although this type is a wrapper around [gmp] it will work equally well with [mpir]. Indeed use of [mpir]
is recommended on Win32.
* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
[h5 Example:]
[mpz_eg]
[endsect]
[section:tom_int tom_int]
`#include `
namespace boost{ namespace multiprecision{
class tommath_int;
typedef number tom_int;
}} // namespaces
The `tommath_int` back-end is used via the typedef `boost::multiprecision::tom_int`. It acts as a thin wrapper around the [tommath] `tom_int`
to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision.
Things you should know when using this type:
* Default constructed objects have the value zero (this is [tommath]'s default behavior).
* Although `tom_int` is mostly a drop in replacement for the builtin integer types, it should be noted that it is a
rather strange beast as it's a signed type that is not a 2's complement type. As a result the bitwise operations
`| & ^` will throw a `std::runtime_error` exception if either of the arguments is negative. Similarly the complement
operator`~` is deliberately not implemented for this type.
* Formatted IO for this type does not support octal or hexadecimal notation for negative values,
as a result performing formatted output on this type when the argument is negative and either of the flags
`std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
as a valid integer.
* Division by zero results in a `std::overflow_error` being thrown.
[h5 Example:]
[tommath_eg]
[endsect]
[section:egs Examples]
[import ../example/integer_examples.cpp]
[section:factorials Factorials]
[FAC1]
[endsect]
[section:bitops Bit Operations]
[BITOPS]
[endsect]
[endsect]
[endsect]
[section:floats Floating Point Numbers]
The following back-ends provide floating point arithmetic:
[table
[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
[[`cpp_dec_float`][boost/multiprecision/cpp_dec_float.hpp][10][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]]
[[`mpf_float`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
[[`mpfr_float`][boost/multiprecision/mpfr.hpp][2][[gmp] and [mpfr]][Very fast and efficient back-end, with its own standard library implementation.][Dependency on GNU licensed [gmp] and [mpfr] libraries.]]
]
[section:cpp_dec_float cpp_dec_float]
`#include `
namespace boost{ namespace multiprecision{
template
class cpp_dec_float;
typedef number > cpp_dec_float_50;
typedef number > cpp_dec_float_100;
}} // namespaces
The `cpp_dec_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free)
floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with
much greater precision.
Type `cpp_dec_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter.
The typedefs `cpp_dec_float_50` and `cpp_dec_float_100` provide arithmetic types at 50 and 100 decimal digits precision
respectively. Optionally, you can specify an integer type to use for the exponent, this defaults to a 32-bit integer type
which is more than large enough for the vast majority of use cases, but larger types such as `long long` can also be specified
if you need a truely huge exponent range.
Normally `cpp_dec_float` allocates no memory: all of the space required for its digits are allocated
directly within the class. As a result care should be taken not to use the class with too high a digit count
as stack space requirements can grow out of control. If that represents a problem then providing an allocator
as the final template parameter causes `cpp_dec_float` to dynamically allocate the memory it needs: this
significantly reduces the size of `cpp_dec_float` and increases the viable upper limit on the number of digits
at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive
as the digit count grows: the current implementation really isn't optimized or designed for large digit counts.
There is full standard library and `numeric_limits` support available for this type.
Things you should know when using this type:
* Default constructed `cpp_dec_float`s have a value of zero.
* The radix of this type is 10. As a result it can behave subtly differently from base-2 types.
* The type has a number of internal guard digits over and above those specified in the template argument.
Normally these should not be visible to the user.
* The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow,
and a NaN is generated for any mathematically undefined operation.
* There is a `std::numeric_limits` specialisation for this type.
* Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type -
for example you can convert from `number >` to `number >`.
Narrowing conversions are truncating and `explicit`.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
as a valid floating point number.
* The actual precision of a `cpp_dec_float` is always slightly higher than the number of digits specified in
the template parameter, actually how much higher is an implementation detail but is always at least 8 decimal
digits.
* Operations involving `cpp_dec_float` are always truncating. However, note that since their are guard digits
in effect, in practice this has no real impact on accuracy for most use cases.
[h5 cpp_dec_float example:]
[cpp_dec_float_eg]
[endsect]
[section:gmp_float gmp_float]
`#include `
namespace boost{ namespace multiprecision{
template
class gmp_float;
typedef number > mpf_float_50;
typedef number > mpf_float_100;
typedef number > mpf_float_500;
typedef number > mpf_float_1000;
typedef number > mpf_float;
}} // namespaces
The `gmp_float` back-end is used in conjunction with `number` : it acts as a thin wrapper around the [gmp] `mpf_t`
to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
much greater precision.
Type `gmp_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
at variable precision by setting the template argument to zero. The typedefs mpf_float_50, mpf_float_100,
mpf_float_500, mpf_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
respectively. The typedef mpf_float provides a variable precision type whose precision can be controlled via the
`number`s member functions.
[note This type only provides standard library and `numeric_limits` support when the precision is fixed at compile time.]
As well as the usual conversions from arithmetic and string types, instances of `number >` are
copy constructible and assignable from:
* The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`.
* The `number` wrappers around those types: `number >`, `number`, `number`.
It's also possible to access the underlying `mpf_t` via the `data()` member function of `gmp_float`.
Things you should know when using this type:
* Default constructed `gmp_float`s have the value zero (this is the [gmp] library's default behavior).
* No changes are made to the [gmp] library's global settings, so this type can be safely mixed with
existing [gmp] code.
* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
* It is not possible to round-trip objects of this type to and from a string and get back
exactly the same value. This appears to be a limitation of [gmp].
* Since the underlying [gmp] types have no notion of infinities or NaN's, care should be taken
to avoid numeric overflow or division by zero. That latter will result in a std::overflow_error being thrown,
while generating excessively large exponents may result in instability of the underlying [gmp]
library (in testing, converting a number with an excessively large or small exponent
to a string caused [gmp] to segfault).
* This type can equally be used with [mpir] as the underlying implementation - indeed that is
the recommended option on Win32.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
as a valid floating point number.
* Division by zero results in a `std::overflow_error` being thrown.
[h5 [gmp] example:]
[mpf_eg]
[endsect]
[section:mpfr_float mpfr_float]
`#include `
namespace boost{ namespace multiprecision{
enum mpfr_allocation_type
{
allocate_stack,
allocate_dynamic
};
template
class mpfr_float_backend;
typedef number > mpfr_float_50;
typedef number > mpfr_float_100;
typedef number > mpfr_float_500;
typedef number > mpfr_float_1000;
typedef number > mpfr_float;
typedef number > static_mpfr_float_50;
typedef number > static_mpfr_float_100;
}} // namespaces
The `mpfr_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfr] `mpfr_t`
to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with
much greater precision.
Type `mpfr_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or
at variable precision by setting the template argument to zero. The typedefs mpfr_float_50, mpfr_float_100,
mpfr_float_500, mpfr_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
respectively. The typedef mpfr_float provides a variable precision type whose precision can be controlled via the
`number`s member functions.
In addition the second template parameter lets you choose between dynamic allocation (the default,
and uses MPFR's normal allocation routines),
or stack allocation (where all the memory required for the underlying data types is stored
within `mpfr_float_backend`). The latter option can result in significantly faster code, at the
expense of growing the size of `mpfr_float_backend`. It can only be used at fixed precision, and
should only be used for lower digit counts. Note that we can not guarentee that using `allocate_stack`
won't cause any calls to mpfr's allocation routines, as mpfr may call these inside it's own code.
The following table gives an idea of the performance tradeoff's at 50 decimal digits
precision[footnote Compiled with VC++10 and /Ox, with MPFR-3.0.0 and MPIR-2.3.0]:
[table
[[Type][Bessel function evaluation, relative times]]
[[`number, et_on>`][1.0 (5.5s)]]
[[`number, et_off>`][1.05 (5.8s)]]
[[`number, et_on>`][1.05 (5.8s)]]
[[`number, et_off>`][1.16 (6.4s)]]
]
[note This type only provides `numeric_limits` support when the precision is fixed at compile time.]
As well as the usual conversions from arithmetic and string types, instances of `number >` are
copy constructible and assignable from:
* The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`.
* The [mpfr] native type `mpfr_t`.
* The `number` wrappers around those types: `number >`, `number >`, `number`, `number`.
It's also possible to access the underlying `mpf_t` via the data() member function of `gmp_float`.
Things you should know when using this type:
* A default constructed `mpfr_float_backend` is set to a NaN (this is the default [mpfr] behavior).
* All operations use round to nearest.
* No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing
[mpfr] or [gmp] code.
* The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32.
* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted
as a valid floating point number.
* Division by zero results in an infinity.
[h5 [mpfr] example:]
[mpfr_eg]
[endsect]
[section:fp_eg Examples]
[import ../example/floating_point_examples.cpp]
[section:aos Area of Circle]
[AOS1]
[AOS2]
[AOS3]
[endsect]
[section:jel Defining a Special Function.]
[JEL]
[endsect]
[section:nd Calculating a Derivative]
[ND1]
[ND2]
[ND3]
[endsect]
[section:gi Calculating an Integral]
[GI1]
[GI2]
[endsect]
[section:poly_eg Polynomial Evaluation]
[POLY]
[endsect]
[endsect]
[endsect]
[section:rational Rational Number Types]
The following back-ends provide rational number arithmetic:
[table
[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
[[`cpp_rational`][boost/multiprecision/cpp_int.hpp][2][None][An all C++ Boost-licensed implementation.][Slower than [gmp].]]
[[`gmp_rational`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]]
[[`tommath_rational`][boost/multiprecision/tommath.hpp][2][[tommath]][All C/C++ implementation that's Boost Software Licence compatible.][Slower than [gmp].]]
[[`rational_adapter`][boost/multiprecision/rational_adapter.hpp][N/A][none][All C++ adapter that allows any integer back-end type to be used as a rational type.][Requires an underlying integer back-end type.]]
[[`boost::rational`][boost/rational.hpp][N/A][None][A C++ rational number type that can used with any `number` integer type.][The expression templates used by `number` end up being "hidden" inside `boost::rational`: performance may well suffer as a result.]]
]
[section:cpp_rational cpp_rational]
`#include `
namespace boost{ namespace multiprecision{
typedef rational_adapter > cpp_rational_backend;
typedef number cpp_rational;
}} // namespaces
The `cpp_rational_backend` type is used via the typedef `boost::multiprecision::cpp_rational`. It provides
a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
As well as the usual conversions from arithmetic and string types, instances of `cpp_rational` are copy constructible
and assignable from type `cpp_int`.
There is also a two argument constructor that accepts a numerator and denominator: both of type `cpp_int`.
There are also non-member functions:
cpp_int numerator(const cpp_rational&);
cpp_int denominator(const cpp_rational&);
which return the numerator and denominator of the number.
Things you should know when using this type:
* Default constructed `cpp_rational`s have the value zero.
* Division by zero results in a `std::overflow_error` being thrown.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
interpreted as a valid rational number.
[h5 Example:]
[cpp_rational_eg]
[endsect]
[section:gmp_rational gmp_rational]
`#include `
namespace boost{ namespace multiprecision{
class gmp_rational;
typedef number mpq_rational;
}} // namespaces
The `gmp_rational` back-end is used via the typedef `boost::multiprecision::mpq_rational`. It acts as a thin wrapper around the [gmp] `mpq_t`
to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
As well as the usual conversions from arithmetic and string types, instances of `number` are copy constructible
and assignable from:
* The [gmp] native types: `mpz_t`, `mpq_t`.
* `number`.
There is also a two-argument constructor that accepts a numerator and denominator (both of type `number`).
There are also non-member functions:
mpz_int numerator(const mpq_rational&);
mpz_int denominator(const mpq_rational&);
which return the numerator and denominator of the number.
It's also possible to access the underlying `mpq_t` via the `data()` member function of `mpq_rational`.
Things you should know when using this type:
* Default constructed `mpq_rational`s have the value zero (this is the [gmp] default behavior).
* Division by zero results in a `std::overflow_error` being thrown.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
interpreted as a valid rational number.
* No changes are made to the [gmp] library's global settings, so this type can coexist with existing
[gmp] code.
* The code can equally be used with [mpir] as the underlying library - indeed that is the preferred option on Win32.
[h5 Example:]
[mpq_eg]
[endsect]
[section:tommath_rational tommath_rational]
`#include `
namespace boost{ namespace multiprecision{
typedef rational_adpater tommath_rational;
typedef number tom_rational;
}} // namespaces
The `tommath_rational` back-end is used via the typedef `boost::multiprecision::tom_rational`. It acts as a thin wrapper around
`boost::rational`
to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision.
The advantage of using this type rather than `boost::rational` directly, is that it is expression-template enabled,
greatly reducing the number of temporaries created in complex expressions.
There are also non-member functions:
tom_int numerator(const tom_rational&);
tom_int denominator(const tom_rational&);
which return the numerator and denominator of the number.
Things you should know when using this type:
* Default constructed `tom_rational`s have the value zero (this the inherited Boost.Rational behavior).
* Division by zero results in a `std::overflow_error` being thrown.
* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be
interpreted as a valid rational number.
* No changes are made to [tommath]'s global state, so this type can safely coexist with other [tommath] code.
* Performance of this type has been found to be pretty poor - this need further investigation - but it appears that Boost.Rational
needs some improvement in this area.
[h5 Example:]
[mp_rat_eg]
[endsect]
[section:br Use With Boost.Rational]
All of the integer types in this library can be used as template arguments to `boost::rational`.
Note that using the library in this way largely negates the effect of the expression templates in `number`.
[endsect]
[section:rational_adapter rational_adapter]
namespace boost{ namespace multiprecision{
template
class rational_adpater;
}}
The class template `rational_adapter` is a back-end for `number` which converts any existing integer back-end
into a rational-number back-end.
So for example, given an integer back-end type `MyIntegerBackend`, the use would be something like:
typedef number MyInt;
typedef number > MyRational;
MyRational r = 2;
r /= 3;
MyInt i = numerator(r);
assert(i == 2);
[endsect]
[endsect]
[section:conversions Constructing and Interconverting Between Number Types]
All of the number types that are based on `number` have certain conversion rules in common.
In particular:
* Any number type can be constructed (or assigned) from any builtin arithmetic type, as long
as the conversion isn't lossy (for example float to int conversion):
cpp_dec_float_50 df(0.5); // OK construction from double
cpp_int i(450); // OK constructs from signed int
cpp_int j = 3.14; // Error, lossy conversion.
* A number can be explicitly constructed from an arithmetic type, even when the conversion is lossy:
cpp_int i(3.14); // OK explicit conversion
i = static_cast(3.14) // OK explicit conversion
i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above
i = 3.14; // Error, no implicit assignment operator for lossy conversion.
cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion.
* A `number` can be converted to any built in type, via the `convert_to` member function:
mpz_int z(2);
int i = z.template convert_to(); // sets i to 2
Additional conversions may be supported by particular backends.
* A `number` can be converted to any built in type, via an explicit conversion operator:
this functionality is only available on compilers supporting C++11's explicit conversion syntax.
mpz_int z(2);
int i = z; // Error, implicit conversion not allowed.
int j = static_cast(z); // OK explicit conversion.
* Any number type can be ['explicitly] constructed (or assigned) from a `const char*` or a `std::string`:
// pi to 50 places from a string:
cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510");
// Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly:
cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000");
// Invalid input always results in a std::runtime_error being thrown:
i = static_cast("3.14");
// implicit conversions from strings are not allowed:
i = "23"; // Error, no assignment operator for implicit conversion from string
// assign member function, avoids having to create a temporary via a static_cast:
i.assign("23"); // OK
* Any number type will interoperate with the builtin types in arithmetic expressions as long as the conversions
are not lossy:
// pi to 50 places from a string:
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
// Multiply by 2 - using an integer literal here is usually more efficient
// than constructing a temporary:
df *= 2;
// You can't mix integer types with floats though:
cpp_int i = 2;
i *= 3.14; // Error, no *= operator will be found.
* Any number type can be streamed to and from the C++ iostreams:
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
// Now print at full precision:
std::cout << std::setprecision(std::numeric_limits::max_digits10)
<< df << std::endl
cpp_int i = 1;
i <<= 256;
// Now print in hex format with prefix:
std::cout << std::hex << std::showbase << i << std::endl;
* Interconversions between number types of the same family are allowed and are implicit conversions if no
loss of precision is involved, and explicit if it is:
int128_t i128 = 0;
int266_t i256 = i128; // OK implicit widening conversion
i128_t = i256; // Error, no assignment operator found, narrowing conversion is explict
i128_t = static_cast(i256); // OK, explicit narrowing conversion
mpz_int z = 0;
mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit
mpf_float_50 f50 = 2;
f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision.
f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
* Some interconversions between number types are completely generic, and are always available, albeit the conversions are always ['explicit]:
cpp_int cppi(2);
// We can always convert between numbers of the same category -
// int to int, rational to rational, or float to float, so this is OK
// as long as we use an explicit conversion:
mpz_int z(cppi);
// We can always promote from int to rational, int to float, or rational to float:
cpp_rational cppr(cppi); // OK, int to rational
cpp_dec_float_50 df(cppi); // OK, int to float
df = static_cast(cppr); // OK, explicit rational to float conversion
// However narrowing and/or implicit conversions always fail:
cppi = df; // Compiler error, conversion not allowed
* Other interconversions may be allowed as special cases, whenever the backend allows it:
mpf_t m; // Native GMP type.
mpf_init_set_ui(m, 0); // set to a value;
mpf_float i(m); // copies the value of the native type.
More information on what additional types a backend supports conversions from are given in the tutorial for each backend.
The converting constructor will be implict if the backend's converting constructor is also implicit, and explicit if the
backends converting constructor is also explicit.
[endsect]
[section:random Generating Random Numbers]
Random numbers are generated in conjunction with Boost.Random. However, since Boost.Random is unaware
of [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] numbers, it's necessary to include the header:
#include
In order to act as a bridge between the two libraries.
Integers with /N/ random bits are generated using `independent_bits_engine`:
[random_eg1]
Alternatively we can generate integers in a given range using `uniform_int_distribution`, this will
invoke the underlying engine multiple times to build up the required number of bits in the result:
[random_eg2]
Floating point values in \[0,1) are generated using `uniform_01`, the trick here is to ensure
that the underlying generator produces as many random bits as there are digits in the floating
point type. As above `independent_bits_engine` can be used for this purpose, note that we also have to
convert decimal digits (in the floating point type) to bits (in the random number generator):
[random_eg3]
Finally, we can modify the above example to produce numbers distributed according to some distribution:
[random_eg4]
[endsect]
[section:primetest Primality Testing]
The library implements a Miller-Rabin test for primality:
#include
template
bool miller_rabin_test(const number& n, unsigned trials, Engine& gen);
template
bool miller_rabin_test(const number& n, unsigned trials);
These functions perform a Miller-Rabin test for primality, if the result is `false` then /n/ is definitely composite,
while if the result is `true` then /n/ is prime with probability ['0.25^trials]. The algorithm used performs some
trial divisions to exclude small prime factors, does one Fermat test to exclude many more composites, and then
uses the Miller-Rabin algorithm straight out of
Knuth Vol 2, which recommends 25 trials for a pretty strong likelihood that /n/ is prime.
The third optional argument is for a Uniform Random Number Generator from Boost.Random. When not provided the `mt19937`
generator is used. Note that when producing random primes then you should probably use a different random number generator
to produce candidate prime numbers for testing, than is used internally by `miller_rabin_test` for determining
whether the value is prime. It also helps of course to seed the generators with some source of randomness.
The following example searches for a prime `p` for which `(p-1)/2` is also probably prime:
[safe_prime]
[endsect]
[section:lits Literal Types and `constexpr` Support]
There is limited support for `constexpr` in the library, currently the `number` front end supports `constexpr`
on default construction and all forwarding constructors, but not on any of the non-member operators. So if
some type `B` is a literal type, then `number` is also a literal type, and you will be able to
compile-time-construct such a type from any literal that `B` is compile-time-constructible from.
However, you will not be able to perform compile-time arithmetic on such types.
Currently the only backend type provided by the library that is also a literal type are instantiations
of `cpp_int_backend` where the Allocator parameter is type `void`, and the Checked parameter is
`boost::multiprecision::unchecked`.
For example:
using namespace boost::multiprecision;
constexpr int128_t i = 0; // OK, fixed precision int128_t has no allocator.
constexpr uint1024_t j = 0xFFFFFFFF00000000uLL; // OK, fixed precision uint1024_t has no allocator.
constexpr checked_uint128_t k = -1; // Error, checked type is not a literal type as we need runtime error checking.
constexpr cpp_int l = 2; // Error, type is not a literal as it performs memory management.
[endsect]
[section:rounding Rounding Rules for Conversions]
As a general rule, all conversions between unrelated types are performed using basic arithmetic operations, therefore
conversions are either exact, or follow the same rounding rules as arithmetic for the type in question.
The following table summarises the situation for conversions from native types:
[table
[[Backend][Rounding Rules]]
[[__cpp_int][Conversions from integer types are exact if the target has sufficient precision, otherwise they
truncate to the first 2^MaxBits bits (modulo arithmetic). Conversions from floating point types
are truncating to the nearest integer.]]
[[__gmp_int][Conversions are performed by the GMP library except for conversion from `long double` which is truncating.]]
[[__tom_int][Conversions from floating point types are truncating, all others are performed by libtommath and are exact.]]
[[__gmp_float][Conversions are performed by the GMP library except for conversion from `long double` which should be exact
provided the target type has as much precision as a `long double`.]]
[[__mpfr_float_backend][All conversions are performed by the underlying MPFR library.]]
[[__cpp_dec_float][All conversions are performed using basic arithmetic operations and are truncating.]]
[[__gmp_rational][See __gmp_int]]
[[__cpp_rational][See __cpp_int]]
[[__tommath_rational][See __tom_int]]
]
[endsect]
[section:mixed Mixed Precision Arithmetic]
Mixed precision arithmetic is fully supported by the library.
There are two different forms:
* Where the operands are of different precision.
* Where the operands are of the same precision, but yield a higher precision result.
[h4 Mixing Operands of Differing Precision]
If the arguments to a binary operator are of different precision, then the operation is allowed
as long as there is an unambiguous implicit conversion from one argument type to the other.
In all cases the arithmetic is performed "as if" the lower precision type is promoted to the
higher precision type before applying the operator. However, particular backends may optimise
this and avoid actually creating a temporary if they are able to do so.
For example:
mpfr_float_50 a(2), b;
mpfr_float_100 c(3), d;
static_mpfr_float_50 e(5), f;
mpz_int i(20);
d = a * c; // OK, result of operand is an mpfr_float_100.
b = a * c; // Error, can't convert the result to an mpfr_float_50 as it will lose digits.
f = a * e; // Error, operator is ambiguous, result could be of either type.
f = e * i; // OK, unambiguous conversion from mpz_int to static_mpfr_float_50
[h4 Operands of the Same Precision]
Sometimes you want to apply an operator to two arguments of the same precision in
such a way as to obtain a result of higher precision. The most common situation
occurs with fixed precision integers, where you want to multiply two N-bit numbers
to obtain a 2N-bit result. This is supported in this library by the following
free functions:
template
ResultType& add(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
These functions apply the named operator to the arguments ['a] and ['b] and store the
result in ['result], returning ['result]. In all cases they behave "as if"
arguments ['a] and ['b] were first promoted to type `ResultType` before applying the
operator, though particular backends may well avoid that step by way of an optimization.
The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2`
may be either instances of class `number` or native integer types. The latter is an optimization
that allows arithmetic to be performed on native integer types producing an extended precision result.
For example:
[mixed_eg]
Produces the output:
[mixed_output]
[h4 Backends With Optimized Mixed Precision Arithmetic]
The following backends have at least some direct support for mixed precision arithmetic,
and therefore avoid creating unnecessary temporaries when using the interfaces above.
Therefore when using these types it's more efficient to use mixed precision arithmetic,
than it is to explicitly cast the operands to the result type:
__mpfr_float_backend, __mpf_float, __cpp_int.
[endsect]
[endsect]
[section:ref Reference]
[section:number number]
[h4 Synopsis]
namespace boost{ namespace multiprecision{
enum expression_template_option { et_on = 1, et_off = 0 };
template struct expression_template_default
{ static const expression_template_option value = et_on; };
template ::value>
class number
{
number();
number(see-below);
number& operator=(see-below);
number& assign(see-below);
// Member operators
number& operator+=(const ``['see-below]``&);
number& operator-=(const ``['see-below]``&);
number& operator*=(const ``['see-below]``&);
number& operator/=(const ``['see-below]``&);
number& operator++();
number& operator--();
number operator++(int);
number operator--(int);
number& operator%=(const ``['see-below]``&);
number& operator&=(const ``['see-below]``&);
number& operator|=(const ``['see-below]``&);
number& operator^=(const ``['see-below]``&);
number& operator<<=(const ``['integer-type]``&);
number& operator>>=(const ``['integer-type]``&);
// Use in Boolean context:
operator ``['convertible-to-bool-type]``()const;
// swap:
void swap(number& other);
// Sign:
bool is_zero()const;
int sign()const;
// string conversion:
std::string str()const;
// Generic conversion mechanism
template
T convert_to()const;
template
explicit operator T ()const;
// precision control:
static unsigned default_precision();
static void default_precision(unsigned digits10);
unsigned precision()const;
void precision(unsigned digits10);
// Comparison:
int compare(const number& o)const;
template
typename enable_if >, int>::type
compare(const V& o)const;
// Access to the underlying implementation:
Backend& backend();
const Backend& backend()const;
};
// Non member operators:
``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&);
// Integer only operations:
``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&);
``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&);
// Comparison operators:
bool operator==(const ``['see-below]``&, const ``['see-below]``&);
bool operator!=(const ``['see-below]``&, const ``['see-below]``&);
bool operator< (const ``['see-below]``&, const ``['see-below]``&);
bool operator> (const ``['see-below]``&, const ``['see-below]``&);
bool operator<=(const ``['see-below]``&, const ``['see-below]``&);
bool operator>=(const ``['see-below]``&, const ``['see-below]``&);
// Swap:
template
void swap(number& a, number& b);
// iostream support:
template
std::ostream& operator << (std::ostream& os, const number& r);
std::ostream& operator << (std::ostream& os, const ``['unmentionable-expression-template-type]``& r);
template
std::istream& operator >> (std::istream& is, number& r);
// Arithmetic with a higher precision result:
template
ResultType& add(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
// Non-member function standard library support:
``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` lround (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` llround(const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, int);
``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, int*);
``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
// Traits support:
template
struct component_type;
template
struct number_category;
template
struct is_number;
template
struct is_number_expression;
// Integer specific functions:
``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``&, unsigned);
``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m);
template
void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y,
number& q, number& r);
template
Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val);
unsigned lsb(const ``['number-or-expression-template-type]``& x);
template
bool bit_test(const number& val, unsigned index);
template
number& bit_set(number& val, unsigned index);
template
number& bit_unset(number& val, unsigned index);
template
number& bit_flip(number& val, unsigned index);
template
bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen);
bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials);
// Rational number support:
typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&);
typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&);
}} // namespaces
namespace boost{ namespace math{
// Boost.Math interoperability functions:
int fpclassify (const ``['number-or-expression-template-type]``&, int);
bool isfinite (const ``['number-or-expression-template-type]``&, int);
bool isnan (const ``['number-or-expression-template-type]``&, int);
bool isinf (const ``['number-or-expression-template-type]``&, int);
bool isnormal (const ``['number-or-expression-template-type]``&, int);
}} // namespaces
// numeric_limits support:
namespace std{
template
struct numeric_limits >
{
/* Usual members here */
};
}
[h4 Description]
enum expression_template_option { et_on = 1, et_off = 0 };
This enumerated type is used to specify whether expression templates are turned on (et_on) or turned off (et_off).
template struct expression_template_default
{ static const expression_template_option value = et_on; };
This traits class specifies the default expression template option to be used with a particular Backend type.
It defaults to `et_on`.
template ::value>
class number;
Class `number` has two template arguments:
[variablelist
[[Backend][The actual arithmetic back-end that does all the work.]]
[[ExpressionTemplates][A Boolean value: when `et_on`, then expression templates are enabled, otherwise when set to `et_off` they are disabled.
The default for this parameter is computed via the traits class `expression_template_default` whose member `value` defaults to `et_on` unless
the the traits class is specialized for a particular backend.]]
]
number();
number(see-below);
number& operator=(see-below);
number& assign(see-below);
Type `number` is default constructible, and both copy constructible and assignable from:
* Itself.
* An expression template which is the result of one of the arithmetic operators.
* Any builtin arithmetic type, as long as the result would not be lossy (for example float to integer conversion).
* Any type that the Backend is implicitly constructible or assignable from.
* An rvalue reference to another `number`. Move-semantics are used for construction if the backend also
supports rvalue reference construction. In the case of assignment, move semantics are always supported
when the argument is an rvalue reference irrespective of the backend.
* Any type in the same family, as long as no loss of precision is involved. For example from `int128_t` to `int256_t`,
or `cpp_dec_float_50` to `cpp_dec_float_100`.
Type `number` is explicitly constructible from:
* Any type mentioned above.
* A `std::string` or any type which is convertible to `const char*`.
* Any arithmetic type (including those that would result in lossy conversions).
* Any type in the same family, including those that result in loss of precision.
* Any type that the Backend is explicitly constructible from.
* Any pair of types for which a generic interconversion exists: that is from integer to integer, integer
to rational, integer to float, rational to rational, rational to float, or float to float.
The assign member function is available for any type for which an explicit converting constructor exists.
It is intended to be used where a temporary generated from an explicit assignment would be expensive, for example:
mpfr_float_50 f50;
mpfr_float_100 f100;
f50 = static_cast(f100); // explicit cast create a temporary
f50.assign(f100); // explicit call to assign create no temporary
In addition, if the type has multiple components (for example rational or complex number types), then there is a
two argument constructor:
number(arg1, arg2);
Where the two args must either be arithmetic types, or types that are convertible to the two components of `this`.
number& operator+=(const ``['see-below]``&);
number& operator-=(const ``['see-below]``&);
number& operator*=(const ``['see-below]``&);
number& operator/=(const ``['see-below]``&);
number& operator++();
number& operator--();
number operator++(int);
number operator--(int);
// Integer only operations:
number& operator%=(const ``['see-below]``&);
number& operator&=(const ``['see-below]``&);
number& operator|=(const ``['see-below]``&);
number& operator^=(const ``['see-below]``&);
number& operator<<=(const ``['integer-type]``&);
number& operator>>=(const ``['integer-type]``&);
These operators all take their usual arithmetic meanings.
The arguments to these operators is either:
* Another `number`.
* An expression template derived from `number`.
* Any type implicitly convertible to `number`, including some other instance of class `number`.
For the left and right shift operations, the argument must be a builtin
integer type with a positive value (negative values result in a `std::runtime_error` being thrown).
operator ``['convertible-to-bool-type]``()const;
Returns an ['unmentionable-type] that is usable in Boolean contexts (this allows `number` to be used in any
Boolean context - if statements, conditional statements, or as an argument to a logical operator - without
type `number` being convertible to type `bool`.
This operator also enables the use of `number` with any of the following operators:
`!`, `||`, `&&` and `?:`.
void swap(number& other);
Swaps `*this` with `other`.
bool is_zero()const;
Returns `true` is `*this` is zero, otherwise `false`.
int sign()const;
Returns a value less than zero if `*this` is negative, a value greater than zero if `*this` is positive, and zero
if `*this` is zero.
std::string str(unsigned precision, bool scientific = true)const;
Returns the number formatted as a string, with at least /precision/ digits, and in scientific format
if /scientific/ is true.
template
T convert_to()const;
template
explicit operator T ()const;
Provides a generic conversion mechanism to convert `*this` to type `T`. Type `T` may be any arithmetic type.
Optionally other types may also be supported by specific `Backend` types.
static unsigned default_precision();
static void default_precision(unsigned digits10);
unsigned precision()const;
void precision(unsigned digits10);
These functions are only available if the Backend template parameter supports runtime changes to precision. They get and set
the default precision and the precision of `*this` respectively.
int compare(const number& o)const;
template
typename enable_if >, int>::type
compare(const V& other)const;
Returns:
* A value less that 0 for `*this < other`
* A value greater that 0 for `*this > other`
* Zero for `*this == other`
Backend& backend();
const Backend& backend()const;
Returns the underlying back-end instance used by `*this`.
[h4 Non-member operators]
// Non member operators:
``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&);
// Integer only operations:
``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&);
``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&);
``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&);
// Comparison operators:
bool operator==(const ``['see-below]``&, const ``['see-below]``&);
bool operator!=(const ``['see-below]``&, const ``['see-below]``&);
bool operator< (const ``['see-below]``&, const ``['see-below]``&);
bool operator> (const ``['see-below]``&, const ``['see-below]``&);
bool operator<=(const ``['see-below]``&, const ``['see-below]``&);
bool operator>=(const ``['see-below]``&, const ``['see-below]``&);
These operators all take their usual arithmetic meanings.
The arguments to these functions must contain at least one of the following:
* A `number`.
* An expression template type derived from `number`.
* Any type for which `number` has an implicit constructor - for example a builtin arithmetic type.
The return type of these operators is either:
* An ['unmentionable-type] expression template type when `ExpressionTemplates` is `true`.
* Type `number` when `ExpressionTemplates` is `false`.
* Type `bool` if the operator is a comparison operator.
Finally note that the second argument to the left and right shift operations must be a builtin integer type,
and that the argument must be positive (negative arguments result in a `std::runtime_error` being thrown).
[h4 swap]
template
void swap(number& a, number& b);
Swaps `a` and `b`.
[h4 Iostream Support]
template
std::ostream& operator << (std::ostream& os, const number& r);
template
std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r);
template
inline std::istream& operator >> (std::istream& is, number& r)
These operators provided formatted input-output operations on `number` types, and expression templates derived from them.
It's down to the back-end type to actually implement string conversion. However, the back-ends provided with
this library support all of the iostream formatting flags, field width and precision settings.
[h4 Arithmetic with a higher precision result]
template
ResultType& add(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
template
ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
These functions apply the named operator to the arguments ['a] and ['b] and store the
result in ['result], returning ['result]. In all cases they behave "as if"
arguments ['a] and ['b] were first promoted to type `ResultType` before applying the
operator, though particular backends may well avoid that step by way of an optimization.
The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2`
may be either instances of class `number` or native integer types. The latter is an optimization
that allows arithmetic to be performed on native integer types producing an extended precision result.
[h4 Non-member standard library function support]
``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` lround (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` llround(const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, int);
``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, int*);
``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
These functions all behave exactly as their standard library C++11 counterparts do: their argument is either an instance of `number` or
an expression template derived from it; If the argument is of type `number` then that is also the return type,
otherwise the return type is an expression template.
These functions are normally implemented by the Backend type. However, default versions are provided for Backend types that
don't have native support for these functions. Please note however, that this default support requires the precision of the type
to be a compile time constant - this means for example that the [gmp] MPF Backend will not work with these functions when that type is
used at variable precision.
Also note that with the exception of `abs` that these functions can only be used with floating-point Backend types (if any other types
such as fixed precision or complex types are added to the library later, then these functions may be extended to support those number types).
The precision of these functions is generally deterimined by the backend implementation. For example the precision
of these functions when used with __mpfr_float_backend is determined entirely by [mpfr]. When these functions use our own
implementations, the accuracy of the transcendal functions is generally a few epsilon. Note however, that the trigonmetrical
functions incur the usual accuracy loss when reducing arguments by large multiples of [pi]. Also note that both __mpf_float
and __cpp_dec_float have a number of guard digits beyond their stated precision, so the error rates listed for these
are in some sense artificially low.
The following table shows the error rates we observe for these functions with various backend types, functions not listed
here are exact (tested on Win32 with VC++10, MPFR-3.0.0, MPIR-2.1.1):
[table
[[Function][mpfr_float_50][mpf_float_50][cpp_dec_float_50]]
[[sqrt][1eps][0eps][0eps]]
[[exp][1eps][0eps][0eps]]
[[log][1eps][0eps][0eps]]
[[log10][1eps][0eps][0eps]]
[[cos][700eps][0eps][0eps]]
[[sin][1eps][0eps][0eps]]
[[tan][0eps][0eps][0eps]]
[[acos][0eps][0eps][0eps]]
[[asin][0eps][0eps][0eps]]
[[atan][1eps][0eps][0eps]]
[[cosh][1045eps[footnote It's likely that the inherent error in the input values to our test cases are to blame here.]][0eps][0eps]]
[[sinh][2eps][0eps][0eps]]
[[tanh][1eps][0eps][0eps]]
[[pow][0eps][4eps][3eps]]
[[atan2][1eps][0eps][0eps]]
]
[h4 Traits Class Support]
template
struct component_type;
If this is a type with multiple components (for example rational or complex types), then this trait has a single member
`type` that is the type of those components.
template
struct number_category;
A traits class that inherits from `mpl::int_` where `N` is one of the enumerated values `number_kind_integer`, `number_kind_floating_point`,
`number_kind_rational`, `number_kind_fixed_point`, or `number_kind_unknown`. This traits class is specialized for any type that has
`std::numeric_limits` support as well as for classes in this library: which means it can be used for generic code that must work
with built in arithmetic types as well as multiprecision ones.
template
struct is_number;
A traits class that inherits from `mpl::true_` if T is an instance of `number<>`, otherwise from `mpl::false_`.
template
struct is_number_expression;
A traits class that inherits from `mpl::true_` if T is an expression template type derived from `number<>`, otherwise from `mpl::false_`.
[h4 Integer functions]
In addition to functioning with types from this library, these functions are also overloaded for built in integer
types if you include ``. Further, when used with fixed precision types (whether
built in integers or multiprecision ones), the functions will promote to a wider type internally when the algorithm
requires it. Versions overloaded for built in integer types return that integer type rather than an expression
template.
``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``& b, unsigned p);
Returns ['b[super p]] as an expression template. Note that this function should be used with extreme care as the result can grow so
large as to take "effectively forever" to compute, or else simply run the host machine out of memory. This is the one function in
this category that is not overloaded for built in integer types, further, it's probably not a good idea to use it with
fixed precision `cpp_int`'s either.
``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m);
Returns ['b[super p] mod m] as an expression template. Fixed precision types are promoted internally to ensure accuracy.
template
void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y,
number& q, number& r);
Divides x by y and returns both the quotient and remainder. After the call `q = x / y` and `r = x % y`.
template
Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val);
Returns the absolute value of `x % val`.
unsigned lsb(const ``['number-or-expression-template-type]``& x);
Returns the index of the least significant bit that is set to 1.
Throws a `std::range_error` if the argument is <= 0.
template
bool bit_test(const number& val, unsigned index);
Returns `true` if the bit at /index/ in /val/ is set.
template
number& bit_set(number& val, unsigned index);
Sets the bit at /index/ in /val/, and returns /val/.
template
number& bit_unset(number& val, unsigned index);
Unsets the bit at /index/ in /val/, and returns /val/.
template
number& bit_flip(number& val, unsigned index);
Flips the bit at /index/ in /val/, and returns /val/.
template
bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen);
bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials);
Tests to see if the number /n/ is probably prime - the test excludes the vast majority of composite numbers
by excluding small prime factors and performing a single Fermat test. Then performs /trials/ Miller-Rabin
tests. Returns `false` if /n/ is definitely composite, or `true` if /n/ is probably prime with the
probability of it being composite less than 0.25^trials. Fixed precision types are promoted internally
to ensure accuracy.
[h4 Rational Number Functions]
typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&);
typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&);
These functions return the numerator and denominator of a rational number respectively.
[h4 Boost.Math Interoperability Support]
namespace boost{ namespace math{
int fpclassify (const ``['number-or-expression-template-type]``&, int);
bool isfinite (const ``['number-or-expression-template-type]``&, int);
bool isnan (const ``['number-or-expression-template-type]``&, int);
bool isinf (const ``['number-or-expression-template-type]``&, int);
bool isnormal (const ``['number-or-expression-template-type]``&, int);
}} // namespaces
These floating-point classification functions behave exactly as their Boost.Math equivalents.
Other Boost.Math functions and templates may also be
specialized or overloaded to ensure interoperability.
[h4 std::numeric_limits support]
namespace std{
template
struct numeric_limits >
{
/* Usual members here */
};
}
Class template `std::numeric_limits` is specialized for all instantiations of `number` whose precision is known at compile time, plus those
types whose precision is unlimited (though it is much less useful in those cases). It is not specialized for types
whose precision can vary at compile time (such as `mpf_float`).
[endsect]
[section:cpp_int_ref cpp_int]
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 >
class cpp_int_backend;
//
// Expression templates default to et_off if there is no allocator:
//
template
struct expression_template_default >
{ static const expression_template_option value = et_off; };
typedef number > cpp_int; // arbitrary precision integer
typedef rational_adapter > cpp_rational_backend;
typedef number cpp_rational; // arbitrary precision rational number
// Fixed precision unsigned types:
typedef number > uint128_t;
typedef number > uint256_t;
typedef number > uint512_t;
typedef number > uint1024_t;
// Fixed precision signed types:
typedef number > int128_t;
typedef number > int256_t;
typedef number > int512_t;
typedef number > int1024_t;
// Over again, but with checking enabled this time:
typedef number > checked_cpp_int;
typedef rational_adapter > checked_cpp_rational_backend;
typedef number checked_cpp_rational;
// Checked fixed precision unsigned types:
typedef number > checked_uint128_t;
typedef number > checked_uint256_t;
typedef number > checked_uint512_t;
typedef number > checked_uint1024_t;
// Fixed precision signed types:
typedef number > checked_int128_t;
typedef number > checked_int256_t;
typedef number > checked_int512_t;
typedef number > checked_int1024_t;
}} // namespaces
Class template `cpp_int_backend` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
to change.
The template arguments are:
[variablelist
[[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
[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic 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 the [link boost_multiprecision.tut.ints.cpp_int tutorial] for more information.]]
[[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]]
]
The type of `number_category >::type` is `mpl::int_`.
More information on this type can be found in the [link boost_multiprecision.tut.ints.cpp_int tutorial].
[endsect]
[section:gmp_int_ref gmp_int]
namespace boost{ namespace multiprecision{
class gmp_int;
typedef number mpz_int;
}} // namespaces
Class template `gmp_int` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
to change.
The type of `number_category >::type` is `mpl::int_`.
More information on this type can be found in the [link boost_multiprecision.tut.ints.gmp_int tutorial].
[endsect]
[section:tom_int_ref tom_int]
namespace boost{ namespace multiprecision{
class tommath_int;
typedef number tom_int;
}} // namespaces
Class template `tommath_int` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
to change.
The type of `number_category >::type` is `mpl::int_`.
More information on this type can be found in the [link boost_multiprecision.tut.ints.tom_int tutorial].
[endsect]
[section:mpf_ref gmp_float]
namespace boost{ namespace multiprecision{
template
class gmp_float;
typedef number > mpf_float_50;
typedef number > mpf_float_100;
typedef number > mpf_float_500;
typedef number > mpf_float_1000;
typedef number > mpf_float;
}} // namespaces
Class template `gmp_float` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type.
Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject
to change.
The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type
should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision`
and `number::precision`. Note that this type does not in any way change the GMP library's global state (for example
it does not change the default precision of the mpf_t data type), therefore you can safely mix this type with existing
code that uses GMP, and also mix `gmp_float`s of differing precision.
The type of `number_category >::type` is `mpl::int_