3 <meta http-equiv=
"Content-Type" content=
"text/html; charset=US-ASCII">
4 <title>Introduction
</title>
5 <link rel=
"stylesheet" href=
"../../../../../doc/src/boostbook.css" type=
"text/css">
6 <meta name=
"generator" content=
"DocBook XSL Stylesheets V1.77.1">
7 <link rel=
"home" href=
"../index.html" title=
"Chapter 1. Boost.Multiprecision">
8 <link rel=
"up" href=
"../index.html" title=
"Chapter 1. Boost.Multiprecision">
9 <link rel=
"prev" href=
"../index.html" title=
"Chapter 1. Boost.Multiprecision">
10 <link rel=
"next" href=
"tut.html" title=
"Tutorial">
12 <body bgcolor=
"white" text=
"black" link=
"#0000FF" vlink=
"#840084" alink=
"#0000FF">
13 <table cellpadding=
"2" width=
"100%"><tr>
14 <td valign=
"top"><img alt=
"Boost C++ Libraries" width=
"277" height=
"86" src=
"../../../../../boost.png"></td>
15 <td align=
"center"><a href=
"../../../../../index.html">Home
</a></td>
16 <td align=
"center"><a href=
"../../../../../libs/libraries.htm">Libraries
</a></td>
17 <td align=
"center"><a href=
"http://www.boost.org/users/people.html">People
</a></td>
18 <td align=
"center"><a href=
"http://www.boost.org/users/faq.html">FAQ
</a></td>
19 <td align=
"center"><a href=
"../../../../../more/index.htm">More
</a></td>
22 <div class=
"spirit-nav">
23 <a accesskey=
"p" href=
"../index.html"><img src=
"../../../../../doc/src/images/prev.png" alt=
"Prev"></a><a accesskey=
"u" href=
"../index.html"><img src=
"../../../../../doc/src/images/up.png" alt=
"Up"></a><a accesskey=
"h" href=
"../index.html"><img src=
"../../../../../doc/src/images/home.png" alt=
"Home"></a><a accesskey=
"n" href=
"tut.html"><img src=
"../../../../../doc/src/images/next.png" alt=
"Next"></a>
26 <div class=
"titlepage"><div><div><h2 class=
"title" style=
"clear: both">
27 <a name=
"boost_multiprecision.intro"></a><a class=
"link" href=
"intro.html" title=
"Introduction">Introduction
</a>
28 </h2></div></div></div>
30 The Multiprecision Library provides
<a class=
"link" href=
"tut/ints.html" title=
"Integer Types">integer
</a>,
31 <a class=
"link" href=
"tut/rational.html" title=
"Rational Number Types">rational
</a> and
<a class=
"link" href=
"tut/floats.html" title=
"floating-point Numbers">floating-point
</a> types in C++
32 that have more range and precision than C++'s ordinary built-in types. The
33 big number types in Multiprecision can be used with a wide selection of basic
34 mathematical operations, elementary transcendental functions as well as the
35 functions in Boost.Math. The Multiprecision types can also interoperate with
36 the built-in types in C++ using clearly defined conversion rules. This allows
37 Boost.Multiprecision to be used for all kinds of mathematical calculations
38 involving integer, rational and floating-point types requiring extended range
42 Multiprecision consists of a generic interface to the mathematics of large
43 numbers as well as a selection of big number back ends, with support for integer,
44 rational and floating-point types. Boost.Multiprecision provides a selection
45 of back ends provided off-the-rack in including interfaces to GMP, MPFR, MPIR,
46 TomMath as well as its own collection of Boost-licensed, header-only back ends
47 for integers, rationals and floats. In addition, user-defined back ends can
48 be created and used with the interface of Multiprecision, provided the class
49 implementation adheres to the necessary
<a class=
"link" href=
"ref/backendconc.html" title=
"Backend Requirements">concepts
</a>.
52 Depending upon the number type, precision may be arbitrarily large (limited
53 only by available memory), fixed at compile time (for example
50 or
100 decimal
54 digits), or a variable controlled at run-time by member functions. The types
55 are expression-template-enabled for better performance than naive user-defined
59 The Multiprecision library comes in two distinct parts:
61 <div class=
"itemizedlist"><ul class=
"itemizedlist" style=
"list-style-type: disc; ">
63 An expression-template-enabled front-end
<code class=
"computeroutput"><span class=
"identifier">number
</span></code>
64 that handles all the operator overloading, expression evaluation optimization,
68 A selection of back-ends that implement the actual arithmetic operations,
69 and need conform only to the reduced interface requirements of the front-end.
73 Separation of front-end and back-end allows use of highly refined, but restricted
74 license libraries where possible, but provides Boost license alternatives for
75 users who must have a portable unconstrained license. Which is to say some
76 back-ends rely on
3rd party libraries, but a header-only Boost license version
77 is always available (if somewhat slower).
80 Should you just wish to cut to the chase and use a fully Boost-licensed number
81 type, then skip to
<a class=
"link" href=
"tut/ints/cpp_int.html" title=
"cpp_int">cpp_int
</a>
82 for multiprecision integers,
<a class=
"link" href=
"tut/floats/cpp_dec_float.html" title=
"cpp_dec_float">cpp_dec_float
</a>
83 for multiprecision floating-point types and
<a class=
"link" href=
"tut/rational/cpp_rational.html" title=
"cpp_rational">cpp_rational
</a>
87 The library is often used via one of the predefined typedefs: for example if
88 you wanted an
<a href=
"http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic" target=
"_top">arbitrary
89 precision
</a> integer type using
<a href=
"http://gmplib.org" target=
"_top">GMP
</a>
90 as the underlying implementation then you could use:
92 <pre class=
"programlisting"><span class=
"preprocessor">#include
</span> <span class=
"special"><</span><span class=
"identifier">boost
</span><span class=
"special">/
</span><span class=
"identifier">multiprecision
</span><span class=
"special">/
</span><span class=
"identifier">gmp
</span><span class=
"special">.
</span><span class=
"identifier">hpp
</span><span class=
"special">></span> <span class=
"comment">// Defines the wrappers around the GMP library's types
</span>
94 <span class=
"identifier">boost
</span><span class=
"special">::
</span><span class=
"identifier">multiprecision
</span><span class=
"special">::
</span><span class=
"identifier">mpz_int
</span> <span class=
"identifier">myint
</span><span class=
"special">;
</span> <span class=
"comment">// Arbitrary precision integer type.
</span>
97 Alternatively, you can compose your own multiprecision type, by combining
98 <code class=
"computeroutput"><span class=
"identifier">number
</span></code> with one of the predefined
99 back-end types. For example, suppose you wanted a
300 decimal digit floating-point
100 type based on the
<a href=
"http://www.mpfr.org" target=
"_top">MPFR
</a> library. In
101 this case, there's no predefined typedef with that level of precision, so instead
104 <pre class=
"programlisting"><span class=
"preprocessor">#include
</span> <span class=
"special"><</span><span class=
"identifier">boost
</span><span class=
"special">/
</span><span class=
"identifier">multiprecision
</span><span class=
"special">/
</span><span class=
"identifier">mpfr
</span><span class=
"special">.
</span><span class=
"identifier">hpp
</span><span class=
"special">></span> <span class=
"comment">// Defines the Backend type that wraps MPFR
</span>
106 <span class=
"keyword">namespace
</span> <span class=
"identifier">mp
</span> <span class=
"special">=
</span> <span class=
"identifier">boost
</span><span class=
"special">::
</span><span class=
"identifier">multiprecision
</span><span class=
"special">;
</span> <span class=
"comment">// Reduce the typing a bit later...
</span>
108 <span class=
"keyword">typedef
</span> <span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">mpfr_float_backend
</span><span class=
"special"><</span><span class=
"number">300</span><span class=
"special">></span> <span class=
"special">></span> <span class=
"identifier">my_float
</span><span class=
"special">;
</span>
110 <span class=
"identifier">my_float
</span> <span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"identifier">b
</span><span class=
"special">,
</span> <span class=
"identifier">c
</span><span class=
"special">;
</span> <span class=
"comment">// These variables have
300 decimal digits precision
</span>
113 We can repeat the above example, but with the expression templates disabled
114 (for faster compile times, but slower runtimes) by passing a second template
115 argument to
<code class=
"computeroutput"><span class=
"identifier">number
</span></code>:
117 <pre class=
"programlisting"><span class=
"preprocessor">#include
</span> <span class=
"special"><</span><span class=
"identifier">boost
</span><span class=
"special">/
</span><span class=
"identifier">multiprecision
</span><span class=
"special">/
</span><span class=
"identifier">mpfr
</span><span class=
"special">.
</span><span class=
"identifier">hpp
</span><span class=
"special">></span> <span class=
"comment">// Defines the Backend type that wraps MPFR
</span>
119 <span class=
"keyword">namespace
</span> <span class=
"identifier">mp
</span> <span class=
"special">=
</span> <span class=
"identifier">boost
</span><span class=
"special">::
</span><span class=
"identifier">multiprecision
</span><span class=
"special">;
</span> <span class=
"comment">// Reduce the typing a bit later...
</span>
121 <span class=
"keyword">typedef
</span> <span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">mpfr_float_backend
</span><span class=
"special"><</span><span class=
"number">300</span><span class=
"special">>,
</span> <span class=
"identifier">et_off
</span><span class=
"special">></span> <span class=
"identifier">my_float
</span><span class=
"special">;
</span>
123 <span class=
"identifier">my_float
</span> <span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"identifier">b
</span><span class=
"special">,
</span> <span class=
"identifier">c
</span><span class=
"special">;
</span> <span class=
"comment">// These variables have
300 decimal digits precision
</span>
126 We can also mix arithmetic operations between different types, provided there
127 is an unambiguous implicit conversion from one type to the other:
129 <pre class=
"programlisting"><span class=
"preprocessor">#include
</span> <span class=
"special"><</span><span class=
"identifier">boost
</span><span class=
"special">/
</span><span class=
"identifier">multiprecision
</span><span class=
"special">/
</span><span class=
"identifier">cpp_int
</span><span class=
"special">.
</span><span class=
"identifier">hpp
</span><span class=
"special">></span>
131 <span class=
"keyword">namespace
</span> <span class=
"identifier">mp
</span> <span class=
"special">=
</span> <span class=
"identifier">boost
</span><span class=
"special">::
</span><span class=
"identifier">multiprecision
</span><span class=
"special">;
</span> <span class=
"comment">// Reduce the typing a bit later...
</span>
133 <span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">int128_t
</span> <span class=
"identifier">a
</span><span class=
"special">(
</span><span class=
"number">3</span><span class=
"special">),
</span> <span class=
"identifier">b
</span><span class=
"special">(
</span><span class=
"number">4</span><span class=
"special">);
</span>
134 <span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">int512_t
</span> <span class=
"identifier">c
</span><span class=
"special">(
</span><span class=
"number">50</span><span class=
"special">),
</span> <span class=
"identifier">d
</span><span class=
"special">;
</span>
136 <span class=
"identifier">d
</span> <span class=
"special">=
</span> <span class=
"identifier">c
</span> <span class=
"special">*
</span> <span class=
"identifier">a
</span><span class=
"special">;
</span> <span class=
"comment">// OK, result of mixed arithmetic is an int512_t
</span>
139 Conversions are also allowed:
141 <pre class=
"programlisting"><span class=
"identifier">d
</span> <span class=
"special">=
</span> <span class=
"identifier">a
</span><span class=
"special">;
</span> <span class=
"comment">// OK, widening conversion.
</span>
142 <span class=
"identifier">d
</span> <span class=
"special">=
</span> <span class=
"identifier">a
</span> <span class=
"special">*
</span> <span class=
"identifier">b
</span><span class=
"special">;
</span> <span class=
"comment">// OK, can convert from an expression template too.
</span>
145 However conversions that are inherently lossy are either declared explicit
146 or else forbidden altogether:
148 <pre class=
"programlisting"><span class=
"identifier">d
</span> <span class=
"special">=
</span> <span class=
"number">3.14</span><span class=
"special">;
</span> <span class=
"comment">// Error implicit conversion from float not allowed.
</span>
149 <span class=
"identifier">d
</span> <span class=
"special">=
</span> <span class=
"keyword">static_cast
</span><span class=
"special"><</span><span class=
"identifier">mp
</span><span class=
"special">::
</span><span class=
"identifier">int512_t
</span><span class=
"special">>(
</span><span class=
"number">3.14</span><span class=
"special">);
</span> <span class=
"comment">// OK explicit construction is allowed
</span>
152 Mixed arithmetic will fail if the conversion is either ambiguous or explicit:
154 <pre class=
"programlisting"><span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">cpp_int_backend
</span><span class=
"special"><>,
</span> <span class=
"identifier">et_off
</span><span class=
"special">></span> <span class=
"identifier">a
</span><span class=
"special">(
</span><span class=
"number">2</span><span class=
"special">);
</span>
155 <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">cpp_int_backend
</span><span class=
"special"><>,
</span> <span class=
"identifier">et_on
</span><span class=
"special">></span> <span class=
"identifier">b
</span><span class=
"special">(
</span><span class=
"number">3</span><span class=
"special">);
</span>
157 <span class=
"identifier">b
</span> <span class=
"special">=
</span> <span class=
"identifier">a
</span> <span class=
"special">*
</span> <span class=
"identifier">b
</span><span class=
"special">;
</span> <span class=
"comment">// Error, implicit conversion could go either way.
</span>
158 <span class=
"identifier">b
</span> <span class=
"special">=
</span> <span class=
"identifier">a
</span> <span class=
"special">*
</span> <span class=
"number">3.14</span><span class=
"special">;
</span> <span class=
"comment">// Error, no operator overload if the conversion would be explicit.
</span>
161 <a name=
"boost_multiprecision.intro.h0"></a>
162 <span class=
"phrase"><a name=
"boost_multiprecision.intro.move_semantics"></a></span><a class=
"link" href=
"intro.html#boost_multiprecision.intro.move_semantics">Move
166 On compilers that support rvalue-references, class
<code class=
"computeroutput"><span class=
"identifier">number
</span></code>
167 is move-enabled if the underlying backend is.
170 In addition the non-expression template operator overloads (see below) are
171 move aware and have overloads that look something like:
173 <pre class=
"programlisting"><span class=
"keyword">template
</span> <span class=
"special"><</span><span class=
"keyword">class
</span> <span class=
"identifier">B
</span><span class=
"special">></span>
174 <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">B
</span><span class=
"special">,
</span> <span class=
"identifier">et_off
</span><span class=
"special">></span> <span class=
"keyword">operator
</span> <span class=
"special">+
</span> <span class=
"special">(
</span><span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">B
</span><span class=
"special">,
</span> <span class=
"identifier">et_off
</span><span class=
"special">>&&</span> <span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"keyword">const
</span> <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">B
</span><span class=
"special">,
</span> <span class=
"identifier">et_off
</span><span class=
"special">>&</span> <span class=
"identifier">b
</span><span class=
"special">)
</span>
175 <span class=
"special">{
</span>
176 <span class=
"keyword">return
</span> <span class=
"identifier">std
</span><span class=
"special">::
</span><span class=
"identifier">move
</span><span class=
"special">(
</span><span class=
"identifier">a
</span> <span class=
"special">+=
</span> <span class=
"identifier">b
</span><span class=
"special">);
</span>
177 <span class=
"special">}
</span>
180 These operator overloads ensure that many expressions can be evaluated without
181 actually generating any temporaries. However, there are still many simple expressions
184 <pre class=
"programlisting"><span class=
"identifier">a
</span> <span class=
"special">=
</span> <span class=
"identifier">b
</span> <span class=
"special">*
</span> <span class=
"identifier">c
</span><span class=
"special">;
</span>
187 Which don't noticeably benefit from move support. Therefore, optimal performance
188 comes from having both move-support, and expression templates enabled.
191 Note that while
"moved-from" objects are left in a sane state, they
192 have an unspecified value, and the only permitted operations on them are destruction
193 or the assignment of a new value. Any other operation should be considered
194 a programming error and all of our backends will trigger an assertion if any
195 other operation is attempted. This behavior allows for optimal performance
196 on move-construction (i.e. no allocation required, we just take ownership of
197 the existing object's internal state), while maintaining usability in the standard
201 <a name=
"boost_multiprecision.intro.h1"></a>
202 <span class=
"phrase"><a name=
"boost_multiprecision.intro.expression_templates"></a></span><a class=
"link" href=
"intro.html#boost_multiprecision.intro.expression_templates">Expression
206 Class
<code class=
"computeroutput"><span class=
"identifier">number
</span></code> is expression-template-enabled:
207 that means that rather than having a multiplication operator that looks like
210 <pre class=
"programlisting"><span class=
"keyword">template
</span> <span class=
"special"><</span><span class=
"keyword">class
</span> <span class=
"identifier">Backend
</span><span class=
"special">></span>
211 <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">></span> <span class=
"keyword">operator
</span> <span class=
"special">*
</span> <span class=
"special">(
</span><span class=
"keyword">const
</span> <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">>&</span> <span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"keyword">const
</span> <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">>&</span> <span class=
"identifier">b
</span><span class=
"special">)
</span>
212 <span class=
"special">{
</span>
213 <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">></span> <span class=
"identifier">result
</span><span class=
"special">(
</span><span class=
"identifier">a
</span><span class=
"special">);
</span>
214 <span class=
"identifier">result
</span> <span class=
"special">*=
</span> <span class=
"identifier">b
</span><span class=
"special">;
</span>
215 <span class=
"keyword">return
</span> <span class=
"identifier">result
</span><span class=
"special">;
</span>
216 <span class=
"special">}
</span>
219 Instead the operator looks more like this:
221 <pre class=
"programlisting"><span class=
"keyword">template
</span> <span class=
"special"><</span><span class=
"keyword">class
</span> <span class=
"identifier">Backend
</span><span class=
"special">></span>
222 <span class=
"emphasis"><em>unmentionable-type
</em></span> <span class=
"keyword">operator
</span> <span class=
"special">*
</span> <span class=
"special">(
</span><span class=
"keyword">const
</span> <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">>&</span> <span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"keyword">const
</span> <span class=
"identifier">number
</span><span class=
"special"><</span><span class=
"identifier">Backend
</span><span class=
"special">>&</span> <span class=
"identifier">b
</span><span class=
"special">);
</span>
225 Where the
"unmentionable" return type is an implementation detail
226 that, rather than containing the result of the multiplication, contains instructions
227 on how to compute the result. In effect it's just a pair of references to the
228 arguments of the function, plus some compile-time information that stores what
232 The great advantage of this method is the
<span class=
"emphasis"><em>elimination of temporaries
</em></span>:
233 for example the
"naive" implementation of
<code class=
"computeroutput"><span class=
"keyword">operator
</span><span class=
"special">*
</span></code> above, requires one temporary for computing
234 the result, and at least another one to return it. It's true that sometimes
235 this overhead can be reduced by using move-semantics, but it can't be eliminated
236 completely. For example, lets suppose we're evaluating a polynomial via Horner's
237 method, something like this:
239 <pre class=
"programlisting"><span class=
"identifier">T
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">7</span><span class=
"special">]
</span> <span class=
"special">=
</span> <span class=
"special">{
</span> <span class=
"comment">/* some values */
</span> <span class=
"special">};
</span>
240 <span class=
"comment">//....
</span>
241 <span class=
"identifier">y
</span> <span class=
"special">=
</span> <span class=
"special">(((((
</span><span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">6</span><span class=
"special">]
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">5</span><span class=
"special">])
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">4</span><span class=
"special">])
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">3</span><span class=
"special">])
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">2</span><span class=
"special">])
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">1</span><span class=
"special">])
</span> <span class=
"special">*
</span> <span class=
"identifier">x
</span> <span class=
"special">+
</span> <span class=
"identifier">a
</span><span class=
"special">[
</span><span class=
"number">0</span><span class=
"special">];
</span>
244 If type
<code class=
"computeroutput"><span class=
"identifier">T
</span></code> is a
<code class=
"computeroutput"><span class=
"identifier">number
</span></code>, then this expression is evaluated
245 <span class=
"emphasis"><em>without creating a single temporary value
</em></span>. In contrast,
246 if we were using the
<a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a>
247 C++ wrapper for
<a href=
"http://www.mpfr.org" target=
"_top">MPFR
</a> - then this expression
248 would result in no less than
11 temporaries (this is true even though
<a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a> does
249 use expression templates to reduce the number of temporaries somewhat). Had
250 we used an even simpler wrapper around
<a href=
"http://www.mpfr.org" target=
"_top">MPFR
</a>
251 like
<a href=
"http://www.holoborodko.com/pavel/mpfr/" target=
"_top">mpreal
</a> things
252 would have been even worse and no less that
24 temporaries are created for
253 this simple expression (note - we actually measure the number of memory allocations
254 performed rather than the number of temporaries directly, note also that the
255 <a href=
"http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats" target=
"_top">mpf_class
</a>
256 wrapper that will be supplied with GMP-
5.1 reduces the number of temporaries
257 to pretty much zero). Note that if we compile with expression templates disabled
258 and rvalue-reference support on, then actually still have no wasted memory
259 allocations as even though temporaries are created, their contents are moved
260 rather than copied.
<a href=
"#ftn.boost_multiprecision.intro.f0" class=
"footnote"><sup class=
"footnote"><a name=
"boost_multiprecision.intro.f0"></a>[
1]
</sup></a>
262 <div class=
"important"><table border=
"0" summary=
"Important">
264 <td rowspan=
"2" align=
"center" valign=
"top" width=
"25"><img alt=
"[Important]" src=
"../../../../../doc/src/images/important.png"></td>
265 <th align=
"left">Important
</th>
267 <tr><td align=
"left" valign=
"top">
269 Expression templates can radically reorder the operations in an expression,
276 Will get transformed into:
282 If this is likely to be an issue for a particular application, then they
288 This library also extends expression template support to standard library functions
289 like
<code class=
"computeroutput"><span class=
"identifier">abs
</span></code> or
<code class=
"computeroutput"><span class=
"identifier">sin
</span></code>
290 with
<code class=
"computeroutput"><span class=
"identifier">number
</span></code> arguments. This
291 means that an expression such as:
293 <pre class=
"programlisting"><span class=
"identifier">y
</span> <span class=
"special">=
</span> <span class=
"identifier">abs
</span><span class=
"special">(
</span><span class=
"identifier">x
</span><span class=
"special">);
</span>
296 can be evaluated without a single temporary being calculated. Even expressions
299 <pre class=
"programlisting"><span class=
"identifier">y
</span> <span class=
"special">=
</span> <span class=
"identifier">sin
</span><span class=
"special">(
</span><span class=
"identifier">x
</span><span class=
"special">);
</span>
302 get this treatment, so that variable 'y' is used as
"working storage"
303 within the implementation of
<code class=
"computeroutput"><span class=
"identifier">sin
</span></code>,
304 thus reducing the number of temporaries used by one. Of course, should you
307 <pre class=
"programlisting"><span class=
"identifier">x
</span> <span class=
"special">=
</span> <span class=
"identifier">sin
</span><span class=
"special">(
</span><span class=
"identifier">x
</span><span class=
"special">);
</span>
310 Then we clearly can't use
<code class=
"computeroutput"><span class=
"identifier">x
</span></code>
311 as working storage during the calculation, so then a temporary variable is
312 created in this case.
315 Given the comments above, you might be forgiven for thinking that expression-templates
316 are some kind of universal-panacea: sadly though, all tricks like this have
317 their downsides. For one thing, expression template libraries like this one,
318 tend to be slower to compile than their simpler cousins, they're also harder
319 to debug (should you actually want to step through our code!), and rely on
320 compiler optimizations being turned on to give really good performance. Also,
321 since the return type from expressions involving
<code class=
"computeroutput"><span class=
"identifier">number
</span></code>s
322 is an
"unmentionable implementation detail", you have to be careful
323 to cast the result of an expression to the actual number type when passing
324 an expression to a template function. For example, given:
326 <pre class=
"programlisting"><span class=
"keyword">template
</span> <span class=
"special"><</span><span class=
"keyword">class
</span> <span class=
"identifier">T
</span><span class=
"special">></span>
327 <span class=
"keyword">void
</span> <span class=
"identifier">my_proc
</span><span class=
"special">(
</span><span class=
"keyword">const
</span> <span class=
"identifier">T
</span><span class=
"special">&);
</span>
332 <pre class=
"programlisting"><span class=
"identifier">my_proc
</span><span class=
"special">(
</span><span class=
"identifier">a
</span><span class=
"special">+
</span><span class=
"identifier">b
</span><span class=
"special">);
</span>
335 Will very likely result in obscure error messages inside the body of
<code class=
"computeroutput"><span class=
"identifier">my_proc
</span></code> - since we've passed it an expression
336 template type, and not a number type. Instead we probably need:
338 <pre class=
"programlisting"><span class=
"identifier">my_proc
</span><span class=
"special">(
</span><span class=
"identifier">my_number_type
</span><span class=
"special">(
</span><span class=
"identifier">a
</span><span class=
"special">+
</span><span class=
"identifier">b
</span><span class=
"special">));
</span>
341 Having said that, these situations don't occur that often - or indeed not at
342 all for non-template functions. In addition, all the functions in the Boost.Math
343 library will automatically convert expression-template arguments to the underlying
344 number type without you having to do anything, so:
346 <pre class=
"programlisting"><span class=
"identifier">mpfr_float_100
</span> <span class=
"identifier">a
</span><span class=
"special">(
</span><span class=
"number">20</span><span class=
"special">),
</span> <span class=
"identifier">delta
</span><span class=
"special">(
</span><span class=
"number">0.125</span><span class=
"special">);
</span>
347 <span class=
"identifier">boost
</span><span class=
"special">::
</span><span class=
"identifier">math
</span><span class=
"special">::
</span><span class=
"identifier">gamma_p
</span><span class=
"special">(
</span><span class=
"identifier">a
</span><span class=
"special">,
</span> <span class=
"identifier">a
</span> <span class=
"special">+
</span> <span class=
"identifier">delta
</span><span class=
"special">);
</span>
350 Will work just fine, with the
<code class=
"computeroutput"><span class=
"identifier">a
</span> <span class=
"special">+
</span> <span class=
"identifier">delta
</span></code> expression
351 template argument getting converted to an
<code class=
"computeroutput"><span class=
"identifier">mpfr_float_100
</span></code>
352 internally by the Boost.Math library.
355 One other potential pitfall that's only possible in C++
11: you should never
356 store an expression template using:
358 <pre class=
"programlisting"><span class=
"keyword">auto
</span> <span class=
"identifier">my_expression
</span> <span class=
"special">=
</span> <span class=
"identifier">a
</span> <span class=
"special">+
</span> <span class=
"identifier">b
</span> <span class=
"special">-
</span> <span class=
"identifier">c
</span><span class=
"special">;
</span>
361 unless you're absolutely sure that the lifetimes of
<code class=
"computeroutput"><span class=
"identifier">a
</span></code>,
362 <code class=
"computeroutput"><span class=
"identifier">b
</span></code> and
<code class=
"computeroutput"><span class=
"identifier">c
</span></code>
363 will outlive that of
<code class=
"computeroutput"><span class=
"identifier">my_expression
</span></code>.
366 And finally... the performance improvements from an expression template library
367 like this are often not as dramatic as the reduction in number of temporaries
368 would suggest. For example if we compare this library with
<a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a>
369 and
<a href=
"http://www.holoborodko.com/pavel/mpfr/" target=
"_top">mpreal
</a>, with
370 all three using the underlying
<a href=
"http://www.mpfr.org" target=
"_top">MPFR
</a>
371 library at
50 decimal digits precision then we see the following typical results
372 for polynomial execution:
375 <a name=
"boost_multiprecision.intro.evaluation_of_order_6_polynomial"></a><p class=
"title"><b>Table
 1.1.
 Evaluation of Order
