|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r75232 - in sandbox/big_number: boost/multiprecision libs/multiprecision/doc
From: john_at_[hidden]
Date: 2011-11-01 15:14:09
Author: johnmaddock
Date: 2011-11-01 15:14:08 EDT (Tue, 01 Nov 2011)
New Revision: 75232
URL: http://svn.boost.org/trac/boost/changeset/75232
Log:
Add interconversions between GMP types.
Updates docs.
Add numerator and denominator methods for rational numbers.
Text files modified:
sandbox/big_number/boost/multiprecision/gmp.hpp | 288 +++++++++++++++++++++++++++++
sandbox/big_number/boost/multiprecision/mp_number.hpp | 21 ++
sandbox/big_number/libs/multiprecision/doc/Jamfile.v2 | 5
sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk | 380 ++++++++++++++++++++++++++++++++++-----
4 files changed, 636 insertions(+), 58 deletions(-)
Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2011-11-01 15:14:08 EDT (Tue, 01 Nov 2011)
@@ -236,6 +236,9 @@
} // namespace detail
+struct gmp_int;
+struct gmp_rational;
+
template <unsigned digits10>
struct gmp_float : public detail::gmp_float_imp<digits10>
{
@@ -244,6 +247,37 @@
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
}
gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {}
+ template <unsigned D>
+ gmp_float(const gmp_float<D>& o)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set(this->m_data, o.data());
+ }
+ gmp_float(const gmp_int& o)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set_z(this->data(), o.data());
+ }
+ gmp_float(const gmp_rational& o)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set_q(this->data(), o.data());
+ }
+ gmp_float(mpf_t val)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set(this->m_data, val);
+ }
+ gmp_float(mpz_t val)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set_z(this->m_data, val);
+ }
+ gmp_float(mpq_t val)
+ {
+ mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+ mpf_set_q(this->m_data, val);
+ }
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_float(gmp_float&& o) : detail::gmp_float_imp<digits10>(o) {}
#endif
@@ -259,6 +293,37 @@
return *this;
}
#endif
+ template <unsigned D>
+ gmp_float& operator=(const gmp_float<D>& o)
+ {
+ mpf_set(this->m_data, o.data());
+ return *this;
+ }
+ gmp_float& operator=(const gmp_int& o)
+ {
+ mpf_set_z(this->data(), o.data());
+ return *this;
+ }
+ gmp_float& operator=(const gmp_rational& o)
+ {
+ mpf_set_q(this->data(), o.data());
+ return *this;
+ }
+ gmp_float& operator=(const mpf_t& val)
+ {
+ mpf_set(this->m_data, val);
+ return *this;
+ }
+ gmp_float& operator=(const mpz_t& val)
+ {
+ mpf_set_z(this->m_data, val);
+ return *this;
+ }
+ gmp_float& operator=(const mpq_t& val)
+ {
+ mpf_set_q(this->m_data, val);
+ return *this;
+ }
template <class V>
gmp_float& operator=(const V& v)
{
@@ -278,14 +343,37 @@
{
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
}
+ gmp_float(mpf_t val)
+ {
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set(this->m_data, val);
+ }
+ gmp_float(mpz_t val)
+ {
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set_z(this->m_data, val);
+ }
+ gmp_float(mpq_t val)
+ {
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set_q(this->m_data, val);
+ }
gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o) {}
+ template <unsigned D>
+ gmp_float(const gmp_float<D>& o)
+ {
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set(this->m_data, o.data());
+ }
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_float(gmp_float&& o) : detail::gmp_float_imp<0>(o) {}
#endif
- gmp_float(const gmp_float& o, unsigned digits10)
+ gmp_float(const gmp_int& o);
+ gmp_float(const gmp_rational& o);
+ gmp_float(const gmp_float& o, unsigned digits10)
{
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
- *this = o;
+ mpf_set(this->m_data, o.data());
}
gmp_float& operator=(const gmp_float& o)
@@ -300,6 +388,29 @@
return *this;
}
#endif
+ template <unsigned D>
+ gmp_float& operator=(const gmp_float<D>& o)
+ {
+ mpf_set(this->m_data, o.data());
+ return *this;
+ }
+ gmp_float& operator=(const gmp_int& o);
+ gmp_float& operator=(const gmp_rational& o);
+ gmp_float& operator=(const mpf_t& val)
+ {
+ mpf_set(this->m_data, val);
+ return *this;
+ }
+ gmp_float& operator=(const mpz_t& val)
+ {
+ mpf_set_z(this->m_data, val);
+ return *this;
+ }
+ gmp_float& operator=(const mpq_t& val)
+ {
+ mpf_set_q(this->m_data, val);
+ return *this;
+ }
template <class V>
gmp_float& operator=(const V& v)
{
@@ -702,9 +813,9 @@
struct gmp_int
{
- typedef mpl::list<long, long long> signed_types;
+ typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
- typedef mpl::list<double, long double> real_types;
+ typedef mpl::list<double, long double> real_types;
gmp_int()
{
@@ -714,6 +825,27 @@
{
mpz_init_set(m_data, o.m_data);
}
+ gmp_int(mpf_t val)
+ {
+ mpz_init(this->m_data);
+ mpz_set_f(this->m_data, val);
+ }
+ gmp_int(mpz_t val)
+ {
+ mpz_init_set(this->m_data, val);
+ }
+ gmp_int(mpq_t val)
+ {
+ mpz_init(this->m_data);
+ mpz_set_q(this->m_data, val);
+ }
+ template <unsigned Digits10>
+ gmp_int(const gmp_float<Digits10>& o)
+ {
+ mpz_init(this->m_data);
+ mpz_set_f(this->m_data, o.data());
+ }
+ gmp_int(const gmp_rational& o);
gmp_int& operator = (const gmp_int& o)
{
mpz_set(m_data, o.m_data);
@@ -812,6 +944,28 @@
mpz_set_str(m_data, s, 10);
return *this;
}
+ gmp_int& operator=(const mpf_t& val)
+ {
+ mpz_set_f(this->m_data, val);
+ return *this;
+ }
+ gmp_int& operator=(const mpz_t& val)
+ {
+ mpz_set(this->m_data, val);
+ return *this;
+ }
+ gmp_int& operator=(const mpq_t& val)
+ {
+ mpz_set_q(this->m_data, val);
+ return *this;
+ }
+ template <unsigned Digits10>
+ gmp_int& operator=(const gmp_float<Digits10>& o)
+ {
+ mpz_set_f(this->m_data, o.data());
+ return *this;
+ }
+ gmp_int& operator=(const gmp_rational& o);
void swap(gmp_int& o)
{
mpz_swap(m_data, o.m_data);
@@ -1176,6 +1330,21 @@
mpq_init(m_data);
mpq_set(m_data, o.m_data);
}
+ gmp_rational(const gmp_int& o)
+ {
+ mpq_init(m_data);
+ mpq_set_z(m_data, o.data());
+ }
+ gmp_rational(mpq_t o)
+ {
+ mpq_init(m_data);
+ mpq_set(m_data, o);
+ }
+ gmp_rational(mpz_t o)
+ {
+ mpq_init(m_data);
+ mpq_set_z(m_data, o);
+ }
gmp_rational& operator = (const gmp_rational& o)
{
mpq_set(m_data, o.m_data);
@@ -1276,6 +1445,21 @@
mpq_set_str(m_data, s, 10);
return *this;
}
+ gmp_rational& operator=(const gmp_int& o)
+ {
+ mpq_set_z(m_data, o.data());
+ return *this;
+ }
+ gmp_rational& operator=(const mpq_t& o)
+ {
+ mpq_set(m_data, o);
+ return *this;
+ }
+ gmp_rational& operator=(const mpz_t& o)
+ {
+ mpq_set_z(m_data, o);
+ return *this;
+ }
void swap(gmp_rational& o)
{
mpq_swap(m_data, o.m_data);
@@ -1324,6 +1508,17 @@
mpq_t m_data;
};
+inline mp_number<gmp_int> numerator(const mp_number<gmp_rational>& val)
+{
+ const __mpz_struct* pz = (mpq_numref(val.backend().data()));
+ return mp_number<gmp_int>((mpz_t&)pz);
+}
+inline mp_number<gmp_int> denominator(const mp_number<gmp_rational>& val)
+{
+ const __mpz_struct* pz = mpq_denref(val.backend().data());
+ return mp_number<gmp_int>((mpz_t&)pz);
+}
+
inline void add(gmp_rational& t, const gmp_rational& o)
{
mpq_add(t.data(), t.data(), o.data());
@@ -1389,6 +1584,41 @@
mpq_abs(result.data(), val.data());
}
+//
+// Some member functions that are dependent upon previous code go here:
+//
+inline gmp_float<0>::gmp_float(const gmp_int& o)
+{
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set_z(this->data(), o.data());
+}
+inline gmp_float<0>::gmp_float(const gmp_rational& o)
+{
+ mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+ mpf_set_q(this->data(), o.data());
+}
+inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o)
+{
+ mpf_set_z(this->data(), o.data());
+ return *this;
+}
+inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o)
+{
+ mpf_set_q(this->data(), o.data());
+ return *this;
+}
+inline gmp_int::gmp_int(const gmp_rational& o)
+{
+ mpz_init(this->m_data);
+ mpz_set_q(this->m_data, o.data());
+}
+inline gmp_int& gmp_int::operator=(const gmp_rational& o)
+{
+ mpz_set_q(this->m_data, o.data());
+ return *this;
+}
+
+
template<>
struct number_category<gmp_int> : public mpl::int_<number_kind_integer>{};
template<>
@@ -1608,6 +1838,56 @@
BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
};
+template<>
+class numeric_limits<boost::multiprecision::mpq_rational >
+{
+ typedef boost::multiprecision::mpq_rational number_type;
+public:
+ BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ //
+ // Largest and smallest numbers are bounded only by available memory, set
+ // to zero:
+ //
+ BOOST_STATIC_CONSTEXPR number_type (min)() noexcept
+ {
+ return number_type();
+ }
+ BOOST_STATIC_CONSTEXPR number_type (max)() noexcept
+ {
+ return number_type();
+ }
+ BOOST_STATIC_CONSTEXPR number_type lowest() noexcept { return (min)(); }
+ // Digits are unbounded, use zero for now:
+ BOOST_STATIC_CONSTEXPR int digits = 0;
+ BOOST_STATIC_CONSTEXPR int digits10 = 0;
+ BOOST_STATIC_CONSTEXPR int max_digits10 = 0;
+ BOOST_STATIC_CONSTEXPR bool is_signed = true;
+ BOOST_STATIC_CONSTEXPR bool is_integer = false;
+ BOOST_STATIC_CONSTEXPR bool is_exact = true;
+ BOOST_STATIC_CONSTEXPR int radix = 2;
+ BOOST_STATIC_CONSTEXPR number_type epsilon() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type round_error() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR int min_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent = 0;
+ BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
+ BOOST_STATIC_CONSTEXPR bool has_infinity = false;
+ BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
+ BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
+ BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
+ BOOST_STATIC_CONSTEXPR number_type infinity() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type quiet_NaN() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type signaling_NaN() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR number_type denorm_min() noexcept { return number_type(); }
+ BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
+ BOOST_STATIC_CONSTEXPR bool is_bounded = false;
+ BOOST_STATIC_CONSTEXPR bool is_modulo = false;
+ BOOST_STATIC_CONSTEXPR bool traps = false;
+ BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
+ BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
+};
+
#ifdef BOOST_NO_NOEXCEPT
# undef noexcept
#endif
Modified: sandbox/big_number/boost/multiprecision/mp_number.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mp_number.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mp_number.hpp 2011-11-01 15:14:08 EDT (Tue, 01 Nov 2011)
@@ -43,6 +43,11 @@
m_backend.precision(digits10);
m_backend = canonical_value(v);
}
+ template <class Other>
+ mp_number(const mp_number<Other>& val, typename enable_if<boost::is_convertible<Other, Backend> >::type* dummy1 = 0)
+ {
+ m_backend = val.backend();
+ }
template <class V>
mp_number(V v, typename enable_if<mpl::and_<is_convertible<V, Backend>, mpl::not_<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > > > >::type* dummy1 = 0)
@@ -69,6 +74,22 @@
return *this;
}
+ template <class V>
+ typename enable_if<mpl::and_<is_convertible<V, Backend>, mpl::not_<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > > >, mp_number<Backend>& >::type
+ operator=(const V& v)
+ {
+ m_backend = v;
+ return *this;
+ }
+
+ template <class Other>
+ typename enable_if<is_convertible<Other, Backend>, mp_number<Backend>& >::type
+ operator=(const mp_number<Other>& v)
+ {
+ m_backend = v.backend();
+ return *this;
+ }
+
template <class tag, class Arg1, class Arg2, class Arg3>
mp_number(const detail::mp_exp<tag, Arg1, Arg2, Arg3>& e)
{
Modified: sandbox/big_number/libs/multiprecision/doc/Jamfile.v2
==============================================================================
--- sandbox/big_number/libs/multiprecision/doc/Jamfile.v2 (original)
+++ sandbox/big_number/libs/multiprecision/doc/Jamfile.v2 2011-11-01 15:14:08 EDT (Tue, 01 Nov 2011)
@@ -13,12 +13,12 @@
big_number
:
# Path for links to Boost:
- #<xsl:param>boost.root=../../../../..
+ #<xsl:param>boost.root=http://www.boost.org/doc/libs/release
# Some general style settings:
<xsl:param>table.footnote.number.format=1
<xsl:param>footnote.number.format=1
- <xsl:param>html.stylesheet=boostbook.css
+ <xsl:param>html.stylesheet=http://www.boost.org/doc/libs/release/doc/src/boostbook.css
# HTML options first:
# Use graphics not text for navigation:
@@ -66,3 +66,4 @@
install pdf-install : standalone : <location>. <install-type>PDF ;
+
Modified: sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk
==============================================================================
--- sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk (original)
+++ sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk 2011-11-01 15:14:08 EDT (Tue, 01 Nov 2011)
@@ -5,10 +5,10 @@
http://www.boost.org/LICENSE_1_0.txt).
]
-[library Boost.BigNumbers
+[library Boost.Multiprecision
[quickbook 1.5]
[copyright 2011 John Maddock]
- [purpose Big Number library]
+ [purpose Multiprecision Number library]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
@@ -20,7 +20,7 @@
[section:intro Introduction]
-The Big Number library comes in two distinct parts: an expression template enabled front end `big_number`
+The Multiprecision library comes in two distinct parts: an expression template enabled front end `mp_number`
that handles all the operator overloading, expression evaluation optimization, and code reduction, and
a selection of backends that implement the actual arithmetic operations, and need conform only to the
reduced interface requirements of the front end.
@@ -38,27 +38,34 @@
[table
[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
-[[`gmp_int`][boost/math/big_number/gmp.hpp][2][GMP][Very fast and efficient backend.][Dependency on GNU licenced GMP library.]]
+[[`gmp_int`][boost/multiprecision/gmp.hpp][2][GMP][Very fast and efficient backend.][Dependency on GNU licenced GMP library.]]
]
[h4 gmp_int]
- namespace boost{ namespace math{
+ namespace boost{ namespace multiprecision{
class gmp_int;
- typedef big_number<gmp_int > mpz_int;
+ typedef mp_number<gmp_int > mpz_int;
}} // namespaces
-The `gmp_int` backend is used via the typedef `boost::math::mpz_int`. It acts as a thin wrapper around the GMP `mpz_t`
+The `gmp_int` backend 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 asignable from:
+
+* The GMP native types: `mpf_t`, `mpz_t`, `mpq_t`.
+* Instances of `mp_number<T>` that are wrappers around those types: `mp_number<gmp_float<N> >`, `mp_number<gmp_rational>`.
+
+It's also possible to access the underlying `mpz_t` via the data() member function of `gmp_int`.
+
[h5 Example:]
- #include <boost/math/big_number/gmp.hpp>
+ #include <boost/multiprecision/gmp.hpp>
- boost::math::mpz_int v = 1;
+ boost::multiprecision::mpz_int v = 1;
// Do some arithmetic:
for(unsigned i = 1; i <= 1000; ++i)
@@ -66,6 +73,10 @@
std::cout << i << std::endl; // prints 1000!
+ // Access the underlying representation:
+ mpz_t z;
+ mpz_int(z, v.backend().data());
+
[endsect]
[section:reals Real Numbers]
@@ -74,61 +85,214 @@
[table
[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
-[[`gmp_real<N>`][boost/math/big_number/gmp.hpp][2][GMP][Very fast and efficient backend.][Dependency on GNU licenced GMP library.]]
+[[`mpf_float<N>`][boost/multiprecision/gmp.hpp][2][GMP][Very fast and efficient backend.][Dependency on GNU licenced GMP library.]]
+[[`mpfr_float<N>`][boost/multiprecision/mpfr.hpp][2][GMP and MPFR][Very fast and efficient backend, with it's own standard library implementation.][Dependency on GNU licenced GMP and MPFR libraries.]]
+[[`mp_float<N>`][boost/multiprecision/mp_float.hpp][10][None][Header only, all C++ implementation.][Approximately 2x slower than the MPFR or GMP libraries.]]
]
-[h4 gmp_real]
+[h4 gmp_float]
- namespace boost{ namespace math{
+ namespace boost{ namespace multiprecision{
template <unsigned Digits10>
- class gmp_real;
+ class gmp_float;
- typedef big_number<gmp_real<50> > mpf_real_50;
- typedef big_number<gmp_real<100> > mpf_real_100;
- typedef big_number<gmp_real<500> > mpf_real_500;
- typedef big_number<gmp_real<1000> > mpf_real_1000;
- typedef big_number<gmp_real<0> > mpf_real;
+ typedef mp_number<gmp_float<50> > mpf_float_50;
+ typedef mp_number<gmp_float<100> > mpf_float_100;
+ typedef mp_number<gmp_float<500> > mpf_float_500;
+ typedef mp_number<gmp_float<1000> > mpf_float_1000;
+ typedef mp_number<gmp_float<0> > mpf_float;
}} // namespaces
-The `gmp_real` backend is used in conjunction with `big_number`: It acts as a thin wrapper around the GMP `mpf_t`
+The `gmp_float` backend is used in conjunction with `mp_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_real` 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_real_50, mpf_real_100,
-mpf_real_500, mpf_real_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision
-respectively. The typedef mpf_real provides a variable precision type whose precision can be controlled via the
-`big_number`'s member functions.
-
-[h5 example:]
-
- #include <boost/math/big_number/gmp.hpp>
-
- boost::math::gmp_real a = 2;
- boost::math::gmp_real::default_precision(1000);
- std::cout << boost::math::gmp_real::default_precision() << std::endl;
+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
+`mp_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 `mp_number<mpf_float<N> >` are
+copy constructible and assignable from:
+
+* The GMP native types `mpf_t`, `mpz_t`, `mpq_t`.
+* The `mp_number` wrappers around those types: `mp_number<mpf_float<M> >`, `mp_number<gmp_int>`, `mp_number<gmp_rational>`.
+
+It's also possible to access the underlying `mpf_t` via the data() member function of `gmp_float`.
+
+[h5 GMP example:]
+
+ #include <boost/multiprecision/gmp.hpp>
+
+ // Operations at variable precision and limited standard library support:
+ boost::multiprecision::gmp_float a = 2;
+ boost::multiprecision::gmp_float::default_precision(1000);
+ std::cout << boost::multiprecision::gmp_float::default_precision() << std::endl;
std::cout << sqrt(a) << std::endl; // print root-2
+ // Operations at fixed precision and full standard library support:
+ boost::multiprecision::mpf_float_100 b = 2;
+ std::cout << std::numeric_limits<mpf_float_100>::digits << std::endl;
+ std::cout << log(b) << std::endl; // print log(2)
+
+ // Access the underlying representation:
+ mpf_t f;
+ mpf_init(f, a.backend().data());
+
+[h4 mpfr_float]
+
+ namespace boost{ namespace multiprecision{
+
+ template <unsigned Digits10>
+ class mpfr_float;
+
+ typedef mp_number<mpfr_float<50> > mpfr_float_50;
+ typedef mp_number<mpfr_float<100> > mpfr_float_100;
+ typedef mp_number<mpfr_float<500> > mpfr_float_500;
+ typedef mp_number<mpfr_float<1000> > mpfr_float_1000;
+ typedef mp_number<mpfr_float<0> > mpfr_float;
+
+ }} // namespaces
+
+The `mpfr_float` backend is used in conjunction with `mp_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` 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
+`mp_number`'s member functions.
+
+[note This type only provides numeric_limits support when the precision is fixed at compile time.]
+
+[h5 MPFR example:]
+
+ #include <boost/multiprecision/gmp.hpp>
+
+ // Operations at variable precision and no numeric_limits support:
+ boost::multiprecision::gmp_float a = 2;
+ boost::multiprecision::gmp_float::default_precision(1000);
+ std::cout << boost::multiprecision::gmp_float::default_precision() << std::endl;
+ std::cout << sqrt(a) << std::endl; // print root-2
+
+ // Operations at fixed precision and full numeric_limits support:
+ boost::multiprecision::mpfr_float_100 b = 2;
+ std::cout << std::numeric_limits<mpfr_float_100>::digits << std::endl;
+ std::cout << log(b) << std::endl; // print log(2)
+
+[h4 mp_float]
+
+ namespace boost{ namespace multiprecision{
+
+ template <unsigned Digits10>
+ class mp_float;
+
+ typedef mp_number<mp_float<50> > mp_float_50;
+ typedef mp_number<mp_float<100> > mp_float_100;
+
+ }} // namespaces
+
+The `mp_float` backend is used in conjunction with `mp_number`: It acts as an entirely C++ (header only and dependency free)
+real-number type that is a drop-in replacement for the native C++ floating-point types, but with
+much greater precision.
+
+Type `mp_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter.
+The typedefs mp_float_50 and mp_float_100 provide arithmetic types at 50 and 100 decimal digits precision
+respectively.
+
+There is full standard library and numeric_limits support available for this type.
+
+[h5 mp_float example:]
+
+ #include <boost/multiprecision/mp_float.hpp>
+
+ // Operations at fixed precision and full numeric_limits support:
+ boost::multiprecision::mp_float_100 b = 2;
+ std::cout << std::numeric_limits<mp_float_100>::digits << std::endl;
+ std::cout << log(b) << std::endl; // print log(2)
+
+[endsect]
+
+[section:rational Rational Number Types]
+
+The following backends provide rational number arithmetic:
+
+[table
+[[Backend Type][Header][Radix][Dependencies][Pros][Cons]]
+[[`gmp_rational`][boost/multiprecision/gmp.hpp][2][GMP][Very fast and efficient backend.][Dependency on GNU licenced GMP library.]]
+]
+
+[h4 gmp_rational]
+
+ namespace boost{ namespace multiprecision{
+
+ class gmp_rational;
+
+ typedef mp_number<gmp_rational > mpq_rational;
+
+ }} // namespaces
+
+The `gmp_rational` backend 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 `mp_number<gmp_rational>` are copy constructible
+and assignable from:
+
+* The GMP native types: `mpz_t`, `mpq_t`.
+* `mp_number<gmp_int>`.
+
+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`.
+
+[h5 Example:]
+
+ #include <boost/multiprecision/gmp.hpp>
+
+ boost::multiprecision::mpq_rational v = 1;
+
+ // Do some arithmetic:
+ for(unsigned i = 1; i <= 1000; ++i)
+ v *= i;
+ v /= 10;
+
+ std::cout << i << std::endl; // prints 1000! / 10
+ std::cout << numerator(i) << std::endl;
+ std::cout << denominator(i) << std::endl;
+
+ // Access the underlying data:
+ mpq_t q;
+ mpq_init(q, i.backend().data());
+
[endsect]
[endsect]
[section:ref Reference]
-[section:bignum big_number]
+[section:mp_number mp_number]
[h4 Synopsis]
- namespace boost{ namespace math{
+ namespace boost{ namespace multiprecision{
template <class Backend>
- class big_number
+ class mp_number
{
- big_number();
- big_number(see-below);
- big_number& operator=(see-below);
+ mp_number();
+ mp_number(see-below);
+ mp_number& operator=(see-below);
/* Other number-type operators here */
// string conversion:
std::string str()const;
@@ -138,44 +302,93 @@
unsigned precision()const;
void precision(unsigned digits10);
// Comparison:
- int compare(const big_number<Backend>& o)const;
+ int compare(const mp_number<Backend>& o)const;
template <class V>
typename enable_if<is_arithmetic<V>, int>::type compare(const V& o)const;
};
+ // iostream support:
+ template <class Backend>
+ std::ostream& operator << (std::ostream& os, const mp_number<Backend>& r);
+ std::ostream& operator << (std::ostream& os, const ``['unmentionable-expression-template-type]``& r);
+ template <class Backend>
+ std::istream& operator >> (std::istream& is, mp_number<Backend>& r);
+
+ // Non-member function standard library support:
+ ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
+
+ ``['unmentionable-expression-template-type]`` ldexp (const ``['mp_number-or-expression-template-type]``&, int);
+ ``['unmentionable-expression-template-type]`` frexp (const ``['mp_number-or-expression-template-type]``&, int*);
+ ``['unmentionable-expression-template-type]`` pow (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fmod (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan2 (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+
}} // namespaces
+ // numeric_limits support:
+ namespace std{
+
+ template <class Backend>
+ struct numeric_limits<boost::multiprecision<Backend> >
+ {
+ /* Usual members here */
+ };
+
+ }
+
[h4 Description]
- big_number();
- big_number(see-below);
- big_number& operator=(see-below);
+ mp_number();
+ mp_number(see-below);
+ mp_number& operator=(see-below);
-Type `big_number` is default constructible, and copy both constructible and assignable from:
+Type `mp_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.
* A `std::string` or any type which is convertible to `const char*`.
+* Any type that the Backend is constructible or assignable from.
/* Other number-type operators here */
The following arithmetic operations are support for real-numbered types:
-* Binary +, -, *, /, +=, -=, *=, /=, ==, !=, <=, >=, <, >.
-* Unary +, -.
+* Binary +, -, *, /, +=, -=, *=, /=, ==, !=, <=, >=, <, >, ||, &&, ||=, &&=.
+* Unary +, -, ++, --, !.
For integer types the following operators are also supported:
-Binary %, %=.
+Binary %, %=, |, |=, &, &=, ^, ^=, <<, <<=, >>, >>=.
-(More to follow!!)
+Note that with the exception of the logical operators and unary + the result of applying an operator to
+mp_number is an "unmentionable" expression template type.
-Note that the result of the binary +, -, *, / and % operations is an expression template of "unmentionable type".
+Binary operators, must have at least one argument that is of type `mp_number` or an expression template
+derived from `mp_number`. One argument may optionally be of arithmetic type.
- std::string str()const;
+Note that type `mp_number` (and all expression templates derived from it) may be used in a Boolian context.
-Returns the number formatted as a string (TODO: enable custom precision).
+ 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.
static unsigned default_precision();
static void default_precision(unsigned digits10);
@@ -183,9 +396,9 @@
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.
+the default precision and the precision of `*this` respectively.
- int compare(const big_number<Backend>& o)const;
+ int compare(const mp_number<Backend>& o)const;
template <class V>
typename enable_if<is_arithmetic<V>, int>::type compare(const V& other)const;
@@ -195,6 +408,69 @@
* A value greater that 0 for *this > other
* Zero for *this == other
+[h4 Iostream Support]
+
+ template <class Backend>
+ std::ostream& operator << (std::ostream& os, const mp_number<Backend>& r);
+ template <class Backend>
+ std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r);
+ template <class Backend>
+ inline std::istream& operator >> (std::istream& is, mp_number<Backend>& r)
+
+These operators provided formatted input-output operations on `mp_number` types, and expression templates derived from them.
+
+[h4 Non-member standard library function support]
+
+ ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
+
+ ``['unmentionable-expression-template-type]`` ldexp (const ``['mp_number-or-expression-template-type]``&, int);
+ ``['unmentionable-expression-template-type]`` frexp (const ``['mp_number-or-expression-template-type]``&, int*);
+ ``['unmentionable-expression-template-type]`` pow (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fmod (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan2 (const ``['mp_number-or-expression-template-type]``&, const ``['mp_number-or-expression-template-type]``&);
+
+These functions all behave exactly as their standard library counterparts do: their argument is either an instance of `mp_number` or
+an expression template derived from it; their return value is always 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.
+
+[h4 std::numeric_limits support]
+
+ namespace std{
+
+ template <class Backend>
+ struct numeric_limits<boost::multiprecision<Backend> >
+ {
+ /* Usual members here */
+ };
+
+ }
+
+Class template `std::numeric_limits` is specialized for all instantiations of `mp_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:backendconc Backend Requirements]
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk