1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Introduction</title> 5<link rel="stylesheet" href="../multiprecision.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.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"> 11</head> 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> 20</tr></table> 21<hr> 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> 24</div> 25<div class="section"> 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> 29<p> 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>, <a class="link" href="tut/floats.html" title="Floating-point Types">floating-point</a>, 32 and <a class="link" href="tut/complex.html" title="Complex Number Types">complex</a> types in 33 C++ that have more range and precision than C++'s ordinary <a href="https://en.cppreference.com/w/cpp/language/types" target="_top">fundamental 34 (built-in)</a> types. The big number types in Multiprecision can be used 35 with a wide selection of basic mathematical operations, elementary transcendental 36 functions as well as the functions in Boost.Math. The Multiprecision types 37 can also interoperate with any <a href="https://en.cppreference.com/w/cpp/language/types" target="_top">fundamental 38 (built-in) type</a> in C++ using clearly defined conversion rules. This 39 allows Boost.Multiprecision to be used for all kinds of mathematical calculations 40 involving integer, rational and floating-point types requiring extended range 41 and precision. 42 </p> 43<p> 44 Multiprecision consists of a generic interface to the mathematics of large 45 numbers as well as a selection of big number back-ends, with support for integer, 46 rational, floating-point, and complex types. Boost.Multiprecision provides 47 a selection of back-ends provided off-the-rack in including interfaces to GMP, 48 MPFR, MPIR, MPC, TomMath as well as its own collection of Boost-licensed, header-only 49 back-ends for integers, rationals and floats. In addition, user-defined back-ends 50 can be created and used with the interface of Multiprecision, provided the 51 class implementation adheres to the necessary <a class="link" href="ref/backendconc.html" title="Backend Requirements">concepts</a>. 52 </p> 53<p> 54 Depending upon the number type, precision may be arbitrarily large (limited 55 only by available memory), fixed at compile time (for example, 50 or 100 decimal 56 digits), or a variable controlled at run-time by member functions. The types 57 are <a href="https://en.wikipedia.org/wiki/Expression_templates" target="_top">expression 58 templates</a> - enabled for better performance than naive user-defined 59 types. 60 </p> 61<p> 62 The Multiprecision library comes in two distinct parts: 63 </p> 64<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 65<li class="listitem"> 66 An expression-template-enabled front-end <code class="computeroutput"><span class="identifier">number</span></code> 67 that handles all the operator overloading, expression evaluation optimization, 68 and code reduction. 69 </li> 70<li class="listitem"> 71 A selection of back-ends that implement the actual arithmetic operations, 72 and need conform only to the reduced interface requirements of the front-end. 73 </li> 74</ul></div> 75<p> 76 Separation of front-end and back-end allows use of highly refined, but restricted 77 license libraries where possible, but provides Boost license alternatives for 78 users who must have a portable unconstrained license. Which is to say some 79 back-ends rely on 3rd party libraries, but a header-only Boost license version 80 is always available (if somewhat slower). 81 </p> 82<h6> 83<a name="boost_multiprecision.intro.h0"></a> 84 <span class="phrase"><a name="boost_multiprecision.intro.getting_started"></a></span><a class="link" href="intro.html#boost_multiprecision.intro.getting_started">Getting 85 started with Boost.Multiprecision</a> 86 </h6> 87<p> 88 Should you just wish to 'cut to the chase' just to get bigger integers and/or 89 bigger and more precise reals as simply and portably as possible, close to 90 'drop-in' replacements for the <a href="https://en.cppreference.com/w/cpp/language/types" target="_top">fundamental 91 (built-in) type</a> analogs, then use a fully Boost-licensed number type, 92 and skip to one of more of : 93 </p> 94<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 95<li class="listitem"> 96 <a class="link" href="tut/ints/cpp_int.html" title="cpp_int">cpp_int</a> for 97 multiprecision integers, 98 </li> 99<li class="listitem"> 100 <a class="link" href="tut/rational/cpp_rational.html" title="cpp_rational">cpp_rational</a> 101 for rational types, 102 </li> 103<li class="listitem"> 104 <a class="link" href="tut/floats/cpp_bin_float.html" title="cpp_bin_float">cpp_bin_float</a> 105 and <a class="link" href="tut/floats/cpp_dec_float.html" title="cpp_dec_float">cpp_dec_float</a> 106 for multiprecision floating-point types, 107 </li> 108<li class="listitem"> 109 <a class="link" href="tut/complex/cpp_complex.html" title="cpp_complex">cpp_complex</a> 110 for complex types. 111 </li> 112</ul></div> 113<p> 114 The library is very often used via one of the predefined convenience <code class="computeroutput"><span class="keyword">typedef</span></code>s like <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">int128_t</span></code> 115 or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">cpp_bin_float_quad</span></code>. 116 </p> 117<p> 118 For example, if you want a signed, 128-bit fixed size integer: 119 </p> 120<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> <span class="comment">// Integer types.</span> 121 122<span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">int128_t</span> <span class="identifier">my_128_bit_int</span><span class="special">;</span> 123</pre> 124<p> 125 Alternatively, and more adventurously, if you wanted an <a href="http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic" target="_top">arbitrary 126 precision</a> integer type using <a href="http://gmplib.org" target="_top">GMP</a> 127 as the underlying implementation then you could use: 128 </p> 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">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> 130 131<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> 132</pre> 133<p> 134 Or for a simple, portable 128-bit floating-point close to a drop-in for a 135 <a href="https://en.cppreference.com/w/cpp/language/types" target="_top">fundamental (built-in) 136 type</a> like <code class="computeroutput"><span class="keyword">double</span></code>, usually 137 64-bit 138 </p> 139<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_bin_float</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> 140 141<span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">::</span><span class="identifier">cpp_bin_float_quad</span> <span class="identifier">my_quad_real</span><span class="special">;</span> 142</pre> 143<p> 144 Alternatively, you can compose your own 'custom' multiprecision type, by combining 145 <code class="computeroutput"><span class="identifier">number</span></code> with one of the predefined 146 back-end types. For example, suppose you wanted a 300 decimal digit floating-point 147 type based on the <a href="http://www.mpfr.org" target="_top">MPFR</a> library. In 148 this case, there's no predefined <code class="computeroutput"><span class="keyword">typedef</span></code> 149 with that level of precision, so instead we compose our own: 150 </p> 151<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> 152 153<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> 154 155<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> 156 157<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> 158</pre> 159<p> 160 We can repeat the above example, but with the expression templates disabled 161 (for faster compile times, but slower runtimes) by passing a second template 162 argument to <code class="computeroutput"><span class="identifier">number</span></code>: 163 </p> 164<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> 165 166<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> 167 168<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> 169 170<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> 171</pre> 172<p> 173 We can also mix arithmetic operations between different types, provided there 174 is an unambiguous implicit conversion from one type to the other: 175 </p> 176<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> 177 178<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> 179 180<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> 181<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> 182 183<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> 184</pre> 185<p> 186 Conversions are also allowed: 187 </p> 188<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> 189<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> 190</pre> 191<p> 192 However conversions that are inherently lossy are either declared explicit 193 or else forbidden altogether: 194 </p> 195<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 double not allowed.</span> 196<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> 197</pre> 198<p> 199 Mixed arithmetic will fail if the conversion is either ambiguous or explicit: 200 </p> 201<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> 202<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> 203 204<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> 205<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> 206</pre> 207<h5> 208<a name="boost_multiprecision.intro.h1"></a> 209 <span class="phrase"><a name="boost_multiprecision.intro.move_semantics"></a></span><a class="link" href="intro.html#boost_multiprecision.intro.move_semantics">Move 210 Semantics</a> 211 </h5> 212<p> 213 On compilers that support rvalue-references, class <code class="computeroutput"><span class="identifier">number</span></code> 214 is move-enabled if the underlying backend is. 215 </p> 216<p> 217 In addition the non-expression template operator overloads (see below) are 218 move aware and have overloads that look something like: 219 </p> 220<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> 221<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> 222<span class="special">{</span> 223 <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> 224<span class="special">}</span> 225</pre> 226<p> 227 These operator overloads ensure that many expressions can be evaluated without 228 actually generating any temporaries. However, there are still many simple expressions 229 such as 230 </p> 231<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> 232</pre> 233<p> 234 which don't noticeably benefit from move support. Therefore, optimal performance 235 comes from having both move-support, and expression templates enabled. 236 </p> 237<p> 238 Note that while "moved-from" objects are left in a sane state, they 239 have an unspecified value, and the only permitted operations on them are destruction 240 or the assignment of a new value. Any other operation should be considered 241 a programming error and all of our backends will trigger an assertion if any 242 other operation is attempted. This behavior allows for optimal performance 243 on move-construction (i.e. no allocation required, we just take ownership of 244 the existing object's internal state), while maintaining usability in the standard 245 library containers. 246 </p> 247<h5> 248<a name="boost_multiprecision.intro.h2"></a> 249 <span class="phrase"><a name="boost_multiprecision.intro.expression_templates"></a></span><a class="link" href="intro.html#boost_multiprecision.intro.expression_templates">Expression 250 Templates</a> 251 </h5> 252<p> 253 Class <code class="computeroutput"><span class="identifier">number</span></code> is expression-template-enabled: 254 that means that rather than having a multiplication operator that looks like 255 this: 256 </p> 257<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> 258<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> 259<span class="special">{</span> 260 <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> 261 <span class="identifier">result</span> <span class="special">*=</span> <span class="identifier">b</span><span class="special">;</span> 262 <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span> 263<span class="special">}</span> 264</pre> 265<p> 266 Instead the operator looks more like this: 267 </p> 268<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> 269<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> 270</pre> 271<p> 272 Where the '<span class="emphasis"><em>unmentionable</em></span>' return type is an implementation 273 detail that, rather than containing the result of the multiplication, contains 274 instructions on how to compute the result. In effect it's just a pair of references 275 to the arguments of the function, plus some compile-time information that stores 276 what the operation is. 277 </p> 278<p> 279 The great advantage of this method is the <span class="emphasis"><em>elimination of temporaries</em></span>: 280 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 281 the result, and at least another one to return it. It's true that sometimes 282 this overhead can be reduced by using move-semantics, but it can't be eliminated 283 completely. For example, lets suppose we're evaluating a polynomial via Horner's 284 method, something like this: 285 </p> 286<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> 287<span class="comment">//....</span> 288<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> 289</pre> 290<p> 291 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 292 <span class="emphasis"><em>without creating a single temporary value</em></span>. In contrast, 293 if we were using the <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a> 294 C++ wrapper for <a href="http://www.mpfr.org" target="_top">MPFR</a> - then this expression 295 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 296 use expression templates to reduce the number of temporaries somewhat). Had 297 we used an even simpler wrapper around <a href="http://www.mpfr.org" target="_top">MPFR</a> 298 like <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a> things 299 would have been even worse and no less that 24 temporaries are created for 300 this simple expression (note - we actually measure the number of memory allocations 301 performed rather than the number of temporaries directly, note also that the 302 <a href="http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats" target="_top">mpf_class</a> 303 wrapper that will be supplied with GMP-5.1 reduces the number of temporaries 304 to pretty much zero). Note that if we compile with expression templates disabled 305 and rvalue-reference support on, then actually still have no wasted memory 306 allocations as even though temporaries are created, their contents are moved 307 rather than copied. <a href="#ftn.boost_multiprecision.intro.f0" class="footnote" name="boost_multiprecision.intro.f0"><sup class="footnote">[1]</sup></a> 308 </p> 309<div class="important"><table border="0" summary="Important"> 310<tr> 311<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> 312<th align="left">Important</th> 313</tr> 314<tr><td align="left" valign="top"> 315<p> 316 Expression templates can radically reorder the operations in an expression, 317 for example: 318 </p> 319<p> 320 a = (b * c) * a; 321 </p> 322<p> 323 Will get transformed into: 324 </p> 325<p> 326 a *= c; a *= b; 327 </p> 328<p> 329 If this is likely to be an issue for a particular application, then they 330 should be disabled. 331 </p> 332</td></tr> 333</table></div> 334<p> 335 This library also extends expression template support to standard library functions 336 like <code class="computeroutput"><span class="identifier">abs</span></code> or <code class="computeroutput"><span class="identifier">sin</span></code> 337 with <code class="computeroutput"><span class="identifier">number</span></code> arguments. This 338 means that an expression such as: 339 </p> 340<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> 341</pre> 342<p> 343 can be evaluated without a single temporary being calculated. Even expressions 344 like: 345 </p> 346<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> 347</pre> 348<p> 349 get this treatment, so that variable 'y' is used as "working storage" 350 within the implementation of <code class="computeroutput"><span class="identifier">sin</span></code>, 351 thus reducing the number of temporaries used by one. Of course, should you 352 write: 353 </p> 354<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> 355</pre> 356<p> 357 Then we clearly can't use <code class="computeroutput"><span class="identifier">x</span></code> 358 as working storage during the calculation, so then a temporary variable is 359 created in this case. 360 </p> 361<p> 362 Given the comments above, you might be forgiven for thinking that expression-templates 363 are some kind of universal-panacea: sadly though, all tricks like this have 364 their downsides. For one thing, expression template libraries like this one, 365 tend to be slower to compile than their simpler cousins, they're also harder 366 to debug (should you actually want to step through our code!), and rely on 367 compiler optimizations being turned on to give really good performance. Also, 368 since the return type from expressions involving <code class="computeroutput"><span class="identifier">number</span></code>s 369 is an "unmentionable implementation detail", you have to be careful 370 to cast the result of an expression to the actual number type when passing 371 an expression to a template function. For example, given: 372 </p> 373<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> 374<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> 375</pre> 376<p> 377 Then calling: 378 </p> 379<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> 380</pre> 381<p> 382 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 383 template type, and not a number type. Instead we probably need: 384 </p> 385<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> 386</pre> 387<p> 388 Having said that, these situations don't occur that often - or indeed not at 389 all for non-template functions. In addition, all the functions in the Boost.Math 390 library will automatically convert expression-template arguments to the underlying 391 number type without you having to do anything, so: 392 </p> 393<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> 394<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> 395</pre> 396<p> 397 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 398 template argument getting converted to an <code class="computeroutput"><span class="identifier">mpfr_float_100</span></code> 399 internally by the Boost.Math library. 400 </p> 401<div class="caution"><table border="0" summary="Caution"> 402<tr> 403<td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="../../../../../doc/src/images/caution.png"></td> 404<th align="left">Caution</th> 405</tr> 406<tr><td align="left" valign="top"> 407<p> 408 In C++11 you should never store an expression template using: 409 </p> 410<p> 411 <code class="computeroutput"><span class="keyword">auto</span> <span class="identifier">my_expression</span> 412 <span class="special">=</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">-</span> 413 <span class="identifier">c</span><span class="special">;</span></code> 414 </p> 415<p> 416 unless you're absolutely sure that the lifetimes of <code class="computeroutput"><span class="identifier">a</span></code>, 417 <code class="computeroutput"><span class="identifier">b</span></code> and <code class="computeroutput"><span class="identifier">c</span></code> 418 will outlive that of <code class="computeroutput"><span class="identifier">my_expression</span></code>. 419 </p> 420<p> 421 In fact, it is particularly easy to create dangling references by mixing 422 expression templates with the <code class="computeroutput"><span class="keyword">auto</span></code> 423 keyword, for example: 424 </p> 425<p> 426 <code class="computeroutput"><span class="keyword">auto</span> <span class="identifier">val</span> 427 <span class="special">=</span> <span class="identifier">cpp_dec_float_50</span><span class="special">(</span><span class="string">"23.1"</span><span class="special">)</span> <span class="special">*</span> <span class="number">100</span><span class="special">;</span></code> 428 </p> 429<p> 430 In this situation, the integer literal is stored directly in the expression 431 template - so its use is OK here - but the <code class="computeroutput"><span class="identifier">cpp_dec_float_50</span></code> 432 temporary is stored by reference and then destructed when the statement completes, 433 leaving a dangling reference. 434 </p> 435<p> 436 <span class="bold"><strong><span class="emphasis"><em>If in doubt, do not ever mix expression templates 437 with the <code class="computeroutput"><span class="keyword">auto</span></code> keyword.</em></span></strong></span> 438 </p> 439</td></tr> 440</table></div> 441<p> 442 And finally... the performance improvements from an expression template library 443 like this are often not as dramatic as the reduction in number of temporaries 444 would suggest. For example, if we compare this library with <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a> 445 and <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a>, with 446 all three using the underlying <a href="http://www.mpfr.org" target="_top">MPFR</a> 447 library at 50 decimal digits precision then we see the following typical results 448 for polynomial execution: 449 </p> 450<div class="table"> 451<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> 452<div class="table-contents"><table class="table" summary="Evaluation of Order 6 Polynomial."> 453<colgroup> 454<col> 455<col> 456<col> 457</colgroup> 458<thead><tr> 459<th> 460 <p> 461 Library 462 </p> 463 </th> 464<th> 465 <p> 466 Relative Time 467 </p> 468 </th> 469<th> 470 <p> 471 Relative number of memory allocations 472 </p> 473 </th> 474</tr></thead> 475<tbody> 476<tr> 477<td> 478 <p> 479 number 480 </p> 481 </td> 482<td> 483 <p> 484 1.0 (0.00957s) 485 </p> 486 </td> 487<td> 488 <p> 489 1.0 (2996 total) 490 </p> 491 </td> 492</tr> 493<tr> 494<td> 495 <p> 496 <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a> 497 </p> 498 </td> 499<td> 500 <p> 501 1.1 (0.0102s) 502 </p> 503 </td> 504<td> 505 <p> 506 4.3 (12976 total) 507 </p> 508 </td> 509</tr> 510<tr> 511<td> 512 <p> 513 <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a> 514 </p> 515 </td> 516<td> 517 <p> 518 1.6 (0.0151s) 519 </p> 520 </td> 521<td> 522 <p> 523 9.3 (27947 total) 524 </p> 525 </td> 526</tr> 527</tbody> 528</table></div> 529</div> 530<br class="table-break"><p> 531 As you can see, the execution time increases a lot more slowly than the number 532 of memory allocations. There are a number of reasons for this: 533 </p> 534<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 535<li class="listitem"> 536 The cost of extended-precision multiplication and division is so great, 537 that the times taken for these tend to swamp everything else. 538 </li> 539<li class="listitem"> 540 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 541 <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> 542 (typically <code class="computeroutput"><span class="keyword">operator</span> <span class="special">*=</span></code> 543 has to create a temporary workspace to carry out the multiplication, where 544 as <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> 545 can use the target variable as workspace). Since the expression templates 546 carry out their magic by converting out-of-place operators to in-place 547 ones, we necessarily take this hit. Even so the transformation is more 548 efficient than creating the extra temporary variable, just not by as much 549 as one would hope. 550 </li> 551</ul></div> 552<p> 553 Finally, note that <code class="computeroutput"><span class="identifier">number</span></code> takes 554 a second template argument, which, when set to <code class="computeroutput"><span class="identifier">et_off</span></code> 555 disables all the expression template machinery. The result is much faster to 556 compile, but slower at runtime. 557 </p> 558<p> 559 We'll conclude this section by providing some more performance comparisons 560 between these three libraries, again, all are using <a href="http://www.mpfr.org" target="_top">MPFR</a> 561 to carry out the underlying arithmetic, and all are operating at the same precision 562 (50 decimal digits): 563 </p> 564<div class="table"> 565<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> 566<div class="table-contents"><table class="table" summary="Evaluation of Boost.Math's Bessel function test data"> 567<colgroup> 568<col> 569<col> 570<col> 571</colgroup> 572<thead><tr> 573<th> 574 <p> 575 Library 576 </p> 577 </th> 578<th> 579 <p> 580 Relative Time 581 </p> 582 </th> 583<th> 584 <p> 585 Relative Number of Memory Allocations 586 </p> 587 </th> 588</tr></thead> 589<tbody> 590<tr> 591<td> 592 <p> 593 mpfr_float_50 594 </p> 595 </td> 596<td> 597 <p> 598 1.0 (5.78s) 599 </p> 600 </td> 601<td> 602 <p> 603 1.0 (1611963) 604 </p> 605 </td> 606</tr> 607<tr> 608<td> 609 <p> 610 number<mpfr_float_backend<50>, et_off><br> (but with 611 rvalue reference support) 612 </p> 613 </td> 614<td> 615 <p> 616 1.1 (6.29s) 617 </p> 618 </td> 619<td> 620 <p> 621 2.64 (4260868) 622 </p> 623 </td> 624</tr> 625<tr> 626<td> 627 <p> 628 <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a> 629 </p> 630 </td> 631<td> 632 <p> 633 1.1 (6.28s) 634 </p> 635 </td> 636<td> 637 <p> 638 2.45 (3948316) 639 </p> 640 </td> 641</tr> 642<tr> 643<td> 644 <p> 645 <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a> 646 </p> 647 </td> 648<td> 649 <p> 650 1.65 (9.54s) 651 </p> 652 </td> 653<td> 654 <p> 655 8.21 (13226029) 656 </p> 657 </td> 658</tr> 659</tbody> 660</table></div> 661</div> 662<br class="table-break"><div class="table"> 663<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> 664<div class="table-contents"><table class="table" summary="Evaluation of Boost.Math's Non-Central T distribution test data"> 665<colgroup> 666<col> 667<col> 668<col> 669</colgroup> 670<thead><tr> 671<th> 672 <p> 673 Library 674 </p> 675 </th> 676<th> 677 <p> 678 Relative Time 679 </p> 680 </th> 681<th> 682 <p> 683 Relative Number of Memory Allocations 684 </p> 685 </th> 686</tr></thead> 687<tbody> 688<tr> 689<td> 690 <p> 691 number 692 </p> 693 </td> 694<td> 695 <p> 696 1.0 (263s) 697 </p> 698 </td> 699<td> 700 <p> 701 1.0 (127710873) 702 </p> 703 </td> 704</tr> 705<tr> 706<td> 707 <p> 708 number<mpfr_float_backend<50>, et_off><br> (but with 709 rvalue reference support) 710 </p> 711 </td> 712<td> 713 <p> 714 1.0 (260s) 715 </p> 716 </td> 717<td> 718 <p> 719 1.2 (156797871) 720 </p> 721 </td> 722</tr> 723<tr> 724<td> 725 <p> 726 <a href="http://math.berkeley.edu/~wilken/code/gmpfrxx/" target="_top">mpfr_class</a> 727 </p> 728 </td> 729<td> 730 <p> 731 1.1 (287s) 732 </p> 733 </td> 734<td> 735 <p> 736 2.1 (268336640) 737 </p> 738 </td> 739</tr> 740<tr> 741<td> 742 <p> 743 <a href="http://www.holoborodko.com/pavel/mpfr/" target="_top">mpreal</a> 744 </p> 745 </td> 746<td> 747 <p> 748 1.5 (389s) 749 </p> 750 </td> 751<td> 752 <p> 753 3.6 (466960653) 754 </p> 755 </td> 756</tr> 757</tbody> 758</table></div> 759</div> 760<br class="table-break"><p> 761 The above results were generated on Win32 compiling with Visual C++ 2010, all 762 optimizations on (/Ox), with MPFR 3.0 and MPIR 2.3.0. 763 </p> 764<div class="footnotes"> 765<br><hr style="width:100; text-align:left;margin-left: 0"> 766<div id="ftn.boost_multiprecision.intro.f0" class="footnote"><p><a href="#boost_multiprecision.intro.f0" class="para"><sup class="para">[1] </sup></a> 767 The actual number generated will depend on the compiler, how well it optimizes 768 the code, and whether it supports rvalue references. The number of 11 temporaries 769 was generated with Visual C++ 2010. 770 </p></div> 771</div> 772</div> 773<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 774<td align="left"></td> 775<td align="right"><div class="copyright-footer">Copyright © 2002-2020 John 776 Maddock and Christopher Kormanyos<p> 777 Distributed under the Boost Software License, Version 1.0. (See accompanying 778 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>) 779 </p> 780</div></td> 781</tr></table> 782<hr> 783<div class="spirit-nav"> 784<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> 785</div> 786</body> 787</html> 788