6 Polynomial.
</b></p>
376 <div class=
"table-contents"><table class=
"table" summary=
"Evaluation of Order 6 Polynomial.">
395 Relative number of memory allocations
420 <a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a>
437 <a href=
"http://www.holoborodko.com/pavel/mpfr/" target=
"_top">mpreal
</a>
454 <br class=
"table-break"><p>
455 As you can see, the execution time increases a lot more slowly than the number
456 of memory allocations. There are a number of reasons for this:
458 <div class=
"itemizedlist"><ul class=
"itemizedlist" style=
"list-style-type: disc; ">
459 <li class=
"listitem">
460 The cost of extended-precision multiplication and division is so great,
461 that the times taken for these tend to swamp everything else.
463 <li class=
"listitem">
464 The cost of an in-place multiplication (using
<code class=
"computeroutput"><span class=
"keyword">operator
</span><span class=
"special">*=
</span></code>) tends to be more than an out-of-place
465 <code class=
"computeroutput"><span class=
"keyword">operator
</span><span class=
"special">*
</span></code>
466 (typically
<code class=
"computeroutput"><span class=
"keyword">operator
</span> <span class=
"special">*=
</span></code>
467 has to create a temporary workspace to carry out the multiplication, where
468 as
<code class=
"computeroutput"><span class=
"keyword">operator
</span><span class=
"special">*
</span></code>
469 can use the target variable as workspace). Since the expression templates
470 carry out their magic by converting out-of-place operators to in-place
471 ones, we necessarily take this hit. Even so the transformation is more
472 efficient than creating the extra temporary variable, just not by as much
477 Finally, note that
<code class=
"computeroutput"><span class=
"identifier">number
</span></code> takes
478 a second template argument, which, when set to
<code class=
"computeroutput"><span class=
"identifier">et_off
</span></code>
479 disables all the expression template machinery. The result is much faster to
480 compile, but slower at runtime.
483 We'll conclude this section by providing some more performance comparisons
484 between these three libraries, again, all are using
<a href=
"http://www.mpfr.org" target=
"_top">MPFR
</a>
485 to carry out the underlying arithmetic, and all are operating at the same precision
489 <a name=
"boost_multiprecision.intro.evaluation_of_boost_math_s_besse"></a><p class=
"title"><b>Table
 1.2.
 Evaluation of Boost.Math's Bessel function test data
</b></p>
490 <div class=
"table-contents"><table class=
"table" summary=
"Evaluation of Boost.Math's Bessel function test data">
509 Relative Number of Memory Allocations
534 number
<mpfr_float_backend
<50>, et_off
><br> (but with
535 rvalue reference support)
552 <a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a>
569 <a href=
"http://www.holoborodko.com/pavel/mpfr/" target=
"_top">mpreal
</a>
586 <br class=
"table-break"><div class=
"table">
587 <a name=
"boost_multiprecision.intro.evaluation_of_boost_math_s_non_c"></a><p class=
"title"><b>Table
 1.3.
 Evaluation of Boost.Math's Non-Central T distribution test data
</b></p>
588 <div class=
"table-contents"><table class=
"table" summary=
"Evaluation of Boost.Math's Non-Central T distribution test data">
607 Relative Number of Memory Allocations
632 number
<mpfr_float_backend
<50>, et_off
><br> (but with
633 rvalue reference support)
650 <a href=
"http://math.berkeley.edu/~wilken/code/gmpfrxx/" target=
"_top">mpfr_class
</a>
667 <a href=
"http://www.holoborodko.com/pavel/mpfr/" target=
"_top">mpreal
</a>
684 <br class=
"table-break"><p>
685 The above results were generated on Win32 compiling with Visual C++
2010, all
686 optimizations on (/Ox), with MPFR
3.0 and MPIR
2.3.0.
688 <div class=
"footnotes">
689 <br><hr style=
"width:100; align:left;">
690 <div id=
"ftn.boost_multiprecision.intro.f0" class=
"footnote"><p><a href=
"#boost_multiprecision.intro.f0" class=
"para"><sup class=
"para">[
1]
</sup></a>
691 The actual number generated will depend on the compiler, how well it optimises
692 the code, and whether it supports rvalue references. The number of
11 temporaries
693 was generated with Visual C++
10
697 <table xmlns:
rev=
"http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width=
"100%"><tr>
698 <td align=
"left"></td>
699 <td align=
"right"><div class=
"copyright-footer">Copyright
© 2002-
2013 John Maddock and Christopher Kormanyos
<p>
700 Distributed under the Boost Software License, Version
1.0. (See accompanying
701 file LICENSE_1_0.txt or copy at
<a href=
"http://www.boost.org/LICENSE_1_0.txt" target=
"_top">http://www.boost.org/LICENSE_1_0.txt
</a>)
706 <div class=
"spirit-nav">
707 <a accesskey=
"p" href=
"../index.html"><img src=
"../../../../../doc/src/images/prev.png" alt=
"Prev"></a><a accesskey=
"u" href=
"../index.html"><img src=
"../../../../../doc/src/images/up.png" alt=
"Up"></a><a accesskey=
"h" href=
"../index.html"><img src=
"../../../../../doc/src/images/home.png" alt=
"Home"></a><a accesskey=
"n" href=
"tut.html"><img src=
"../../../../../doc/src/images/next.png" alt=
"Next"></a>