]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | Copyright 2011, 2013 John Maddock. | |
3 | Copyright 2013 Paul A. Bristow. | |
4 | Copyright 2013 Christopher Kormanyos. | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. | |
7 | (See accompanying file LICENSE_1_0.txt or copy at | |
8 | http://www.boost.org/LICENSE_1_0.txt). | |
9 | ] | |
10 | ||
11 | [library Boost.Multiprecision | |
12 | [quickbook 1.7] | |
13 | [copyright 2002-2013 John Maddock and Christopher Kormanyos] | |
14 | [purpose Multiprecision Number library] | |
15 | [license | |
16 | Distributed under the Boost Software License, Version 1.0. | |
17 | (See accompanying file LICENSE_1_0.txt or copy at | |
18 | [@http://www.boost.org/LICENSE_1_0.txt]) | |
19 | ] | |
20 | [authors [Maddock, John], [Kormanyos, Christopher]] | |
21 | [/last-revision $Date: 2011-07-08 18:51:46 +0100 (Fri, 08 Jul 2011) $] | |
22 | ] | |
23 | ||
24 | [import html4_symbols.qbk] | |
25 | ||
26 | [import ../example/gmp_snips.cpp] | |
27 | [import ../example/mpfr_snips.cpp] | |
28 | [import ../example/mpfi_snips.cpp] | |
29 | [import ../example/float128_snips.cpp] | |
30 | [import ../example/cpp_dec_float_snips.cpp] | |
31 | [import ../example/cpp_bin_float_snips.cpp] | |
32 | [import ../example/cpp_int_import_export.cpp] | |
33 | [import ../example/cpp_bin_float_import_export.cpp] | |
34 | [import ../example/tommath_snips.cpp] | |
35 | [import ../example/cpp_int_snips.cpp] | |
36 | [import ../example/random_snips.cpp] | |
37 | [import ../example/safe_prime.cpp] | |
38 | [import ../example/mixed_integer_arithmetic.cpp] | |
39 | [import ../example/logged_adaptor.cpp] | |
40 | [import ../example/numeric_limits_snips.cpp] | |
41 | [import ../example/hashing_examples.cpp] | |
42 | ||
43 | [template mpfr[] [@http://www.mpfr.org MPFR]] | |
44 | [template mpfi[] [@http://perso.ens-lyon.fr/nathalie.revol/software.html MPFI]] | |
45 | [template gmp[] [@http://gmplib.org GMP]] | |
46 | [template mpf_class[] [@http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats mpf_class]] | |
47 | [template mpfr_class[] [@http://math.berkeley.edu/~wilken/code/gmpfrxx/ mpfr_class]] | |
48 | [template mpreal[] [@http://www.holoborodko.com/pavel/mpfr/ mpreal]] | |
49 | [template mpir[] [@http://mpir.org/ MPIR]] | |
50 | [template tommath[] [@http://libtom.org/?page=features&newsitems=5&whatfile=ltm libtommath]] | |
51 | [template quadmath[] [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath]] | |
52 | ||
53 | [template super[x]'''<superscript>'''[x]'''</superscript>'''] | |
54 | [template sub[x]'''<subscript>'''[x]'''</subscript>'''] | |
55 | ||
56 | [template equation[name] '''<inlinemediaobject> | |
57 | <imageobject role="html"> | |
58 | <imagedata fileref="../'''[name]'''.png"></imagedata> | |
59 | </imageobject> | |
60 | <imageobject role="print"> | |
61 | <imagedata fileref="../'''[name]'''.svg"></imagedata> | |
62 | </imageobject> | |
63 | </inlinemediaobject>'''] | |
64 | ||
65 | [def __cpp_int [link boost_multiprecision.tut.ints.cpp_int cpp_int]] | |
66 | [def __gmp_int [link boost_multiprecision.tut.ints.gmp_int gmp_int]] | |
67 | [def __tom_int [link boost_multiprecision.tut.ints.tom_int tom_int]] | |
68 | [def __gmp_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]] | |
69 | [def __mpf_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]] | |
70 | [def __mpfr_float_backend [link boost_multiprecision.tut.floats.mpfr_float mpfr_float]] | |
71 | [def __cpp_bin_float [link boost_multiprecision.tut.floats.cpp_bin_float cpp_bin_float]] | |
72 | [def __cpp_dec_float [link boost_multiprecision.tut.floats.cpp_dec_float cpp_dec_float]] | |
73 | [def __gmp_rational [link boost_multiprecision.tut.rational.gmp_rational gmp_rational]] | |
74 | [def __cpp_rational [link boost_multiprecision.tut.rational.cpp_rational cpp_rational]] | |
75 | [def __tommath_rational [link boost_multiprecision.tut.rational.tommath_rational tommath_rational]] | |
76 | [def __number [link boost_multiprecision.ref.number number]] | |
77 | [def __float128 [link boost_multiprecision.tut.floats.float128 float128]] | |
78 | [def __debug_adaptor [link boost_multiprecision.tut.misc.debug_adaptor debug_adaptor]] | |
79 | [def __logged_adaptor [link boost_multiprecision.tut.misc.logged_adaptor logged_adaptor]] | |
80 | [def __rational_adaptor [link boost_multiprecision.tut.rational.rational_adaptor rational_adaptor]] | |
81 | ||
82 | [section:intro Introduction] | |
83 | ||
84 | The Multiprecision Library provides [link boost_multiprecision.tut.ints integer], | |
85 | [link boost_multiprecision.tut.rational rational] | |
86 | and [link boost_multiprecision.tut.floats floating-point] types in C++ that have more | |
87 | range and precision than C++'s ordinary built-in types. | |
88 | The big number types in Multiprecision can be used with a wide | |
89 | selection of basic mathematical operations, elementary transcendental | |
90 | functions as well as the functions in Boost.Math. | |
91 | The Multiprecision types can also interoperate with the | |
92 | built-in types in C++ using clearly defined conversion rules. | |
93 | This allows Boost.Multiprecision to be used for all | |
94 | kinds of mathematical calculations involving integer, | |
95 | rational and floating-point types requiring extended | |
96 | range and precision. | |
97 | ||
98 | Multiprecision consists of a generic interface to the | |
99 | mathematics of large numbers as well as a selection of | |
100 | big number back ends, with support for integer, rational and | |
101 | floating-point types. Boost.Multiprecision provides a selection | |
102 | of back ends provided off-the-rack in including | |
103 | interfaces to GMP, MPFR, MPIR, TomMath as well as | |
104 | its own collection of Boost-licensed, header-only back ends for | |
105 | integers, rationals and floats. In addition, user-defined back ends | |
106 | can be created and used with the interface of Multiprecision, | |
107 | provided the class implementation adheres to the necessary | |
108 | [link boost_multiprecision.ref.backendconc concepts]. | |
109 | ||
110 | Depending upon the number type, precision may be arbitrarily large | |
111 | (limited only by available memory), fixed at compile time | |
112 | (for example 50 or 100 decimal digits), or a variable controlled at run-time | |
113 | by member functions. The types are expression-template-enabled for | |
114 | better performance than naive user-defined types. | |
115 | ||
116 | The Multiprecision library comes in two distinct parts: | |
117 | ||
118 | * An expression-template-enabled front-end `number` | |
119 | that handles all the operator overloading, expression evaluation optimization, and code reduction. | |
120 | * A selection of back-ends that implement the actual arithmetic operations, and need conform only to the | |
121 | reduced interface requirements of the front-end. | |
122 | ||
123 | Separation of front-end and back-end allows use of highly refined, but restricted license libraries | |
124 | where possible, but provides Boost license alternatives for users who must have a portable | |
125 | unconstrained license. Which is to say some back-ends rely on 3rd party libraries, but a header-only Boost license version is always | |
126 | available (if somewhat slower). | |
127 | ||
128 | Should you just wish to cut to the chase and use a fully Boost-licensed number type, then skip to | |
129 | __cpp_int for multiprecision integers, __cpp_dec_float for multiprecision floating-point types | |
130 | and __cpp_rational for rational types. | |
131 | ||
132 | The library is often used via one of the predefined typedefs: for example if you wanted an | |
133 | [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] | |
134 | integer type using [gmp] as the underlying implementation then you could use: | |
135 | ||
136 | #include <boost/multiprecision/gmp.hpp> // Defines the wrappers around the GMP library's types | |
137 | ||
138 | boost::multiprecision::mpz_int myint; // Arbitrary precision integer type. | |
139 | ||
140 | Alternatively, you can compose your own multiprecision type, by combining `number` with one of the | |
141 | predefined back-end types. For example, suppose you wanted a 300 decimal digit floating-point type | |
142 | based on the [mpfr] library. In this case, there's no predefined typedef with that level of precision, | |
143 | so instead we compose our own: | |
144 | ||
145 | #include <boost/multiprecision/mpfr.hpp> // Defines the Backend type that wraps MPFR | |
146 | ||
147 | namespace mp = boost::multiprecision; // Reduce the typing a bit later... | |
148 | ||
149 | typedef mp::number<mp::mpfr_float_backend<300> > my_float; | |
150 | ||
151 | my_float a, b, c; // These variables have 300 decimal digits precision | |
152 | ||
153 | We can repeat the above example, but with the expression templates disabled (for faster compile times, but slower runtimes) | |
154 | by passing a second template argument to `number`: | |
155 | ||
156 | #include <boost/multiprecision/mpfr.hpp> // Defines the Backend type that wraps MPFR | |
157 | ||
158 | namespace mp = boost::multiprecision; // Reduce the typing a bit later... | |
159 | ||
160 | typedef mp::number<mp::mpfr_float_backend<300>, et_off> my_float; | |
161 | ||
162 | my_float a, b, c; // These variables have 300 decimal digits precision | |
163 | ||
164 | We can also mix arithmetic operations between different types, provided there is an unambiguous implicit conversion from one | |
165 | type to the other: | |
166 | ||
167 | #include <boost/multiprecision/cpp_int.hpp> | |
168 | ||
169 | namespace mp = boost::multiprecision; // Reduce the typing a bit later... | |
170 | ||
171 | mp::int128_t a(3), b(4); | |
172 | mp::int512_t c(50), d; | |
173 | ||
174 | d = c * a; // OK, result of mixed arithmetic is an int512_t | |
175 | ||
176 | Conversions are also allowed: | |
177 | ||
178 | d = a; // OK, widening conversion. | |
179 | d = a * b; // OK, can convert from an expression template too. | |
180 | ||
181 | However conversions that are inherently lossy are either declared explicit or else forbidden altogether: | |
182 | ||
183 | d = 3.14; // Error implicit conversion from float not allowed. | |
184 | d = static_cast<mp::int512_t>(3.14); // OK explicit construction is allowed | |
185 | ||
186 | Mixed arithmetic will fail if the conversion is either ambiguous or explicit: | |
187 | ||
188 | number<cpp_int_backend<>, et_off> a(2); | |
189 | number<cpp_int_backend<>, et_on> b(3); | |
190 | ||
191 | b = a * b; // Error, implicit conversion could go either way. | |
192 | b = a * 3.14; // Error, no operator overload if the conversion would be explicit. | |
193 | ||
194 | [h4 Move Semantics] | |
195 | ||
196 | On compilers that support rvalue-references, class `number` is move-enabled if the underlying backend is. | |
197 | ||
198 | In addition the non-expression template operator overloads (see below) are move aware and have overloads | |
199 | that look something like: | |
200 | ||
201 | template <class B> | |
202 | number<B, et_off> operator + (number<B, et_off>&& a, const number<B, et_off>& b) | |
203 | { | |
204 | return std::move(a += b); | |
205 | } | |
206 | ||
207 | These operator overloads ensure that many expressions can be evaluated without actually generating any temporaries. | |
208 | However, there are still many simple expressions such as: | |
209 | ||
210 | a = b * c; | |
211 | ||
212 | Which don't noticeably benefit from move support. Therefore, optimal performance comes from having both | |
213 | move-support, and expression templates enabled. | |
214 | ||
215 | Note that while "moved-from" objects are left in a sane state, they have an unspecified value, and the only permitted | |
216 | operations on them are destruction or the assignment of a new value. Any other operation should be considered | |
217 | a programming error and all of our backends will trigger an assertion if any other operation is attempted. This behavior | |
218 | allows for optimal performance on move-construction (i.e. no allocation required, we just take ownership of the existing | |
219 | object's internal state), while maintaining usability in the standard library containers. | |
220 | ||
221 | [h4 Expression Templates] | |
222 | ||
223 | Class `number` is expression-template-enabled: that means that rather than having a multiplication | |
224 | operator that looks like this: | |
225 | ||
226 | template <class Backend> | |
227 | number<Backend> operator * (const number<Backend>& a, const number<Backend>& b) | |
228 | { | |
229 | number<Backend> result(a); | |
230 | result *= b; | |
231 | return result; | |
232 | } | |
233 | ||
234 | Instead the operator looks more like this: | |
235 | ||
236 | template <class Backend> | |
237 | ``['unmentionable-type]`` operator * (const number<Backend>& a, const number<Backend>& b); | |
238 | ||
239 | Where the "unmentionable" return type is an implementation detail that, rather than containing the result | |
240 | of the multiplication, contains instructions on how to compute the result. In effect it's just a pair | |
241 | of references to the arguments of the function, plus some compile-time information that stores what the operation | |
242 | is. | |
243 | ||
244 | The great advantage of this method is the ['elimination of temporaries]: for example the "naive" implementation | |
245 | of `operator*` above, requires one temporary for computing the result, and at least another one to return it. It's true | |
246 | that sometimes this overhead can be reduced by using move-semantics, but it can't be eliminated completely. For example, | |
247 | lets suppose we're evaluating a polynomial via Horner's method, something like this: | |
248 | ||
249 | T a[7] = { /* some values */ }; | |
250 | //.... | |
251 | y = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]; | |
252 | ||
253 | If type `T` is a `number`, then this expression is evaluated ['without creating a single temporary value]. In contrast, | |
254 | if we were using the [mpfr_class] C++ wrapper for [mpfr] - then this expression would result in no less than 11 | |
255 | temporaries (this is true even though [mpfr_class] does use expression templates to reduce the number of temporaries somewhat). Had | |
256 | we used an even simpler wrapper around [mpfr] like [mpreal] things would have been even worse and no less that 24 temporaries | |
257 | are created for this simple expression (note - we actually measure the number of memory allocations performed rather than | |
258 | the number of temporaries directly, note also that the [mpf_class] wrapper that will be supplied with GMP-5.1 reduces the number of | |
259 | temporaries to pretty much zero). Note that if we compile with expression templates disabled and rvalue-reference support | |
260 | on, then actually still have no wasted memory allocations as even though temporaries are created, their contents are moved | |
261 | rather than copied. | |
262 | [footnote The actual number generated will depend on the compiler, how well it optimises the code, and whether it supports | |
263 | rvalue references. The number of 11 temporaries was generated with Visual C++ 10] | |
264 | ||
265 | [important | |
266 | Expression templates can radically reorder the operations in an expression, for example: | |
267 | ||
268 | a = (b * c) * a; | |
269 | ||
270 | Will get transformed into: | |
271 | ||
272 | a *= c; | |
273 | a *= b; | |
274 | ||
275 | If this is likely to be an issue for a particular application, then they should be disabled. | |
276 | ] | |
277 | ||
278 | This library also extends expression template support to standard library functions like `abs` or `sin` with `number` | |
279 | arguments. This means that an expression such as: | |
280 | ||
281 | y = abs(x); | |
282 | ||
283 | can be evaluated without a single temporary being calculated. Even expressions like: | |
284 | ||
285 | y = sin(x); | |
286 | ||
287 | get this treatment, so that variable 'y' is used as "working storage" within the implementation of `sin`, | |
288 | thus reducing the number of temporaries used by one. Of course, should you write: | |
289 | ||
290 | x = sin(x); | |
291 | ||
292 | Then we clearly can't use `x` as working storage during the calculation, so then a temporary variable | |
293 | is created in this case. | |
294 | ||
295 | Given the comments above, you might be forgiven for thinking that expression-templates are some kind of universal-panacea: | |
296 | sadly though, all tricks like this have their downsides. For one thing, expression template libraries | |
297 | like this one, tend to be slower to compile than their simpler cousins, they're also harder to debug | |
298 | (should you actually want to step through our code!), and rely on compiler optimizations being turned | |
299 | on to give really good performance. Also, since the return type from expressions involving `number`s | |
300 | is an "unmentionable implementation detail", you have to be careful to cast the result of an expression | |
301 | to the actual number type when passing an expression to a template function. For example, given: | |
302 | ||
303 | template <class T> | |
304 | void my_proc(const T&); | |
305 | ||
306 | Then calling: | |
307 | ||
308 | my_proc(a+b); | |
309 | ||
310 | Will very likely result in obscure error messages inside the body of `my_proc` - since we've passed it | |
311 | an expression template type, and not a number type. Instead we probably need: | |
312 | ||
313 | my_proc(my_number_type(a+b)); | |
314 | ||
315 | Having said that, these situations don't occur that often - or indeed not at all for non-template functions. | |
316 | In addition, all the functions in the Boost.Math library will automatically convert expression-template arguments | |
317 | to the underlying number type without you having to do anything, so: | |
318 | ||
319 | mpfr_float_100 a(20), delta(0.125); | |
320 | boost::math::gamma_p(a, a + delta); | |
321 | ||
322 | Will work just fine, with the `a + delta` expression template argument getting converted to an `mpfr_float_100` | |
323 | internally by the Boost.Math library. | |
324 | ||
325 | One other potential pitfall that's only possible in C++11: you should never store an expression template using: | |
326 | ||
327 | auto my_expression = a + b - c; | |
328 | ||
329 | unless you're absolutely sure that the lifetimes of `a`, `b` and `c` will outlive that of `my_expression`. | |
330 | ||
331 | And finally... the performance improvements from an expression template library like this are often not as | |
332 | dramatic as the reduction in number of temporaries would suggest. For example if we compare this library with | |
333 | [mpfr_class] and [mpreal], with all three using the underlying [mpfr] library at 50 decimal digits precision then | |
334 | we see the following typical results for polynomial execution: | |
335 | ||
336 | [table Evaluation of Order 6 Polynomial. | |
337 | [[Library] [Relative Time] [Relative number of memory allocations]] | |
338 | [[number] [1.0 (0.00957s)] [1.0 (2996 total)]] | |
339 | [[[mpfr_class]] [1.1 (0.0102s)] [4.3 (12976 total)]] | |
340 | [[[mpreal]] [1.6 (0.0151s)] [9.3 (27947 total)]] | |
341 | ] | |
342 | ||
343 | As you can see, the execution time increases a lot more slowly than the number of memory allocations. There are | |
344 | a number of reasons for this: | |
345 | ||
346 | * The cost of extended-precision multiplication and division is so great, that the times taken for these tend to | |
347 | swamp everything else. | |
348 | * The cost of an in-place multiplication (using `operator*=`) tends to be more than an out-of-place | |
349 | `operator*` (typically `operator *=` has to create a temporary workspace to carry out the multiplication, where | |
350 | as `operator*` can use the target variable as workspace). Since the expression templates carry out their | |
351 | magic by converting out-of-place operators to in-place ones, we necessarily take this hit. Even so the | |
352 | transformation is more efficient than creating the extra temporary variable, just not by as much as | |
353 | one would hope. | |
354 | ||
355 | Finally, note that `number` takes a second template argument, which, when set to `et_off` disables all | |
356 | the expression template machinery. The result is much faster to compile, but slower at runtime. | |
357 | ||
358 | We'll conclude this section by providing some more performance comparisons between these three libraries, | |
359 | again, all are using [mpfr] to carry out the underlying arithmetic, and all are operating at the same precision | |
360 | (50 decimal digits): | |
361 | ||
362 | [table Evaluation of Boost.Math's Bessel function test data | |
363 | [[Library] [Relative Time] [Relative Number of Memory Allocations]] | |
364 | [[mpfr_float_50] [1.0 (5.78s)] [1.0 (1611963)]] | |
365 | [[number<mpfr_float_backend<50>, et_off>[br](but with rvalue reference support)] | |
366 | [1.1 (6.29s)] [2.64 (4260868)]] | |
367 | [[[mpfr_class]] [1.1 (6.28s)] [2.45 (3948316)]] | |
368 | [[[mpreal]] [1.65 (9.54s)] [8.21 (13226029)]] | |
369 | ] | |
370 | ||
371 | [table Evaluation of Boost.Math's Non-Central T distribution test data | |
372 | [[Library][Relative Time][Relative Number of Memory Allocations]] | |
373 | [[number] [1.0 (263s)][1.0 (127710873)]] | |
374 | [[number<mpfr_float_backend<50>, et_off>[br](but with rvalue reference support)] | |
375 | [1.0 (260s)][1.2 (156797871)]] | |
376 | [[[mpfr_class]] [1.1 (287s)][2.1 (268336640)]] | |
377 | [[[mpreal]] [1.5 (389s)][3.6 (466960653)]] | |
378 | ] | |
379 | ||
380 | The above results were generated on Win32 compiling with Visual C++ 2010, all optimizations on (/Ox), | |
381 | with MPFR 3.0 and MPIR 2.3.0. | |
382 | ||
383 | [endsect] [/section:intro Introduction] | |
384 | ||
385 | [section:tut Tutorial] | |
386 | ||
387 | In order to use this library you need to make two choices: | |
388 | ||
389 | * What kind of number do I want ([link boost_multiprecision.tut.ints integer], | |
390 | [link boost_multiprecision.tut.floats floating-point] or [link boost_multiprecision.tut.rational rational]). | |
391 | * Which back-end do I want to perform the actual arithmetic (Boost-supplied, GMP, MPFR, Tommath etc)? | |
392 | ||
393 | [section:ints Integer Types] | |
394 | ||
395 | The following back-ends provide integer arithmetic: | |
396 | ||
397 | [table | |
398 | [[Backend Type][Header][Radix][Dependencies][Pros][Cons]] | |
399 | [[`cpp_int`][boost/multiprecision/cpp_int.hpp][2][None] | |
400 | [Very versatile, Boost licensed, all C++ integer type which support both [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] and fixed precision integer types.][Slower than [gmp], though typically not as slow as [tommath]]] | |
401 | [[`gmp_int`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] | |
402 | [[`tom_int`][boost/multiprecision/tommath.hpp][2][[tommath]][Public domain back-end with no licence restrictions.][Slower than [gmp].]] | |
403 | ] | |
404 | ||
405 | [section:cpp_int cpp_int] | |
406 | ||
407 | `#include <boost/multiprecision/cpp_int.hpp>` | |
408 | ||
409 | namespace boost{ namespace multiprecision{ | |
410 | ||
411 | typedef unspecified-type limb_type; | |
412 | ||
413 | enum cpp_integer_type { signed_magnitude, unsigned_magnitude }; | |
414 | enum cpp_int_check_type { checked, unchecked }; | |
415 | ||
416 | template <unsigned MinBits = 0, | |
417 | unsigned MaxBits = 0, | |
418 | cpp_integer_type SignType = signed_magnitude, | |
419 | cpp_int_check_type Checked = unchecked, | |
420 | class Allocator = std::allocator<limb_type> > | |
421 | class cpp_int_backend; | |
422 | // | |
423 | // Expression templates default to et_off if there is no allocator: | |
424 | // | |
425 | template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked> | |
426 | struct expression_template_default<cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> > | |
427 | { static const expression_template_option value = et_off; }; | |
428 | ||
429 | typedef number<cpp_int_backend<> > cpp_int; // arbitrary precision integer | |
430 | typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend; | |
431 | typedef number<cpp_rational_backend> cpp_rational; // arbitrary precision rational number | |
432 | ||
433 | // Fixed precision unsigned types: | |
434 | typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t; | |
435 | typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t; | |
436 | typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t; | |
437 | typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t; | |
438 | ||
439 | // Fixed precision signed types: | |
440 | typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t; | |
441 | typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t; | |
442 | typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t; | |
443 | typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t; | |
444 | ||
445 | // Over again, but with checking enabled this time: | |
446 | typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int; | |
447 | typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend; | |
448 | typedef number<cpp_rational_backend> checked_cpp_rational; | |
449 | ||
450 | // Checked fixed precision unsigned types: | |
451 | typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t; | |
452 | typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t; | |
453 | typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t; | |
454 | typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t; | |
455 | ||
456 | // Fixed precision signed types: | |
457 | typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t; | |
458 | typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t; | |
459 | typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t; | |
460 | typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t; | |
461 | ||
462 | }} // namespaces | |
463 | ||
464 | The `cpp_int_backend` type is normally used via one of the convenience typedefs given above. | |
465 | ||
466 | This back-end is the "Swiss Army Knife" of integer types as it can represent both fixed and | |
467 | [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] | |
468 | integer types, and both signed and unsigned types. There are five template arguments: | |
469 | ||
470 | [variablelist | |
471 | [[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory | |
472 | allocation. When zero, this field is determined automatically based on how many bits can be stored | |
473 | in union with the dynamic storage header: setting a larger value may improve performance as larger integer | |
474 | values will be stored internally before memory allocation is required.]] | |
475 | [[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type. | |
476 | When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic | |
477 | memory allocation will ever be performed: in this situation the Allocator parameter should be set to | |
478 | type `void`. Note that this parameter should not be used simply to prevent large memory | |
479 | allocations, not only is that role better performed by the allocator, but fixed precision | |
480 | integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]] | |
481 | [[SignType][Determines whether the resulting type is signed or not. Note that for | |
482 | [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types | |
483 | this parameter must be `signed_magnitude`. For fixed precision | |
484 | types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]] | |
485 | [[Checked][This parameter has two values: `checked` or `unchecked`. See below.]] | |
486 | [[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]] | |
487 | ] | |
488 | ||
489 | When the template parameter Checked is set to `checked` then the result is a ['checked-integer], checked | |
490 | and unchecked integers have the following properties: | |
491 | ||
492 | [table | |
493 | [[Condition][Checked-Integer][Unchecked-Integer]] | |
494 | [[Numeric overflow in fixed precision arithmetic][Throws a `std::overflow_error`.][Performs arithmetic modulo 2[super MaxBits]]] | |
495 | [[Constructing an integer from a value that can not be represented in the target type][Throws a `std::range_error`.] | |
496 | [Converts the value modulo 2[super MaxBits], signed to unsigned conversions extract the last MaxBits bits of the | |
497 | 2's complement representation of the input value.]] | |
498 | [[Unsigned subtraction yielding a negative value.][Throws a `std::range_error`.][Yields the value that would | |
499 | result from treating the unsigned type as a 2's complement signed type.]] | |
500 | [[Attempting a bitwise operation on a negative value.][Throws a `std::range_error`][Yields the value, but not the bit pattern, | |
501 | that would result from performing the operation on a 2's complement integer type.]] | |
502 | ] | |
503 | ||
504 | Things you should know when using this type: | |
505 | ||
506 | * Default constructed `cpp_int_backend`s have the value zero. | |
507 | * Division by zero results in a `std::overflow_error` being thrown. | |
508 | * Construction from a string that contains invalid non-numeric characters results in a `std::runtime_error` being thrown. | |
509 | * Since the precision of `cpp_int_backend` is necessarily limited when the allocator parameter is void, | |
510 | care should be taken to avoid numeric overflow when using this type | |
511 | unless you actually want modulo-arithmetic behavior. | |
512 | * The type uses a sign-magnitude representation internally, so type `int128_t` has 128-bits of precision plus an extra sign bit. | |
513 | In this respect the behaviour of these types differs from built-in 2's complement types. In might be tempting to use a | |
514 | 127-bit type instead, and indeed this does work, but behaviour is still slightly different from a 2's complement built-in type | |
515 | as the min and max values are identical (apart from the sign), where as they differ by one for a true 2's complement type. | |
516 | That said it should be noted that there's no requirement for built-in types to be 2's complement either - it's simply that this | |
517 | is the most common format by far. | |
518 | * Attempting to print negative values as either an Octal or Hexadecimal string results in a `std::runtime_error` being thrown, | |
519 | this is a direct consequence of the sign-magnitude representation. | |
520 | * The fixed precision types `[checked_][u]intXXX_t` have expression template support turned off - it seems to make little | |
521 | difference to the performance of these types either way - so we may as well have the faster compile times by turning | |
522 | the feature off. | |
523 | * Unsigned types support subtraction - the result is "as if" a 2's complement operation had been performed as long as they are not | |
524 | ['checked-integers] (see above). | |
525 | In other words they behave pretty much as a built in integer type would in this situation. So for example if we were using | |
526 | `uint128_t` then `uint128_t(1)-4` would result in the value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD` | |
527 | of type `uint128_t`. However, had this operation been performed on `checked_uint128_t` then a `std::range_error` would have | |
528 | been thrown. | |
529 | * Unary negation of unsigned types results in a compiler error (static assertion). | |
530 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
531 | * When used at fixed precision, the size of this type is always one machine word larger than you would expect for an N-bit integer: | |
532 | the extra word stores both the sign, and how many machine words in the integer are actually in use. | |
533 | The latter is an optimisation for larger fixed precision integers, so that a 1024-bit integer has almost the same performance | |
534 | characteristics as a 128-bit integer, rather than being 4 times slower for addition and 16 times slower for multiplication | |
535 | (assuming the values involved would always fit in 128 bits). | |
536 | Typically this means you can use | |
537 | an integer type wide enough for the "worst case scenario" with only minor performance degradation even if most of the time | |
538 | the arithmetic could in fact be done with a narrower type. | |
539 | * When used at fixed precision and MaxBits is smaller than the number of bits in the largest native integer type, then | |
540 | internally `cpp_int_backend` switches to a "trivial" implementation where it is just a thin wrapper around a single | |
541 | integer. Note that it will still be slightly slower than a bare native integer, as it emulates a | |
542 | signed-magnitude representation rather than simply using the platforms native sign representation: this ensures | |
543 | there is no step change in behavior as a cpp_int grows in size. | |
544 | * Fixed precision `cpp_int`'s have some support for `constexpr` values and user-defined literals, see | |
545 | [link boost_multiprecision.tut.lits here] for the full description. For example `0xfffff_cppi1024` | |
546 | specifies a 1024-bit integer with the value 0xffff. This can be used to generate compile time constants that are | |
547 | too large to fit into any built in number type. | |
548 | * You can import/export the raw bits of a __cpp_int to and from external storage via the `import_bits` and `export_bits` | |
549 | functions. More information is in the [link boost_multiprecision.tut.import_export section on import/export]. | |
550 | ||
551 | [h5 Example:] | |
552 | ||
553 | [cpp_int_eg] | |
554 | ||
555 | [endsect] [/section:cpp_int cpp_int] | |
556 | ||
557 | [section:gmp_int gmp_int] | |
558 | ||
559 | `#include <boost/multiprecision/gmp.hpp>` | |
560 | ||
561 | namespace boost{ namespace multiprecision{ | |
562 | ||
563 | class gmp_int; | |
564 | ||
565 | typedef number<gmp_int > mpz_int; | |
566 | ||
567 | }} // namespaces | |
568 | ||
569 | The `gmp_int` back-end is used via the typedef `boost::multiprecision::mpz_int`. It acts as a thin wrapper around the [gmp] `mpz_t` | |
570 | to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision. | |
571 | ||
572 | As well as the usual conversions from arithmetic and string types, type `mpz_int` is copy constructible and assignable from: | |
573 | ||
574 | * The [gmp] native types: `mpf_t`, `mpz_t`, `mpq_t`. | |
575 | * Instances of `number<T>` that are wrappers around those types: `number<gmp_float<N> >`, `number<gmp_rational>`. | |
576 | ||
577 | It's also possible to access the underlying `mpz_t` via the `data()` member function of `gmp_int`. | |
578 | ||
579 | Things you should know when using this type: | |
580 | ||
581 | * No changes are made to the GMP library's global settings - so you can safely mix this type with | |
582 | existing code that uses [gmp]. | |
583 | * Default constructed `gmp_int`s have the value zero (this is GMP's default behavior). | |
584 | * Formatted IO for this type does not support octal or hexadecimal notation for negative values, | |
585 | as a result performing formatted output on this type when the argument is negative and either of the flags | |
586 | `std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown. | |
587 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
588 | as a valid integer. | |
589 | * Division by zero results in a `std::overflow_error` being thrown. | |
590 | * Although this type is a wrapper around [gmp] it will work equally well with [mpir]. Indeed use of [mpir] | |
591 | is recommended on Win32. | |
592 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
593 | ||
594 | [h5 Example:] | |
595 | ||
596 | [mpz_eg] | |
597 | ||
598 | [endsect] | |
599 | ||
600 | [section:tom_int tom_int] | |
601 | ||
602 | `#include <boost/multiprecision/tommath.hpp>` | |
603 | ||
604 | namespace boost{ namespace multiprecision{ | |
605 | ||
606 | class tommath_int; | |
607 | ||
608 | typedef number<tommath_int > tom_int; | |
609 | ||
610 | }} // namespaces | |
611 | ||
612 | The `tommath_int` back-end is used via the typedef `boost::multiprecision::tom_int`. It acts as a thin wrapper around the [tommath] `tom_int` | |
613 | to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision. | |
614 | ||
615 | Things you should know when using this type: | |
616 | ||
617 | * Default constructed objects have the value zero (this is [tommath]'s default behavior). | |
618 | * Although `tom_int` is mostly a drop in replacement for the builtin integer types, it should be noted that it is a | |
619 | rather strange beast as it's a signed type that is not a 2's complement type. As a result the bitwise operations | |
620 | `| & ^` will throw a `std::runtime_error` exception if either of the arguments is negative. Similarly the complement | |
621 | operator`~` is deliberately not implemented for this type. | |
622 | * Formatted IO for this type does not support octal or hexadecimal notation for negative values, | |
623 | as a result performing formatted output on this type when the argument is negative and either of the flags | |
624 | `std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown. | |
625 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
626 | as a valid integer. | |
627 | * Division by zero results in a `std::overflow_error` being thrown. | |
628 | ||
629 | [h5 Example:] | |
630 | ||
631 | [tommath_eg] | |
632 | ||
633 | [endsect] [/section:tom_int tom_int] | |
634 | ||
635 | [section:egs Examples] | |
636 | ||
637 | [import ../example/integer_examples.cpp] | |
638 | ||
639 | [section:factorials Factorials] | |
640 | [FAC1] | |
641 | [endsect] [/section:factorials Factorials] | |
642 | ||
643 | ||
644 | [section:bitops Bit Operations] | |
645 | [BITOPS] | |
646 | [endsect] [/section:bitops Bit Operations] | |
647 | ||
648 | ||
649 | [endsect] | |
650 | ||
651 | [endsect] | |
652 | ||
653 | [section:floats floating-point Numbers] | |
654 | ||
655 | The following back-ends provide floating-point arithmetic: | |
656 | ||
657 | [table | |
658 | [[Backend Type][Header][Radix][Dependencies][Pros][Cons]] | |
659 | [[`cpp_bin_float<N>`][boost/multiprecision/cpp_bin_float.hpp][2][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]] | |
660 | [[`cpp_dec_float<N>`][boost/multiprecision/cpp_dec_float.hpp][10][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]] | |
661 | [[`mpf_float<N>`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] | |
662 | [[`mpfr_float<N>`][boost/multiprecision/mpfr.hpp][2][[gmp] and [mpfr]][Very fast and efficient back-end, with its own standard library implementation.][Dependency on GNU licensed [gmp] and [mpfr] libraries.]] | |
663 | [[`float128`][boost/multiprecision/float128.hpp][2][Either [quadmath] or the Intel C++ Math library.][Very fast and efficient back-end for 128-bit floating-point values (113-bit mantissa, equivalent to FORTRAN's QUAD real)][Depends on the compiler being either recent GCC or Intel C++ versions.]] | |
664 | ] | |
665 | ||
666 | [section:cpp_bin_float cpp_bin_float] | |
667 | ||
668 | `#include <boost/multiprecision/cpp_bin_float.hpp>` | |
669 | ||
670 | namespace boost{ namespace multiprecision{ | |
671 | ||
672 | enum digit_base_type | |
673 | { | |
674 | digit_base_2 = 2, | |
675 | digit_base_10 = 10 | |
676 | }; | |
677 | ||
678 | template <unsigned Digits, digit_base_type base = digit_base_10, class Allocator = void, class Exponent = int, ExponentMin = 0, ExponentMax = 0> | |
679 | class cpp_bin_float; | |
680 | ||
681 | typedef number<cpp_bin_float<50> > cpp_bin_float_50; | |
682 | typedef number<cpp_bin_float<100> > cpp_bin_float_100; | |
683 | ||
684 | typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single; | |
685 | typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double; | |
686 | typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended; | |
687 | typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad; | |
688 | ||
689 | }} // namespaces | |
690 | ||
691 | The `cpp_bin_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free) | |
692 | floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with | |
693 | much greater precision. | |
694 | ||
695 | Type `cpp_bin_float` can be used at fixed precision by specifying a non-zero `Digits` template parameter. | |
696 | The typedefs `cpp_bin_float_50` and `cpp_bin_float_100` provide arithmetic types at 50 and 100 decimal digits precision | |
697 | respectively. | |
698 | ||
699 | Optionally, you can specify whether the precision is specified in decimal digits or binary bits - for example | |
700 | to declare a `cpp_bin_float` with exactly the same precision as `double` one would use | |
701 | `number<cpp_bin_float<53, digit_base_2> >`. The typedefs `cpp_bin_float_single`, `cpp_bin_float_double`, | |
702 | `cpp_bin_float_quad` and `cpp_bin_float_double_extended` provide | |
703 | software analogues of the IEEE single, double and quad float data types, plus the Intel-extended-double type respectively. | |
704 | Note that while these types are functionally equivalent to the native IEEE types, but they do not have the same size | |
705 | or bit-layout as true IEEE compatible types. | |
706 | ||
707 | Normally `cpp_bin_float` allocates no memory: all of the space required for its digits are allocated | |
708 | directly within the class. As a result care should be taken not to use the class with too high a digit count | |
709 | as stack space requirements can grow out of control. If that represents a problem then providing an allocator | |
710 | as a template parameter causes `cpp_bin_float` to dynamically allocate the memory it needs: this | |
711 | significantly reduces the size of `cpp_bin_float` and increases the viable upper limit on the number of digits | |
712 | at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive | |
713 | as the digit count grows: the current implementation really isn't optimized or designed for large digit counts. | |
714 | Note that since the actual type of the objects allocated | |
715 | is completely opaque, the suggestion would be to use an allocator with `void` `value_type`, for example: | |
716 | `number<cpp_bin_float<1000, digit_base_10, std::allocator<void> > >`. | |
717 | ||
718 | The final template parameters determine the type and range of the exponent: parameter `Exponent` can be | |
719 | any signed integer type, but note that `MinExponent` and `MaxExponent` can not go right up to the limits | |
720 | of the `Exponent` type as there has to be a little extra headroom for internal calculations. You will | |
721 | get a compile time error if this is the case. In addition if MinExponent or MaxExponent are zero, then | |
722 | the library will choose suitable values that are as large as possible given the constraints of the type | |
723 | and need for extra headroom for internal calculations. | |
724 | ||
725 | There is full standard library and `numeric_limits` support available for this type. | |
726 | ||
727 | Things you should know when using this type: | |
728 | ||
729 | * Default constructed `cpp_bin_float`s have a value of zero. | |
730 | * The radix of this type is 2, even when the precision is specified as decimal digits. | |
731 | * The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow, | |
732 | and a NaN is generated for any mathematically undefined operation. | |
733 | * There is a `std::numeric_limits` specialisation for this type. | |
734 | * Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type - | |
735 | for example you can convert from `number<cpp_bin_float<50> >` to `number<cpp_bin_float<SomeOtherValue> >`. | |
736 | Narrowing conversions round to nearest and are `explicit`. | |
737 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
738 | as a valid floating-point number. | |
739 | * All arithmetic operations are correctly rounded to nearest. String conversions and the `sqrt` function | |
740 | are also correctly rounded, but transcendental functions (sin, cos, pow, exp etc) are not. | |
741 | ||
742 | [h5 cpp_bin_float example:] | |
743 | ||
744 | [cpp_bin_float_eg] | |
745 | ||
746 | [endsect] | |
747 | ||
748 | [section:cpp_dec_float cpp_dec_float] | |
749 | ||
750 | `#include <boost/multiprecision/cpp_dec_float.hpp>` | |
751 | ||
752 | namespace boost{ namespace multiprecision{ | |
753 | ||
754 | template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void> | |
755 | class cpp_dec_float; | |
756 | ||
757 | typedef number<cpp_dec_float<50> > cpp_dec_float_50; | |
758 | typedef number<cpp_dec_float<100> > cpp_dec_float_100; | |
759 | ||
760 | }} // namespaces | |
761 | ||
762 | The `cpp_dec_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free) | |
763 | floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with | |
764 | much greater precision. | |
765 | ||
766 | Type `cpp_dec_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter. | |
767 | The typedefs `cpp_dec_float_50` and `cpp_dec_float_100` provide arithmetic types at 50 and 100 decimal digits precision | |
768 | respectively. Optionally, you can specify an integer type to use for the exponent, this defaults to a 32-bit integer type | |
769 | which is more than large enough for the vast majority of use cases, but larger types such as `long long` can also be specified | |
770 | if you need a truly huge exponent range. In any case the ExponentType must be a built in signed integer type at least 2 bytes | |
771 | and 16-bits wide. | |
772 | ||
773 | Normally `cpp_dec_float` allocates no memory: all of the space required for its digits are allocated | |
774 | directly within the class. As a result care should be taken not to use the class with too high a digit count | |
775 | as stack space requirements can grow out of control. If that represents a problem then providing an allocator | |
776 | as the final template parameter causes `cpp_dec_float` to dynamically allocate the memory it needs: this | |
777 | significantly reduces the size of `cpp_dec_float` and increases the viable upper limit on the number of digits | |
778 | at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive | |
779 | as the digit count grows: the current implementation really isn't optimized or designed for large digit counts. | |
780 | ||
781 | There is full standard library and `numeric_limits` support available for this type. | |
782 | ||
783 | Things you should know when using this type: | |
784 | ||
785 | * Default constructed `cpp_dec_float`s have a value of zero. | |
786 | * The radix of this type is 10. As a result it can behave subtly differently from base-2 types. | |
787 | * The type has a number of internal guard digits over and above those specified in the template argument. | |
788 | Normally these should not be visible to the user. | |
789 | * The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow, | |
790 | and a NaN is generated for any mathematically undefined operation. | |
791 | * There is a `std::numeric_limits` specialisation for this type. | |
792 | * Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type - | |
793 | for example you can convert from `number<cpp_dec_float<50> >` to `number<cpp_dec_float<SomeOtherValue> >`. | |
794 | Narrowing conversions are truncating and `explicit`. | |
795 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
796 | as a valid floating-point number. | |
797 | * The actual precision of a `cpp_dec_float` is always slightly higher than the number of digits specified in | |
798 | the template parameter, actually how much higher is an implementation detail but is always at least 8 decimal | |
799 | digits. | |
800 | * Operations involving `cpp_dec_float` are always truncating. However, note that since their are guard digits | |
801 | in effect, in practice this has no real impact on accuracy for most use cases. | |
802 | ||
803 | [h5 cpp_dec_float example:] | |
804 | ||
805 | [cpp_dec_float_eg] | |
806 | ||
807 | [endsect] | |
808 | ||
809 | [section:gmp_float gmp_float] | |
810 | ||
811 | `#include <boost/multiprecision/gmp.hpp>` | |
812 | ||
813 | namespace boost{ namespace multiprecision{ | |
814 | ||
815 | template <unsigned Digits10> | |
816 | class gmp_float; | |
817 | ||
818 | typedef number<gmp_float<50> > mpf_float_50; | |
819 | typedef number<gmp_float<100> > mpf_float_100; | |
820 | typedef number<gmp_float<500> > mpf_float_500; | |
821 | typedef number<gmp_float<1000> > mpf_float_1000; | |
822 | typedef number<gmp_float<0> > mpf_float; | |
823 | ||
824 | }} // namespaces | |
825 | ||
826 | The `gmp_float` back-end is used in conjunction with `number` : it acts as a thin wrapper around the [gmp] `mpf_t` | |
827 | to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with | |
828 | much greater precision. | |
829 | ||
830 | Type `gmp_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or | |
831 | at variable precision by setting the template argument to zero. The typedefs mpf_float_50, mpf_float_100, | |
832 | mpf_float_500, mpf_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision | |
833 | respectively. The typedef mpf_float provides a variable precision type whose precision can be controlled via the | |
834 | `number`s member functions. | |
835 | ||
836 | [note This type only provides standard library and `numeric_limits` support when the precision is fixed at compile time.] | |
837 | ||
838 | As well as the usual conversions from arithmetic and string types, instances of `number<mpf_float<N> >` are | |
839 | copy constructible and assignable from: | |
840 | ||
841 | * The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`. | |
842 | * The `number` wrappers around those types: `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`. | |
843 | ||
844 | It's also possible to access the underlying `mpf_t` via the `data()` member function of `gmp_float`. | |
845 | ||
846 | Things you should know when using this type: | |
847 | ||
848 | * Default constructed `gmp_float`s have the value zero (this is the [gmp] library's default behavior). | |
849 | * No changes are made to the [gmp] library's global settings, so this type can be safely mixed with | |
850 | existing [gmp] code. | |
851 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
852 | * It is not possible to round-trip objects of this type to and from a string and get back | |
853 | exactly the same value. This appears to be a limitation of [gmp]. | |
854 | * Since the underlying [gmp] types have no notion of infinities or NaN's, care should be taken | |
855 | to avoid numeric overflow or division by zero. That latter will result in a std::overflow_error being thrown, | |
856 | while generating excessively large exponents may result in instability of the underlying [gmp] | |
857 | library (in testing, converting a number with an excessively large or small exponent | |
858 | to a string caused [gmp] to segfault). | |
859 | * This type can equally be used with [mpir] as the underlying implementation - indeed that is | |
860 | the recommended option on Win32. | |
861 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
862 | as a valid floating-point number. | |
863 | * Division by zero results in a `std::overflow_error` being thrown. | |
864 | ||
865 | [h5 [gmp] example:] | |
866 | ||
867 | [mpf_eg] | |
868 | ||
869 | [endsect] | |
870 | ||
871 | [section:mpfr_float mpfr_float] | |
872 | ||
873 | `#include <boost/multiprecision/mpfr.hpp>` | |
874 | ||
875 | namespace boost{ namespace multiprecision{ | |
876 | ||
877 | enum mpfr_allocation_type | |
878 | { | |
879 | allocate_stack, | |
880 | allocate_dynamic | |
881 | }; | |
882 | ||
883 | template <unsigned Digits10, mpfr_allocation_type AllocateType = allocate_dynamic> | |
884 | class mpfr_float_backend; | |
885 | ||
886 | typedef number<mpfr_float_backend<50> > mpfr_float_50; | |
887 | typedef number<mpfr_float_backend<100> > mpfr_float_100; | |
888 | typedef number<mpfr_float_backend<500> > mpfr_float_500; | |
889 | typedef number<mpfr_float_backend<1000> > mpfr_float_1000; | |
890 | typedef number<mpfr_float_backend<0> > mpfr_float; | |
891 | ||
892 | typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50; | |
893 | typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100; | |
894 | ||
895 | }} // namespaces | |
896 | ||
897 | The `mpfr_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfr] `mpfr_t` | |
898 | to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with | |
899 | much greater precision. | |
900 | ||
901 | Type `mpfr_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or | |
902 | at variable precision by setting the template argument to zero. The typedefs mpfr_float_50, mpfr_float_100, | |
903 | mpfr_float_500, mpfr_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision | |
904 | respectively. The typedef mpfr_float provides a variable precision type whose precision can be controlled via the | |
905 | `number`s member functions. | |
906 | ||
907 | In addition the second template parameter lets you choose between dynamic allocation (the default, | |
908 | and uses MPFR's normal allocation routines), | |
909 | or stack allocation (where all the memory required for the underlying data types is stored | |
910 | within `mpfr_float_backend`). The latter option can result in significantly faster code, at the | |
911 | expense of growing the size of `mpfr_float_backend`. It can only be used at fixed precision, and | |
912 | should only be used for lower digit counts. Note that we can not guarantee that using `allocate_stack` | |
913 | won't cause any calls to mpfr's allocation routines, as mpfr may call these inside it's own code. | |
914 | The following table gives an idea of the performance tradeoff's at 50 decimal digits | |
915 | precision[footnote Compiled with VC++10 and /Ox, with MPFR-3.0.0 and MPIR-2.3.0]: | |
916 | ||
917 | [table | |
918 | [[Type][Bessel function evaluation, relative times]] | |
919 | [[`number<mpfr_float_backend<50, allocate_static>, et_on>`][1.0 (5.5s)]] | |
920 | [[`number<mpfr_float_backend<50, allocate_static>, et_off>`][1.05 (5.8s)]] | |
921 | [[`number<mpfr_float_backend<50, allocate_dynamic>, et_on>`][1.05 (5.8s)]] | |
922 | [[`number<mpfr_float_backend<50, allocate_dynamic>, et_off>`][1.16 (6.4s)]] | |
923 | ] | |
924 | ||
925 | [note This type only provides `numeric_limits` support when the precision is fixed at compile time.] | |
926 | ||
927 | As well as the usual conversions from arithmetic and string types, instances of `number<mpfr_float_backend<N> >` are | |
928 | copy constructible and assignable from: | |
929 | ||
930 | * The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`. | |
931 | * The [mpfr] native type `mpfr_t`. | |
932 | * The `number` wrappers around those types: `number<mpfr_float_backend<M> >`, `number<mpf_float<M> >`, `number<gmp_int>`, `number<gmp_rational>`. | |
933 | ||
934 | It's also possible to access the underlying `mpfr_t` via the data() member function of `mpfr_float_backend`. | |
935 | ||
936 | Things you should know when using this type: | |
937 | ||
938 | * A default constructed `mpfr_float_backend` is set to zero (['Note that this is [*not] the default [mpfr] behavior]). | |
939 | * All operations use round to nearest. | |
940 | * No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing | |
941 | [mpfr] or [gmp] code. | |
942 | * The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32. | |
943 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
944 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
945 | as a valid floating-point number. | |
946 | * Division by zero results in an infinity. | |
947 | ||
948 | [h5 [mpfr] example:] | |
949 | ||
950 | [mpfr_eg] | |
951 | ||
952 | [endsect] | |
953 | ||
954 | [section:float128 float128] | |
955 | ||
956 | `#include <boost/multiprecision/float128.hpp>` | |
957 | ||
958 | namespace boost{ namespace multiprecision{ | |
959 | ||
960 | class float128_backend; | |
961 | ||
962 | typedef number<float128_backend, et_off> float128; | |
963 | ||
964 | }} // namespaces | |
965 | ||
966 | The `float128` number type is a very thin wrapper around GCC's `__float128` or Intel's `_Quad` data types | |
967 | and provides an real-number type that is a drop-in replacement for the native C++ floating-point types, but with | |
968 | a 113 bit mantissa, and compatible with FORTRAN's 128-bit QUAD real. | |
969 | ||
970 | All the usual standard library and `numeric_limits` support are available, performance should be equivalent | |
971 | to the underlying native types: for example the LINPACK benchmarks for GCC's `__float128` and | |
972 | `boost::multiprecision::float128` both achieved 5.6 MFLOPS[footnote On 64-bit Ubuntu 11.10, GCC-4.8.0, Intel Core 2 Duo T5800.]. | |
973 | ||
974 | As well as the usual conversions from arithmetic and string types, instances of `float128` are | |
975 | copy constructible and assignable from GCC's `__float128` and Intel's `_Quad` data types. | |
976 | ||
977 | It's also possible to access the underlying `__float128` or `_Quad` type via the `data()` member | |
978 | function of `float128_backend`. | |
979 | ||
980 | Things you should know when using this type: | |
981 | ||
982 | * Default constructed `float128`s have the value zero. | |
983 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
984 | * It is not possible to round-trip objects of this type to and from a string and get back | |
985 | exactly the same value when compiled with Intel's C++ compiler and using `_Quad` as the underlying type: this is a current limitation of | |
986 | our code. Round tripping when using `__float128` as the underlying type is possible (both for GCC and Intel). | |
987 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
988 | as a valid floating-point number. | |
989 | * Division by zero results in an infinity being produced. | |
990 | * Type `float128` can be used as a literal type (constexpr support). | |
991 | * When using the Intel compiler, the underlying type defaults to `__float128` if it's available and `_Quad` if not. You can override | |
992 | the default by defining either `BOOST_MP_USE_FLOAT128` or `BOOST_MP_USE_QUAD`. | |
993 | * When the underlying type is Intel's `_Quad` type, the code must be compiled with the compiler option `-Qoption,cpp,--extended_float_type`. | |
994 | ||
995 | [h5 float128 example:] | |
996 | ||
997 | [float128_eg] | |
998 | ||
999 | [endsect] | |
1000 | ||
1001 | [section:fp_eg Examples] | |
1002 | ||
1003 | [import ../example/floating_point_examples.cpp] | |
1004 | ||
1005 | [section:aos Area of Circle] | |
1006 | ||
1007 | [AOS1] | |
1008 | [AOS2] | |
1009 | [AOS3] | |
1010 | ||
1011 | [endsect] | |
1012 | ||
1013 | [section:jel Defining a Special Function.] | |
1014 | ||
1015 | [JEL] | |
1016 | ||
1017 | [endsect] | |
1018 | ||
1019 | [section:nd Calculating a Derivative] | |
1020 | ||
1021 | [ND1] | |
1022 | [ND2] | |
1023 | [ND3] | |
1024 | ||
1025 | [endsect] | |
1026 | ||
1027 | [section:gi Calculating an Integral] | |
1028 | ||
1029 | [GI1] | |
1030 | [GI2] | |
1031 | ||
1032 | [endsect] | |
1033 | ||
1034 | [section:poly_eg Polynomial Evaluation] | |
1035 | ||
1036 | [POLY] | |
1037 | ||
1038 | [endsect] [/section:poly_eg Polynomial Evaluation] | |
1039 | ||
1040 | [endsect] [/section:fp_eg Examples] | |
1041 | ||
1042 | [endsect] [/section:floats floating-point Numbers] | |
1043 | ||
1044 | [section:interval Interval Number Types] | |
1045 | ||
1046 | There is one currently only one interval number type supported - [mpfi]. | |
1047 | ||
1048 | [section:mpfi mpfi_float] | |
1049 | ||
1050 | `#include <boost/multiprecision/mpfi.hpp>` | |
1051 | ||
1052 | namespace boost{ namespace multiprecision{ | |
1053 | ||
1054 | template <unsigned Digits10> | |
1055 | class mpfi_float_backend; | |
1056 | ||
1057 | typedef number<mpfi_float_backend<50> > mpfi_float_50; | |
1058 | typedef number<mpfi_float_backend<100> > mpfifloat_100; | |
1059 | typedef number<mpfi_float_backend<500> > mpfifloat_500; | |
1060 | typedef number<mpfi_float_backend<1000> > mpfi_float_1000; | |
1061 | typedef number<mpfi_float_backend<0> > mpfi_float; | |
1062 | ||
1063 | }} // namespaces | |
1064 | ||
1065 | The `mpfi_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfi] `mpfi_t` | |
1066 | to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with | |
1067 | much greater precision and implementing interval arithmetic. | |
1068 | ||
1069 | Type `mpfi_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or | |
1070 | at variable precision by setting the template argument to zero. The typedefs mpfi_float_50, mpfi_float_100, | |
1071 | mpfi_float_500, mpfi_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision | |
1072 | respectively. The typedef mpfi_float provides a variable precision type whose precision can be controlled via the | |
1073 | `number`s member functions. | |
1074 | ||
1075 | [note This type only provides `numeric_limits` support when the precision is fixed at compile time.] | |
1076 | ||
1077 | As well as the usual conversions from arithmetic and string types, instances of `number<mpfi_float_backend<N> >` are | |
1078 | copy constructible and assignable from: | |
1079 | ||
1080 | * The [mpfi] native type `mpfi_t`. | |
1081 | * The `number` wrappers around [mpfi] or [mpfr]: `number<mpfi_float_backend<M> >` and `number<mpfr_float<M> >`. | |
1082 | * There is a two argument constructor taking two `number<mpfr_float<M> >` arguments specifying the interval. | |
1083 | ||
1084 | It's also possible to access the underlying `mpfi_t` via the data() member function of `mpfi_float_backend`. | |
1085 | ||
1086 | Things you should know when using this type: | |
1087 | ||
1088 | * A default constructed `mpfi_float_backend` is set to zero (['Note that this is [*not] the default [mpfi] behavior]). | |
1089 | * No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing | |
1090 | [mpfr] or [gmp] code. | |
1091 | * The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32. | |
1092 | * This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. | |
1093 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted | |
1094 | as a valid floating-point number. | |
1095 | * Division by zero results in an infinity. | |
1096 | ||
1097 | There are some additional non member functions for working on intervals: | |
1098 | ||
1099 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1100 | number<mpfr_float_backend<Digits10>, ExpressionTemplates> lower(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val); | |
1101 | ||
1102 | Returns the lower end of the interval. | |
1103 | ||
1104 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1105 | number<mpfr_float_backend<Digits10>, ExpressionTemplates> upper(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val); | |
1106 | ||
1107 | Returns the upper end of the interval. | |
1108 | ||
1109 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1110 | number<mpfr_float_backend<Digits10>, ExpressionTemplates> median(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val); | |
1111 | ||
1112 | Returns the mid point of the interval. | |
1113 | ||
1114 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1115 | number<mpfr_float_backend<Digits10>, ExpressionTemplates> width(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val); | |
1116 | ||
1117 | Returns the absolute width of the interval. | |
1118 | ||
1119 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1120 | number<mpfi_float_backend<Digits10>, ExpressionTemplates> intersect( | |
1121 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, | |
1122 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b); | |
1123 | ||
1124 | Returns the interval which is the intersection of the ['a] and ['b]. Returns an | |
1125 | unspecified empty interval if there is no such intersection. | |
1126 | ||
1127 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1128 | number<mpfi_float_backend<Digits10>, ExpressionTemplates> hull( | |
1129 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, | |
1130 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b); | |
1131 | ||
1132 | Returns the interval which is the union of ['a] and ['b]. | |
1133 | ||
1134 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1135 | bool overlap(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, | |
1136 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b); | |
1137 | ||
1138 | Returns `true` only if the intervals ['a] and ['b] overlap. | |
1139 | ||
1140 | template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2> | |
1141 | bool in(const number<mpfr_float_backend<Digits10>, ExpressionTemplates1>& a, | |
1142 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates2>& b); | |
1143 | ||
1144 | Returns `true` only if point ['a] is contained within the interval ['b]. | |
1145 | ||
1146 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1147 | bool zero_in(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a); | |
1148 | ||
1149 | Returns `true` only if the interval ['a] contains the value zero. | |
1150 | ||
1151 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1152 | bool subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, | |
1153 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b); | |
1154 | ||
1155 | Returns `true` only if ['a] is a subset of ['b]. | |
1156 | ||
1157 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1158 | bool proper_subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, | |
1159 | const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b); | |
1160 | ||
1161 | Returns `true` only if ['a] is a proper subset of ['b]. | |
1162 | ||
1163 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1164 | bool empty(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a); | |
1165 | ||
1166 | Returns `true` only if ['a] is an empty interval, equivalent to `upper(a) < lower(a)`. | |
1167 | ||
1168 | template <unsigned Digits10, expression_template_option ExpressionTemplates> | |
1169 | bool singleton(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a); | |
1170 | ||
1171 | Returns `true` if `lower(a) == upper(a)`. | |
1172 | ||
1173 | [h5 [mpfi] example:] | |
1174 | ||
1175 | [mpfi_eg] | |
1176 | ||
1177 | [endsect] | |
1178 | ||
1179 | [endsect] | |
1180 | ||
1181 | [section:rational Rational Number Types] | |
1182 | ||
1183 | The following back-ends provide rational number arithmetic: | |
1184 | ||
1185 | [table | |
1186 | [[Backend Type][Header][Radix][Dependencies][Pros][Cons]] | |
1187 | [[`cpp_rational`][boost/multiprecision/cpp_int.hpp][2][None][An all C++ Boost-licensed implementation.][Slower than [gmp].]] | |
1188 | [[`gmp_rational`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] | |
1189 | [[`tommath_rational`][boost/multiprecision/tommath.hpp][2][[tommath]][All C/C++ implementation that's Boost Software Licence compatible.][Slower than [gmp].]] | |
1190 | [[`rational_adaptor`][boost/multiprecision/rational_adaptor.hpp][N/A][none][All C++ adaptor that allows any integer back-end type to be used as a rational type.][Requires an underlying integer back-end type.]] | |
1191 | [[`boost::rational`][boost/rational.hpp][N/A][None][A C++ rational number type that can used with any `number` integer type.][The expression templates used by `number` end up being "hidden" inside `boost::rational`: performance may well suffer as a result.]] | |
1192 | ] | |
1193 | ||
1194 | [section:cpp_rational cpp_rational] | |
1195 | ||
1196 | `#include <boost/multiprecision/cpp_int.hpp>` | |
1197 | ||
1198 | namespace boost{ namespace multiprecision{ | |
1199 | ||
1200 | typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend; | |
1201 | ||
1202 | typedef number<cpp_rational_backend> cpp_rational; | |
1203 | ||
1204 | }} // namespaces | |
1205 | ||
1206 | The `cpp_rational_backend` type is used via the typedef `boost::multiprecision::cpp_rational`. It provides | |
1207 | a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. | |
1208 | ||
1209 | As well as the usual conversions from arithmetic and string types, instances of `cpp_rational` are copy constructible | |
1210 | and assignable from type `cpp_int`. | |
1211 | ||
1212 | There is also a two argument constructor that accepts a numerator and denominator: both of type `cpp_int`. | |
1213 | ||
1214 | There are also non-member functions: | |
1215 | ||
1216 | cpp_int numerator(const cpp_rational&); | |
1217 | cpp_int denominator(const cpp_rational&); | |
1218 | ||
1219 | which return the numerator and denominator of the number. | |
1220 | ||
1221 | Things you should know when using this type: | |
1222 | ||
1223 | * Default constructed `cpp_rational`s have the value zero. | |
1224 | * Division by zero results in a `std::overflow_error` being thrown. | |
1225 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be | |
1226 | interpreted as a valid rational number. | |
1227 | ||
1228 | [h5 Example:] | |
1229 | ||
1230 | [cpp_rational_eg] | |
1231 | ||
1232 | [endsect] | |
1233 | ||
1234 | [section:gmp_rational gmp_rational] | |
1235 | ||
1236 | `#include <boost/multiprecision/gmp.hpp>` | |
1237 | ||
1238 | namespace boost{ namespace multiprecision{ | |
1239 | ||
1240 | class gmp_rational; | |
1241 | ||
1242 | typedef number<gmp_rational > mpq_rational; | |
1243 | ||
1244 | }} // namespaces | |
1245 | ||
1246 | The `gmp_rational` back-end is used via the typedef `boost::multiprecision::mpq_rational`. It acts as a thin wrapper around the [gmp] `mpq_t` | |
1247 | to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. | |
1248 | ||
1249 | As well as the usual conversions from arithmetic and string types, instances of `number<gmp_rational>` are copy constructible | |
1250 | and assignable from: | |
1251 | ||
1252 | * The [gmp] native types: `mpz_t`, `mpq_t`. | |
1253 | * `number<gmp_int>`. | |
1254 | ||
1255 | There is also a two-argument constructor that accepts a numerator and denominator (both of type `number<gmp_int>`). | |
1256 | ||
1257 | There are also non-member functions: | |
1258 | ||
1259 | mpz_int numerator(const mpq_rational&); | |
1260 | mpz_int denominator(const mpq_rational&); | |
1261 | ||
1262 | which return the numerator and denominator of the number. | |
1263 | ||
1264 | It's also possible to access the underlying `mpq_t` via the `data()` member function of `mpq_rational`. | |
1265 | ||
1266 | Things you should know when using this type: | |
1267 | ||
1268 | * Default constructed `mpq_rational`s have the value zero (this is the [gmp] default behavior). | |
1269 | * Division by zero results in a `std::overflow_error` being thrown. | |
1270 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be | |
1271 | interpreted as a valid rational number. | |
1272 | * No changes are made to the [gmp] library's global settings, so this type can coexist with existing | |
1273 | [gmp] code. | |
1274 | * The code can equally be used with [mpir] as the underlying library - indeed that is the preferred option on Win32. | |
1275 | ||
1276 | [h5 Example:] | |
1277 | ||
1278 | [mpq_eg] | |
1279 | ||
1280 | [endsect] | |
1281 | ||
1282 | [section:tommath_rational tommath_rational] | |
1283 | ||
1284 | `#include <boost/multiprecision/tommath.hpp>` | |
1285 | ||
1286 | namespace boost{ namespace multiprecision{ | |
1287 | ||
1288 | typedef rational_adpater<tommath_int> tommath_rational; | |
1289 | typedef number<tommath_rational > tom_rational; | |
1290 | ||
1291 | }} // namespaces | |
1292 | ||
1293 | The `tommath_rational` back-end is used via the typedef `boost::multiprecision::tom_rational`. It acts as a thin wrapper around | |
1294 | `boost::rational<tom_int>` | |
1295 | to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. | |
1296 | ||
1297 | The advantage of using this type rather than `boost::rational<tom_int>` directly, is that it is expression-template enabled, | |
1298 | greatly reducing the number of temporaries created in complex expressions. | |
1299 | ||
1300 | There are also non-member functions: | |
1301 | ||
1302 | tom_int numerator(const tom_rational&); | |
1303 | tom_int denominator(const tom_rational&); | |
1304 | ||
1305 | which return the numerator and denominator of the number. | |
1306 | ||
1307 | Things you should know when using this type: | |
1308 | ||
1309 | * Default constructed `tom_rational`s have the value zero (this the inherited Boost.Rational behavior). | |
1310 | * Division by zero results in a `std::overflow_error` being thrown. | |
1311 | * Conversion from a string results in a `std::runtime_error` being thrown if the string can not be | |
1312 | interpreted as a valid rational number. | |
1313 | * No changes are made to [tommath]'s global state, so this type can safely coexist with other [tommath] code. | |
1314 | * Performance of this type has been found to be pretty poor - this need further investigation - but it appears that Boost.Rational | |
1315 | needs some improvement in this area. | |
1316 | ||
1317 | [h5 Example:] | |
1318 | ||
1319 | [mp_rat_eg] | |
1320 | ||
1321 | [endsect] | |
1322 | ||
1323 | [section:br Use With Boost.Rational] | |
1324 | ||
1325 | All of the integer types in this library can be used as template arguments to `boost::rational<IntType>`. | |
1326 | ||
1327 | Note that using the library in this way largely negates the effect of the expression templates in `number`. | |
1328 | ||
1329 | [endsect] | |
1330 | ||
1331 | [section:rational_adaptor rational_adaptor] | |
1332 | ||
1333 | namespace boost{ namespace multiprecision{ | |
1334 | ||
1335 | template <class IntBackend> | |
1336 | class rational_adpater; | |
1337 | ||
1338 | }} | |
1339 | ||
1340 | The class template `rational_adaptor` is a back-end for `number` which converts any existing integer back-end | |
1341 | into a rational-number back-end. | |
1342 | ||
1343 | So for example, given an integer back-end type `MyIntegerBackend`, the use would be something like: | |
1344 | ||
1345 | typedef number<MyIntegerBackend> MyInt; | |
1346 | typedef number<rational_adaptor<MyIntegerBackend> > MyRational; | |
1347 | ||
1348 | MyRational r = 2; | |
1349 | r /= 3; | |
1350 | MyInt i = numerator(r); | |
1351 | assert(i == 2); | |
1352 | ||
1353 | [endsect] | |
1354 | ||
1355 | [endsect] | |
1356 | ||
1357 | [section:misc Miscellaneous Number Types.] | |
1358 | ||
1359 | Backend types listed in this section are predominantly designed to aid debugging. | |
1360 | ||
1361 | [section:logged_adaptor logged_adaptor] | |
1362 | ||
1363 | `#include <boost/multiprecision/logged_adaptor.hpp>` | |
1364 | ||
1365 | namespace boost{ namespace multiprecision{ | |
1366 | ||
1367 | template <class Backend> | |
1368 | void log_postfix_event(const Backend& result, const char* event_description); | |
1369 | template <class Backend, class T> | |
1370 | void log_postfix_event(const Backend& result1, const T& result2, const char* event_description); | |
1371 | ||
1372 | template <class Backend> | |
1373 | void log_prefix_event(const Backend& arg1, const char* event_description); | |
1374 | template <class Backend, class T> | |
1375 | void log_prefix_event(const Backend& arg1, const T& arg2, const char* event_description); | |
1376 | template <class Backend, class T, class U> | |
1377 | void log_prefix_event(const Backend& arg1, const T& arg2, const U& arg3, const char* event_description); | |
1378 | template <class Backend, class T, class U, class V> | |
1379 | void log_prefix_event(const Backend& arg1, const T& arg2, const U& arg3, const V& arg4, const char* event_description); | |
1380 | ||
1381 | template <Backend> | |
1382 | class logged_adaptor; | |
1383 | ||
1384 | }} // namespaces | |
1385 | ||
1386 | The `logged_adaptor` type is used in conjunction with `number` and some other backend type: it acts as a thin wrapper around | |
1387 | some other backend to class `number` and logs all the events that take place on that object. Before any number operation takes | |
1388 | place, it calls `log_prefix_event` with the arguments to the operation (up to 4), plus a string describing the operation. | |
1389 | Then after the operation it calls `log_postfix_event` with the result of the operation, plus a string describing the operation. | |
1390 | Optionally, `log_postfix_event` takes a second result argument: this occurs when the result of the operation is not a `number`, | |
1391 | for example when `fpclassify` is called, `log_postfix_event` will be called with `result1` being the argument to the function, and | |
1392 | `result2` being the integer result of `fpclassify`. | |
1393 | ||
1394 | The default versions of `log_prefix_event` and `log_postfix_event` do nothing, it is therefore up to the user to overload these | |
1395 | for the particular backend being observed. | |
1396 | ||
1397 | This type provides `numeric_limits` support whenever the template argument Backend does so. | |
1398 | ||
1399 | This type is particularly useful when combined with an interval number type - in this case we can use `log_postfix_event` | |
1400 | to monitor the error accumulated after each operation. We could either set some kind of trap whenever the accumulated error | |
1401 | exceeds some threshold, or simply print out diagnostic information. Using this technique we can quickly locate the cause of | |
1402 | numerical instability in a particular routine. The following example demonstrates this technique in a trivial algorithm | |
1403 | that deliberately introduces cancellation error: | |
1404 | ||
1405 | [logged_adaptor] | |
1406 | ||
1407 | When we examine program output we can clearly see that the diameter of the interval increases after each subtraction: | |
1408 | ||
1409 | [logged_adaptor_output] | |
1410 | ||
1411 | [endsect] | |
1412 | ||
1413 | [section:debug_adaptor debug_adaptor] | |
1414 | ||
1415 | `#include <boost/multiprecision/debug_adaptor.hpp>` | |
1416 | ||
1417 | namespace boost{ namespace multiprecision{ | |
1418 | ||
1419 | template <Backend> | |
1420 | class debug_adaptor; | |
1421 | ||
1422 | }} // namespaces | |
1423 | ||
1424 | The `debug_adaptor` type is used in conjunction with `number` and some other backend type: it acts as a thin wrapper around | |
1425 | some other backend to class `number` and intercepts all operations on that object storing the result as a string within itself. | |
1426 | ||
1427 | This type provides `numeric_limits` support whenever the template argument Backend does so. | |
1428 | ||
1429 | This type is particularly useful when your debugger provides a good view of `std::string`: when this is the case | |
1430 | multiprecision values can easily be inspected in the debugger by looking at the `debug_value` member of `debug_adaptor`. | |
1431 | The down side of this approach is that runtimes are much slower when using this type. Set against that it can make | |
1432 | debugging very much easier, certainly much easier than sprinkling code with `printf` statements. | |
1433 | ||
1434 | When used in conjunction with the Visual C++ debugger visualisers, the value of a multiprecision type that uses this | |
1435 | backend is displayed in the debugger just a builtin value would be, here we're inspecting a value of type | |
1436 | `number<debug_adaptor<cpp_dec_float<50> > >`: | |
1437 | ||
1438 | [$../debugger1.png] | |
1439 | ||
1440 | Otherwise you will need to expand out the view and look at the "debug_value" member: | |
1441 | ||
1442 | [$../debugger2.png] | |
1443 | ||
1444 | It works for all the backend types equally too, here it is inspecting a `number<debug_adaptor<gmp_rational> >`: | |
1445 | ||
1446 | [$../debugger3.png] | |
1447 | ||
1448 | ||
1449 | [endsect] | |
1450 | ||
1451 | [section:visualizers Visual C++ Debugger Visualizers] | |
1452 | ||
1453 | Let's face it debugger multiprecision numbers is hard - simply because we can't easily inspect the value of the numbers. | |
1454 | Visual C++ provides a partial solution in the shape of "visualizers" which provide improved views of complex data structures, | |
1455 | these visualizers need to be added to the `[Visualizer]` section of `autoexp.dat` located in the `Common7/Packages/Debugger` | |
1456 | directory of your Visual Studio installation. The actual visualizer code is in the sandbox | |
1457 | [@https://svn.boost.org/svn/boost/sandbox/boost_docs/subprojects/DebuggerVisualizers/multiprecision.vis.txt here] - just cut and paste the code | |
1458 | into your `autoexp.dat` file. | |
1459 | ||
1460 | [note These visualizers have only been tested with VC10, also given the ability of buggy visualizers to crash your Visual C++ | |
1461 | debugger, make sure you back up `autoexp.dat` file before using these!!] | |
1462 | ||
1463 | The first visualizer provides improved views of `debug_adaptor`: | |
1464 | ||
1465 | [$../debugger1.png] | |
1466 | ||
1467 | The next visualizer provides improved views of cpp_int: small numbers are displayed as actual values, while larger numbers are | |
1468 | displayed as an array of hexadecimal parts, with the most significant part first. | |
1469 | ||
1470 | Here's what it looks like for small values: | |
1471 | ||
1472 | [$../debugger4.png] | |
1473 | ||
1474 | And for larger values: | |
1475 | ||
1476 | [$../debugger5.png] | |
1477 | ||
1478 | There is also a `~raw` child member that | |
1479 | lets you see the actual members of the class: | |
1480 | ||
1481 | [$../debugger6.png] | |
1482 | ||
1483 | The visualizer for `cpp_dec_float` shows the first few digits of the value in the preview field, and the full array of digits | |
1484 | when you expand the view. As before the `~raw` child gives you access to the actual data members: | |
1485 | ||
1486 | [$../debugger7.png] | |
1487 | ||
1488 | [endsect] | |
1489 | ||
1490 | [endsect] | |
1491 | ||
1492 | [section:conversions Constructing and Interconverting Between Number Types] | |
1493 | ||
1494 | All of the number types that are based on `number` have certain conversion rules in common. | |
1495 | In particular: | |
1496 | ||
1497 | * Any number type can be constructed (or assigned) from any builtin arithmetic type, as long | |
1498 | as the conversion isn't lossy (for example float to int conversion): | |
1499 | ||
1500 | cpp_dec_float_50 df(0.5); // OK construction from double | |
1501 | cpp_int i(450); // OK constructs from signed int | |
1502 | cpp_int j = 3.14; // Error, lossy conversion. | |
1503 | ||
1504 | * A number can be explicitly constructed from an arithmetic type, even when the conversion is lossy: | |
1505 | ||
1506 | cpp_int i(3.14); // OK explicit conversion | |
1507 | i = static_cast<cpp_int>(3.14) // OK explicit conversion | |
1508 | i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above | |
1509 | i = 3.14; // Error, no implicit assignment operator for lossy conversion. | |
1510 | cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion. | |
1511 | ||
1512 | * A `number` can be converted to any built in type, via the `convert_to` member function: | |
1513 | ||
1514 | mpz_int z(2); | |
1515 | int i = z.template convert_to<int>(); // sets i to 2 | |
1516 | ||
1517 | * Conversions to rational numbers from floating-point ones are always allowed, and are exact and implicit | |
1518 | as long as the rational number uses an unbounded integer type. Please be aware that constructing a rational | |
1519 | number from an extended precision floating-point type with a large exponent range can effectively run the system | |
1520 | out of memory, as in the extreme case ['2[super max_exponent] / CHAR_BITS] bytes of storage may be required. This | |
1521 | does not represent a problem for built in floating-point types however, as the exponent range for these is rather | |
1522 | limited. | |
1523 | ||
1524 | * Conversions to floating-point numbers from rational ones are rounded to nearest (less than 0.5ulp error) | |
1525 | as long as the floating-point number is binary, and the integer type used by the rational number is unbounded. | |
1526 | ||
1527 | Additional conversions may be supported by particular backends. | |
1528 | ||
1529 | * A `number` can be converted to any built in type, via an explicit conversion operator: | |
1530 | this functionality is only available on compilers supporting C++11's explicit conversion syntax. | |
1531 | ||
1532 | mpz_int z(2); | |
1533 | int i = z; // Error, implicit conversion not allowed. | |
1534 | int j = static_cast<int>(z); // OK explicit conversion. | |
1535 | ||
1536 | * Any number type can be ['explicitly] constructed (or assigned) from a `const char*` or a `std::string`: | |
1537 | ||
1538 | // pi to 50 places from a string: | |
1539 | cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510"); | |
1540 | // Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly: | |
1541 | cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000"); | |
1542 | // Invalid input always results in a std::runtime_error being thrown: | |
1543 | i = static_cast<cpp_int>("3.14"); | |
1544 | // implicit conversions from strings are not allowed: | |
1545 | i = "23"; // Error, no assignment operator for implicit conversion from string | |
1546 | // assign member function, avoids having to create a temporary via a static_cast: | |
1547 | i.assign("23"); // OK | |
1548 | ||
1549 | * Any number type will interoperate with the builtin types in arithmetic expressions as long as the conversions | |
1550 | are not lossy: | |
1551 | ||
1552 | // pi to 50 places from a string: | |
1553 | cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; | |
1554 | // Multiply by 2 - using an integer literal here is usually more efficient | |
1555 | // than constructing a temporary: | |
1556 | df *= 2; | |
1557 | ||
1558 | // You can't mix integer types with floats though: | |
1559 | cpp_int i = 2; | |
1560 | i *= 3.14; // Error, no *= operator will be found. | |
1561 | ||
1562 | * Any number type can be streamed to and from the C++ iostreams: | |
1563 | ||
1564 | cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; | |
1565 | // Now print at full precision: | |
1566 | std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10) | |
1567 | << df << std::endl | |
1568 | cpp_int i = 1; | |
1569 | i <<= 256; | |
1570 | // Now print in hex format with prefix: | |
1571 | std::cout << std::hex << std::showbase << i << std::endl; | |
1572 | ||
1573 | * Interconversions between number types of the same family are allowed and are implicit conversions if no | |
1574 | loss of precision is involved, and explicit if it is: | |
1575 | ||
1576 | int128_t i128 = 0; | |
1577 | int266_t i256 = i128; // OK implicit widening conversion | |
1578 | i128_t = i256; // Error, no assignment operator found, narrowing conversion is explicit. | |
1579 | i128_t = static_cast<int128_t>(i256); // OK, explicit narrowing conversion. | |
1580 | ||
1581 | mpz_int z = 0; | |
1582 | mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit. | |
1583 | ||
1584 | mpf_float_50 f50 = 2; | |
1585 | f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision. | |
1586 | f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required. | |
1587 | ||
1588 | * Some interconversions between number types are completely generic, and are always available, albeit the conversions are always ['explicit]: | |
1589 | ||
1590 | cpp_int cppi(2); | |
1591 | // We can always convert between numbers of the same category - | |
1592 | // int to int, rational to rational, or float to float, so this is OK | |
1593 | // as long as we use an explicit conversion: | |
1594 | mpz_int z(cppi); | |
1595 | // We can always promote from int to rational, int to float, or rational to float: | |
1596 | cpp_rational cppr(cppi); // OK, int to rational | |
1597 | cpp_dec_float_50 df(cppi); // OK, int to float | |
1598 | df = static_cast<cpp_dec_float_50>(cppr); // OK, explicit rational to float conversion | |
1599 | // However narrowing and/or implicit conversions always fail: | |
1600 | cppi = df; // Compiler error, conversion not allowed | |
1601 | ||
1602 | * Other interconversions may be allowed as special cases, whenever the backend allows it: | |
1603 | ||
1604 | mpf_t m; // Native GMP type. | |
1605 | mpf_init_set_ui(m, 0); // set to a value; | |
1606 | mpf_float i(m); // copies the value of the native type. | |
1607 | ||
1608 | More information on what additional types a backend supports conversions from are given in the tutorial for each backend. | |
1609 | The converting constructor will be implicit if the backend's converting constructor is also implicit, and explicit if the | |
1610 | backends converting constructor is also explicit. | |
1611 | ||
1612 | [endsect] | |
1613 | ||
1614 | [section:random Generating Random Numbers] | |
1615 | ||
1616 | Random numbers are generated in conjunction with Boost.Random. | |
1617 | ||
1618 | There is a single generator that supports generating random integers with large bit counts: | |
1619 | [@http://www.boost.org/doc/html/boost/random/independent_bits_engine.html `independent_bits_engine`]. | |
1620 | This type can be used with either ['unbounded] integer types, or with ['bounded] (ie fixed precision) unsigned integers: | |
1621 | ||
1622 | [random_eg1] | |
1623 | ||
1624 | Program output is: | |
1625 | ||
1626 | [random_eg1_out] | |
1627 | ||
1628 | In addition, the generator adaptors [@http://www.boost.org/doc/html/boost/random/discard_block_engine.html `discard_block`], | |
1629 | [@http://www.boost.org/doc/html/boost/random/xor_combine_engine.html `xor_combine_engine`] and | |
1630 | [@http://www.boost.org/doc/html/boost/random/discrete_distribution.html `discrete_distribution`] can be used | |
1631 | with multiprecision types. Note that if you seed an `independent_bits_engine`, then you are actually seeding | |
1632 | the underlying generator, and should therefore provide a sequence of unsigned 32-bit values as the seed. | |
1633 | ||
1634 | Alternatively we can generate integers in a given range using | |
1635 | [@http://www.boost.org/doc/html/boost/random/uniform_int_distribution.html `uniform_int_distribution`], this will | |
1636 | invoke the underlying engine multiple times to build up the required number of bits in the result: | |
1637 | ||
1638 | [random_eg2] | |
1639 | ||
1640 | [random_eg2_out] | |
1641 | ||
1642 | It is also possible to use [@http://www.boost.org/doc/html/boost/random/uniform_int_distribution.html `uniform_int_distribution`] | |
1643 | with a multiprecision generator such as [@http://www.boost.org/doc/html/boost/random/independent_bits_engine.html `independent_bits_engine`]. | |
1644 | Or to use [@http://www.boost.org/doc/html/boost/random/uniform_smallint.html `uniform_smallint`] or | |
1645 | [@http://www.boost.org/doc/html/boost/random/random_number_generator.html `random_number_generator`] with multiprecision types. | |
1646 | ||
1647 | floating-point values in \[0,1) are most easily generated using [@http://www.boost.org/doc/html/boost/random/generate_canonical.html `generate_canonical`], | |
1648 | note that `generate_canonical` will call the generator multiple times to produce the requested number of bits, for example we can use | |
1649 | it with a regular generator like so: | |
1650 | ||
1651 | [random_eg3] | |
1652 | ||
1653 | [random_eg3_out] | |
1654 | ||
1655 | Note however, the distributions do not invoke the generator multiple times to fill up the mantissa of a multiprecision floating-point type | |
1656 | with random bits. For these therefore, we should probably use a multiprecision generator (ie `independent_bits_engine`) in combination | |
1657 | with the distribution: | |
1658 | ||
1659 | [random_eg4] | |
1660 | ||
1661 | [random_eg4_out] | |
1662 | ||
1663 | And finally, it is possible to use the floating-point generators [@http://www.boost.org/doc/html/boost/random/lagged_fibonacci_01_engine.html `lagged_fibonacci_01_engine`] | |
1664 | and [@http://www.boost.org/doc/html/boost/random/subtract_with_idp144360752.html `subtract_with_carry_01_engine`] directly with multiprecision floating-point types. | |
1665 | It's worth noting however, that there is a distinct lack of literature on generating high bit-count random numbers, and therefore a lack of "known good" parameters to | |
1666 | use with these generators in this situation. For this reason, these should probably be used for research purposes only: | |
1667 | ||
1668 | [random_eg5] | |
1669 | ||
1670 | [endsect] | |
1671 | ||
1672 | [section:primetest Primality Testing] | |
1673 | ||
1674 | The library implements a Miller-Rabin test for primality: | |
1675 | ||
1676 | #include <boost/multiprecision/miller_rabin.hpp> | |
1677 | ||
1678 | template <class Backend, expression_template_option ExpressionTemplates, class Engine> | |
1679 | bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials, Engine& gen); | |
1680 | ||
1681 | template <class Backend, expression_template_option ExpressionTemplates, class Engine> | |
1682 | bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials); | |
1683 | ||
1684 | These functions perform a Miller-Rabin test for primality, if the result is `false` then /n/ is definitely composite, | |
1685 | while if the result is true then n is probably prime. The probability to declare a composite n as probable prime is | |
1686 | at most 0.25[super trials]. Note that this does not allow a statement about the probability of n being actually | |
1687 | prime (for that, the prior probability would have to be known). The algorithm used performs some | |
1688 | trial divisions to exclude small prime factors, does one Fermat test to exclude many more composites, and then | |
1689 | uses the Miller-Rabin algorithm straight out of | |
1690 | Knuth Vol 2, which recommends 25 trials for a pretty strong likelihood that /n/ is prime. | |
1691 | ||
1692 | The third optional argument is for a Uniform Random Number Generator from Boost.Random. When not provided the `mt19937` | |
1693 | generator is used. Note that when producing random primes then you should probably use a different random number generator | |
1694 | to produce candidate prime numbers for testing, than is used internally by `miller_rabin_test` for determining | |
1695 | whether the value is prime. It also helps of course to seed the generators with some source of randomness. | |
1696 | ||
1697 | The following example searches for a prime `p` for which `(p-1)/2` is also probably prime: | |
1698 | ||
1699 | [safe_prime] | |
1700 | ||
1701 | [endsect] | |
1702 | ||
1703 | [section:lits Literal Types and `constexpr` Support] | |
1704 | ||
1705 | [note The features described in this section make heavy use of C++11 language features, currently | |
1706 | (as of May 2013) only | |
1707 | GCC-4.7 and later, and Clang 3.3 and later have the support required to make these features work.] | |
1708 | ||
1709 | There is limited support for `constexpr` and user-defined literals in the library, currently the | |
1710 | `number` front end supports `constexpr` | |
1711 | on default construction and all forwarding constructors, but not on any of the non-member operators. So if | |
1712 | some type `B` is a literal type, then `number<B>` is also a literal type, and you will be able to | |
1713 | compile-time-construct such a type from any literal that `B` is compile-time-constructible from. | |
1714 | However, you will not be able to perform compile-time arithmetic on such types. | |
1715 | ||
1716 | Currently the only backend type provided by the library that is also a literal type are instantiations | |
1717 | of `cpp_int_backend` where the Allocator parameter is type `void`, and the Checked parameter is | |
1718 | `boost::multiprecision::unchecked`. | |
1719 | ||
1720 | For example: | |
1721 | ||
1722 | using namespace boost::multiprecision; | |
1723 | ||
1724 | constexpr int128_t i = 0; // OK, fixed precision int128_t has no allocator. | |
1725 | constexpr uint1024_t j = 0xFFFFFFFF00000000uLL; // OK, fixed precision uint1024_t has no allocator. | |
1726 | ||
1727 | constexpr checked_uint128_t k = -1; // Error, checked type is not a literal type as we need runtime error checking. | |
1728 | constexpr cpp_int l = 2; // Error, type is not a literal as it performs memory management. | |
1729 | ||
1730 | There is also limited support for user defined-literals - these are limited to unchecked, fixed precision `cpp_int`'s | |
1731 | which are specified in hexadecimal notation. The suffixes supported are: | |
1732 | ||
1733 | [table | |
1734 | [[Suffix][Meaning]] | |
1735 | [[_cppi][Specifies a value of type: `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`, where N is chosen | |
1736 | to contain just enough digits to hold the number specified.]] | |
1737 | [[_cppui][Specifies a value of type: `number<cpp_int_backend<N,N,unsigned_magnitude,unchecked,void> >`, where N is chosen | |
1738 | to contain just enough digits to hold the number specified.]] | |
1739 | [[_cppi['N]][Specifies a value of type `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`.]] | |
1740 | [[_cppui['N]][Specifies a value of type `number<cpp_int_backend<N,N,signed_magnitude,unchecked,void> >`.]] | |
1741 | ] | |
1742 | ||
1743 | In each case, use of these suffixes with hexadecimal values produces a `constexpr` result. | |
1744 | ||
1745 | Examples: | |
1746 | ||
1747 | // | |
1748 | // Any use of user defined literals requires that we import the literal-operators | |
1749 | // into current scope first: | |
1750 | using namespace boost::multiprecision::literals; | |
1751 | // | |
1752 | // To keep things simple in the example, we'll make our types used visible to this scope as well: | |
1753 | using namespace boost::multiprecision; | |
1754 | // | |
1755 | // The value zero as a number<cpp_int_backend<4,4,signed_magnitude,unchecked,void> >: | |
1756 | constexpr auto a = 0x0_cppi; | |
1757 | // The type of each constant has 4 bits per hexadecimal digit, | |
1758 | // so this is of type uint256_t (ie number<cpp_int_backend<256,256,unsigned_magnitude,unchecked,void> >): | |
1759 | constexpr auto b = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_cppui; | |
1760 | // | |
1761 | // Smaller values can be assigned to larger values: | |
1762 | int256_t c = 0x1234_cppi; // OK | |
1763 | // | |
1764 | // However, this does not currently work in constexpr contexts: | |
1765 | constexpr int256_t d = 0x1_cppi; // Compiler error | |
1766 | // | |
1767 | // Constants can be padded out with leading zeros to generate wider types: | |
1768 | constexpr uint256_t e = 0x0000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFF_cppui; // OK | |
1769 | // | |
1770 | // However, specific width types are best produced with specific-width suffixes, | |
1771 | // ones supported by default are `_cpp[u]i128`, `_cpp[u]i256`, `_cpp[u]i512`, `_cpp[u]i1024`. | |
1772 | // | |
1773 | constexpr int128_t f = 0x1234_cppi128; // OK, always produces an int128_t as the result. | |
1774 | constexpr uint1024_t g = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccc_cppui1024; | |
1775 | // | |
1776 | // If other specific width types are required, then there is a macro for generating the operators | |
1777 | // for these. The macro can be used at namespace scope only: | |
1778 | // | |
1779 | BOOST_MP_DEFINE_SIZED_CPP_INT_LITERAL(2048); | |
1780 | // | |
1781 | // Now we can create 2048-bit literals as well: | |
1782 | constexpr auto h = 0xff_cppi2048; // h is of type number<cpp_int_backend<2048,2048,signed_magnitude,unchecked,void> > | |
1783 | // | |
1784 | // Finally negative values are handled via the unary minus operator: | |
1785 | // | |
1786 | constexpr int1024_t i = -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_cppui1024; | |
1787 | // | |
1788 | // Which means this also works: | |
1789 | constexpr int1024_t j = -g; // OK: unary minus operator is constexpr. | |
1790 | ||
1791 | [endsect] | |
1792 | ||
1793 | [section:import_export Importing and Exporting Data to and from cpp_int and cpp_bin_float] | |
1794 | ||
1795 | Any integer number type that uses `cpp_int_backend` as it's implementation layer can import or export it's bits via two non-member functions: | |
1796 | ||
1797 | template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, | |
1798 | expression_template_option ExpressionTemplates, class OutputIterator> | |
1799 | OutputIterator export_bits( | |
1800 | const number<const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, | |
1801 | OutputIterator out, | |
1802 | unsigned chunk_size, | |
1803 | bool msv_first = true); | |
1804 | ||
1805 | template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, | |
1806 | expression_template_option ExpressionTemplates, class Iterator> | |
1807 | number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& | |
1808 | import_bits( | |
1809 | number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, | |
1810 | Iterator i, | |
1811 | Iterator j, | |
1812 | unsigned chunk_size = 0, | |
1813 | bool msv_first = true); | |
1814 | ||
1815 | These functions are designed for data-interchange with other storage formats, and since __cpp_bin_float uses __cpp_int internally, | |
1816 | by extension they can be used for floating point numbers based on that backend as well (see example below). Parameters and use are as follows: | |
1817 | ||
1818 | template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, | |
1819 | expression_template_option ExpressionTemplates, class OutputIterator> | |
1820 | OutputIterator export_bits( | |
1821 | const number<const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, | |
1822 | OutputIterator out, | |
1823 | unsigned chunk_size, | |
1824 | bool msv_first = true); | |
1825 | ||
1826 | Exports the absolute value of `val` to OutputIterator `out`. The function will write `chunk_size` bits at a time | |
1827 | to the OutputIterator, and if `msv_first` is true, will write the most-significant block first. Byte and bit order | |
1828 | within each `chunk_size` block is always in the machines native format. Further, each block is stored in a | |
1829 | `boost::uintmax_t` when it's assigned to `*out`. | |
1830 | ||
1831 | [note Unfortunately, the standard's OutputIterator concept provides no means of deducing the type to output since | |
1832 | `std::iterator_traits<OutputIteratorType>::value_type` is type `void`. This is why the bit count for each block | |
1833 | has to be specified manually. It may also result in compiler warnings about the value being narrowed.] | |
1834 | ||
1835 | [tip If you're exporting to non-native byte layout, then use | |
1836 | [@http://www.boost.org/doc/libs/release/libs/endian/doc/index.html | |
1837 | Boost.Endian] to create a custom OutputIterator that | |
1838 | reverses the byte order of each chunk prior to actually storing the result.] | |
1839 | ||
1840 | template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, | |
1841 | expression_template_option ExpressionTemplates, class ForwardIterator> | |
1842 | number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& | |
1843 | import_bits( | |
1844 | number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, | |
1845 | ForwardIterator i, | |
1846 | ForwardIterator j, | |
1847 | unsigned chunk_size = 0, | |
1848 | bool msv_first = true); | |
1849 | ||
1850 | Imports bits from the iterator range ['\[i,j)] and stores them in `val` to produce an unsigned result (if the result | |
1851 | is to be signed you will need to handle that separately). When `msv_first` is true, takes `*i` as the most significant | |
1852 | chunk. Assumes there are `chunk_size` bits in each value read from the iterator range, and that these are in machine native | |
1853 | bit/byte order. When `chunk_size` is zero, then assumes that each chunk contains | |
1854 | `std::numeric_limits<std::iterator_traits<ForwardIterator>::value_type>::digits`, note that this will give the wrong result | |
1855 | if dereferencing the iterators leads to a signed-integer type, [*and] the sign bit is significant (be particularly careful | |
1856 | if you expect type `char` to contain 8-bit values, as by default it will extract only 7-bits at a time if `char` is signed). | |
1857 | As with exporting, if the external data is to be in a non-native byte order (within each chunk), then you will need to create an iterator adaptor | |
1858 | that presents it in native order (see [@http://www.boost.org/doc/libs/release/libs/endian/doc/index.html Boost.Endian]). | |
1859 | ||
1860 | [note | |
1861 | Note that this function is optimized for the case where the data can be memcpy'ed from the source to the integer - in this case both | |
1862 | iterators much be pointers, and everything must be little-endian.] | |
1863 | ||
1864 | [h4 Examples] | |
1865 | ||
1866 | [IE1] | |
1867 | ||
1868 | [IE2] | |
1869 | ||
1870 | [endsect] | |
1871 | ||
1872 | [section:rounding Rounding Rules for Conversions] | |
1873 | ||
1874 | As a general rule, all conversions between unrelated types are performed using basic arithmetic operations, therefore | |
1875 | conversions are either exact, or follow the same rounding rules as arithmetic for the type in question. | |
1876 | ||
1877 | The following table summarises the situation for conversions from native types: | |
1878 | ||
1879 | [table | |
1880 | [[Backend][Rounding Rules]] | |
1881 | [[__cpp_int][Conversions from integer types are exact if the target has sufficient precision, otherwise they | |
1882 | truncate to the first 2^MaxBits bits (modulo arithmetic). Conversions from floating-point types | |
1883 | are truncating to the nearest integer.]] | |
1884 | [[__gmp_int][Conversions are performed by the GMP library except for conversion from `long double` which is truncating.]] | |
1885 | [[__tom_int][Conversions from floating-point types are truncating, all others are performed by libtommath and are exact.]] | |
1886 | [[__gmp_float][Conversions are performed by the GMP library except for conversion from `long double` which should be exact | |
1887 | provided the target type has as much precision as a `long double`.]] | |
1888 | [[__mpfr_float_backend][All conversions are performed by the underlying MPFR library.]] | |
1889 | [[__cpp_dec_float][All conversions are performed using basic arithmetic operations and are truncating.]] | |
1890 | [[__gmp_rational][See __gmp_int]] | |
1891 | [[__cpp_rational][See __cpp_int]] | |
1892 | [[__tommath_rational][See __tom_int]] | |
1893 | ] | |
1894 | ||
1895 | [endsect] | |
1896 | ||
1897 | [section:mixed Mixed Precision Arithmetic] | |
1898 | ||
1899 | Mixed precision arithmetic is fully supported by the library. | |
1900 | ||
1901 | There are two different forms: | |
1902 | ||
1903 | * Where the operands are of different precision. | |
1904 | * Where the operands are of the same precision, but yield a higher precision result. | |
1905 | ||
1906 | [h4 Mixing Operands of Differing Precision] | |
1907 | ||
1908 | If the arguments to a binary operator are of different precision, then the operation is allowed | |
1909 | as long as there is an unambiguous implicit conversion from one argument type to the other. | |
1910 | In all cases the arithmetic is performed "as if" the lower precision type is promoted to the | |
1911 | higher precision type before applying the operator. However, particular backends may optimise | |
1912 | this and avoid actually creating a temporary if they are able to do so. | |
1913 | ||
1914 | For example: | |
1915 | ||
1916 | mpfr_float_50 a(2), b; | |
1917 | mpfr_float_100 c(3), d; | |
1918 | static_mpfr_float_50 e(5), f; | |
1919 | mpz_int i(20); | |
1920 | ||
1921 | d = a * c; // OK, result of operand is an mpfr_float_100. | |
1922 | b = a * c; // Error, can't convert the result to an mpfr_float_50 as it will lose digits. | |
1923 | f = a * e; // Error, operator is ambiguous, result could be of either type. | |
1924 | f = e * i; // OK, unambiguous conversion from mpz_int to static_mpfr_float_50 | |
1925 | ||
1926 | [h4 Operands of the Same Precision] | |
1927 | ||
1928 | Sometimes you want to apply an operator to two arguments of the same precision in | |
1929 | such a way as to obtain a result of higher precision. The most common situation | |
1930 | occurs with fixed precision integers, where you want to multiply two N-bit numbers | |
1931 | to obtain a 2N-bit result. This is supported in this library by the following | |
1932 | free functions: | |
1933 | ||
1934 | template <class ResultType, class Source1 class Source2> | |
1935 | ResultType& add(ResultType& result, const Source1& a, const Source2& b); | |
1936 | ||
1937 | template <class ResultType, class Source1 class Source2> | |
1938 | ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); | |
1939 | ||
1940 | template <class ResultType, class Source1 class Source2> | |
1941 | ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); | |
1942 | ||
1943 | These functions apply the named operator to the arguments ['a] and ['b] and store the | |
1944 | result in ['result], returning ['result]. In all cases they behave "as if" | |
1945 | arguments ['a] and ['b] were first promoted to type `ResultType` before applying the | |
1946 | operator, though particular backends may well avoid that step by way of an optimization. | |
1947 | ||
1948 | The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2` | |
1949 | may be either instances of class `number` or native integer types. The latter is an optimization | |
1950 | that allows arithmetic to be performed on native integer types producing an extended precision result. | |
1951 | ||
1952 | For example: | |
1953 | ||
1954 | [mixed_eg] | |
1955 | ||
1956 | Produces the output: | |
1957 | ||
1958 | [mixed_output] | |
1959 | ||
1960 | [h4 Backends With Optimized Mixed Precision Arithmetic] | |
1961 | ||
1962 | The following backends have at least some direct support for mixed precision arithmetic, | |
1963 | and therefore avoid creating unnecessary temporaries when using the interfaces above. | |
1964 | Therefore when using these types it's more efficient to use mixed precision arithmetic, | |
1965 | than it is to explicitly cast the operands to the result type: | |
1966 | ||
1967 | __mpfr_float_backend, __mpf_float, __cpp_int. | |
1968 | ||
1969 | [endsect] | |
1970 | ||
1971 | [section:gen_int Generic Integer Operations] | |
1972 | ||
1973 | All of the [link boost_multiprecision.ref.number.integer_functions non-member integer operations] are overloaded for the | |
1974 | built in integer types in | |
1975 | `<boost/multiprecision/integer.hpp>`. | |
1976 | Where these operations require a temporary increase in precision (such as for powm), then | |
1977 | if no built in type is available, a __cpp_int of appropriate precision will be used. | |
1978 | ||
1979 | Some of these functions are trivial, others use compiler intrinsics (where available) to ensure optimal | |
1980 | evaluation. | |
1981 | ||
1982 | The overloaded functions are: | |
1983 | ||
1984 | template <class Integer, class I2> | |
1985 | Integer& multiply(Integer& result, const I2& a, const I2& b); | |
1986 | ||
1987 | Multiplies two `I2` values, to produce a wider `Integer` result. | |
1988 | ||
1989 | Returns `result = a * b` without overflow or loss of precision in the multiplication. | |
1990 | ||
1991 | template <class Integer, class I2> | |
1992 | Integer& add(Integer& result, const I2& a, const I2& b); | |
1993 | ||
1994 | Adds two `I2` values, to produce a wider `Integer` result. | |
1995 | ||
1996 | Returns `result = a + b` without overflow or loss of precision in the addition. | |
1997 | ||
1998 | template <class Integer, class I2> | |
1999 | Integer& subtract(Integer& result, const I2& a, const I2& b); | |
2000 | ||
2001 | Subtracts two `I2` values, to produce a wider `Integer` result. | |
2002 | ||
2003 | Returns `result = a - b` without overflow or loss of precision in the subtraction. | |
2004 | ||
2005 | template <class Integer> | |
2006 | Integer powm(const Integer& b, const Integer& p, const Integer& m); | |
2007 | ||
2008 | Returns b[super p] % m. | |
2009 | ||
2010 | template <class Integer> | |
2011 | void divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r); | |
2012 | ||
2013 | Sets `q = x / y` and `r = x % y`. | |
2014 | ||
2015 | template <class Integer1, class Integer2> | |
2016 | Integer2 integer_modulus(const Integer1& x, Integer2 val); | |
2017 | ||
2018 | Returns x % val; | |
2019 | ||
2020 | template <class Integer> | |
2021 | unsigned lsb(const Integer& x); | |
2022 | ||
2023 | Returns the (zero-based) index of the least significant bit of `x`. | |
2024 | ||
2025 | Throws a `std::domain_error` if `x <= 0`. | |
2026 | ||
2027 | template <class Integer> | |
2028 | unsigned msb(const Integer& x); | |
2029 | ||
2030 | Returns the (zero-based) index of the most significant bit of `x`. | |
2031 | ||
2032 | Throws a `std::domain_error` if `x <= 0`. | |
2033 | ||
2034 | template <class Integer> | |
2035 | bool bit_test(const Integer& val, unsigned index); | |
2036 | ||
2037 | Returns `true` if bit `index` is set in `val`. | |
2038 | ||
2039 | template <class Integer> | |
2040 | Integer& bit_set(Integer& val, unsigned index); | |
2041 | ||
2042 | Sets the `index` bit in `val`. | |
2043 | ||
2044 | template <class Integer> | |
2045 | Integer& bit_unset(Integer& val, unsigned index); | |
2046 | ||
2047 | Unsets the `index` bit in `val`. | |
2048 | ||
2049 | template <class Integer> | |
2050 | Integer& bit_flip(Integer& val, unsigned index); | |
2051 | ||
2052 | Flips the `index` bit in `val`. | |
2053 | ||
2054 | template <class Integer> | |
2055 | Integer sqrt(const Integer& x); | |
2056 | template <class Integer> | |
2057 | Integer sqrt(const Integer& x, Integer& r); | |
2058 | ||
2059 | Returns the integer square root `s` of x and sets `r` to the remainder ['x - s[super 2]]. | |
2060 | ||
2061 | template <class Engine> | |
2062 | bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials, Engine& gen); | |
2063 | bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials); | |
2064 | ||
2065 | The regular Miller-Rabin functions in `<boost/multiprecision/miller_rabin.hpp>` are defined in terms of the above | |
2066 | generic operations, and so function equally well for built in and multiprecision types. | |
2067 | ||
2068 | [endsect] | |
2069 | ||
2070 | [section:serial Boost.Serialization Support] | |
2071 | ||
2072 | Support for serialization comes in two forms: | |
2073 | ||
2074 | * Classes __number, __debug_adaptor, __logged_adaptor and __rational_adaptor have "pass through" serialization | |
2075 | support which requires the underlying backend to be serializable. | |
2076 | * Backends __cpp_int, __cpp_bin_float, __cpp_dec_float and __float128 have full support for Boost.Serialization. | |
2077 | ||
2078 | [endsect] [/section:serialization Boost Serialization] | |
2079 | ||
2080 | [section:limits Numeric Limits] | |
2081 | ||
2082 | Boost.Multiprecision tries hard to implement `std::numeric_limits` for all types | |
2083 | as far as possible and meaningful because experience with Boost.Math | |
2084 | has shown that this aids portability. | |
2085 | ||
2086 | The [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf C++ standard library] | |
2087 | defines `std::numeric_limits` in section 18.3.2. | |
2088 | ||
2089 | This in turn refers to the C standard | |
2090 | [@http://www.open-std.org/jtc1/sc22/wg11/docs/n507.pdf SC22/WG11 N507 DRAFT INTERNATIONAL ISO/IEC STANDARD | |
2091 | WD 10967-1] | |
2092 | Information technology Language independent arithmetic Part 1: Integer and floating-point arithmetic. | |
2093 | ||
2094 | That C Standard in turn refers to | |
2095 | ||
2096 | [@http://754r.ucbtest.org/standards/754.pdf IEEE754 IEEE Standard for Binary | |
2097 | Floating-Point Arithmetic] | |
2098 | ||
2099 | There is a useful summary at | |
2100 | [@http://www.cplusplus.com/reference/limits/numeric_limits/ C++ reference]. | |
2101 | ||
2102 | The chosen backend often determines how completely `std::numeric_limits` is available. | |
2103 | ||
2104 | Compiler options, processor type, and definition of macros or assembler instructions to control denormal numbers will alter | |
2105 | the values in the tables given below. | |
2106 | ||
2107 | [warning GMP's `mpf_t` does not have a concept of overflow: | |
2108 | operations that lead to overflow eventually run of out of resources | |
2109 | and terminate with stack overflow (often after several seconds).] | |
2110 | ||
2111 | [section:constants std::numeric_limits<> constants] | |
2112 | ||
2113 | [h4 is_specialized] | |
2114 | ||
2115 | `true` for all arithmetic types (integer, floating and fixed-point) | |
2116 | for which `std::numeric_limits<T>::numeric_limits` is specialized. | |
2117 | ||
2118 | A typical test is | |
2119 | ||
2120 | if (std::numeric_limits<T>::is_specialized == false) | |
2121 | { | |
2122 | std::cout << "type " << typeid(T).name() << " is not specialized for std::numeric_limits!" << std::endl; | |
2123 | // ... | |
2124 | } | |
2125 | ||
2126 | Typically `numeric_limits<T>::is_specialized` is `true` for all `T` where the compile-time constant | |
2127 | members of `numeric_limits` are indeed known at compile time, and don't vary at runtime. For example | |
2128 | floating-point types with runtime-variable precision such as `mpfr_float` have no `numeric_limits` | |
2129 | specialization as it would be impossible to define all the members at compile time. In contrast | |
2130 | the precision of a type such as `mpfr_float_50` is known at compile time, and so it ['does] have a | |
2131 | `numeric_limits` specialization. | |
2132 | ||
2133 | Note that not all the `std::numeric_limits` member constants and functions are meaningful for all user-defined types (UDT), | |
2134 | such as the decimal and binary multiprecision types provided here. More information on this is given in the sections below. | |
2135 | ||
2136 | [h4 infinity] | |
2137 | ||
2138 | For floating-point types, [infin] is defined wherever possible, | |
2139 | but clearly infinity is meaningless for __arbitrary_precision arithmetic backends, | |
2140 | and there is one floating-point type (GMP's `mpf_t`, see __mpf_float) which has no notion | |
2141 | of infinity or NaN at all. | |
2142 | ||
2143 | A typical test whether infinity is implemented is | |
2144 | ||
2145 | if(std::numeric_limits<T>::has_infinity) | |
2146 | { | |
2147 | std::cout << std::numeric_limits<T>::infinity() << std::endl; | |
2148 | } | |
2149 | ||
2150 | and using tests like this is strongly recommended to improve portability. | |
2151 | ||
2152 | If the backend is switched to a type that does not support infinity then, | |
2153 | without checks like this, there will be trouble. | |
2154 | ||
2155 | [h4 is_signed] | |
2156 | ||
2157 | `std::numeric_limits<T>::is_signed == true` if the type `T` is signed. | |
2158 | ||
2159 | For built-in binary types, the sign is held in a single bit, | |
2160 | but for other types (cpp_dec_float and cpp_bin_float) | |
2161 | it may be a separate storage element, usually `bool`. | |
2162 | ||
2163 | [h4 is_exact] | |
2164 | ||
2165 | `std::numeric_limits<T>::is_exact == true` if type T uses exact representations. | |
2166 | ||
2167 | This is defined as `true` for all integer types and `false` for floating-point types. | |
2168 | ||
2169 | [@http://stackoverflow.com/questions/14203654/stdnumeric-limitsis-exact-what-is-a-usable-definition A usable definition] | |
2170 | has been discussed. | |
2171 | ||
2172 | ISO/IEC 10967-1, Language independent arithmetic, noted by the C++ Standard defines | |
2173 | ||
2174 | A floating-point type F shall be a finite subset of [real]. | |
2175 | ||
2176 | The important practical distinction is that all integers (up to `max()`) can be stored exactly. | |
2177 | ||
2178 | [@http://en.wikipedia.org/wiki/Rational_number Rational] | |
2179 | types using two integer types are also exact. | |
2180 | ||
2181 | Floating-point types [*cannot store all real values] | |
2182 | (those in the set of [real]) [*exactly]. | |
2183 | For example, 0.5 can be stored exactly in a binary floating-point, but 0.1 cannot. | |
2184 | What is stored is the nearest representable real value, that is, rounded to nearest. | |
2185 | ||
2186 | Fixed-point types (usually decimal) are also defined as exact, in that they only | |
2187 | store a [*fixed precision], so half cents or pennies (or less) cannot be stored. | |
2188 | The results of computations are rounded up or down, | |
2189 | just like the result of integer division stored as an integer result. | |
2190 | ||
2191 | There are number of proposals to | |
2192 | [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3407.html | |
2193 | add Decimal floating-point Support to C++]. | |
2194 | ||
2195 | [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2849.pdf Decimal TR]. | |
2196 | ||
2197 | And also | |
2198 | [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html | |
2199 | C++ Binary Fixed-Point Arithmetic]. | |
2200 | ||
2201 | [h4 is_bounded] | |
2202 | ||
2203 | `std::numeric_limits<T>::is_bounded == true` if the set of values represented by the type `T` is finite. | |
2204 | ||
2205 | This is `true` for all built-in integer, fixed and floating-point types, | |
2206 | and most multi-precision types. | |
2207 | ||
2208 | It is only `false` for a few __arbitrary_precision types like `cpp_int`. | |
2209 | ||
2210 | Rational and fixed-exponent representations are exact but not integer. | |
2211 | ||
2212 | [h4 is_modulo] | |
2213 | ||
2214 | `std::numeric_limits<T>::is_modulo` is defined as `true` if adding two positive values of type T | |
2215 | can yield a result less than either value. | |
2216 | ||
2217 | `is_modulo == true` means that the type does not overflow, but, for example, | |
2218 | 'wraps around' to zero, when adding one to the `max()` value. | |
2219 | ||
2220 | For most built-in integer types, `std::numeric_limits<>::is_modulo` is `true`. | |
2221 | ||
2222 | `bool` is the only exception. | |
2223 | ||
2224 | The modulo behaviour is sometimes useful, | |
2225 | but also can be unexpected, and sometimes undesired, behaviour. | |
2226 | ||
2227 | Overflow of signed integers can be especially unexpected, | |
2228 | possibly causing change of sign. | |
2229 | ||
2230 | Boost.Multiprecision integer type `cpp_int` is not modulo | |
2231 | because as an __arbitrary_precision types, | |
2232 | it expands to hold any value that the machine resources permit. | |
2233 | ||
2234 | However fixed precision __cpp_int's may be modulo if they are unchecked | |
2235 | (i.e. they behave just like built in integers), but not if they are checked | |
2236 | (overflow causes an exception to be raised). | |
2237 | ||
2238 | Built-in and multi-precision floating-point types are normally not modulo. | |
2239 | ||
2240 | Where possible, overflow is to `std::numeric_limits<>::infinity()`, | |
2241 | provided `std::numeric_limits<>::has_infinity == true`. | |
2242 | ||
2243 | [h4 radix] | |
2244 | ||
2245 | Constant `std::numeric_limits<T>::radix` returns either 2 (for built-in and binary types) | |
2246 | or 10 (for decimal types). | |
2247 | ||
2248 | [h4 digits] | |
2249 | ||
2250 | The number of `radix` digits that be represented without change: | |
2251 | ||
2252 | * for integer types, the number of [*non-sign bits] in the significand. | |
2253 | * for floating types, the number of [*radix digits] in the significand. | |
2254 | ||
2255 | The values include any implicit bit, so for example, for the ubiquious | |
2256 | `double` using 64 bits | |
2257 | ([@http://en.wikipedia.org/wiki/Double_precision_floating-point_format IEEE binary64 ]), | |
2258 | `digits` == 53, even though there are only 52 actual bits of the significand stored in the representation. | |
2259 | The value of `digits` reflects the fact that there is one implicit bit which is always set to 1. | |
2260 | ||
2261 | The Boost.Multiprecision binary types do not use an implicit bit, so the | |
2262 | `digits` member reflects exactly how many bits of precision were requested: | |
2263 | ||
2264 | typedef number<cpp_bin_float<53, digit_base_2> > float64; | |
2265 | typedef number<cpp_bin_float<113, digit_base_2> > float128; | |
2266 | std::numeric_limits<float64>::digits == 53. | |
2267 | std::numeric_limits<float128>::digits == 113. | |
2268 | ||
2269 | For the most common case of `radix == 2`, | |
2270 | `std::numeric_limits<T>::digits` is the number of bits in the representation, | |
2271 | not counting any sign bit. | |
2272 | ||
2273 | For a decimal integer type, when `radix == 10`, it is the number of decimal digits. | |
2274 | ||
2275 | [h4 digits10] | |
2276 | ||
2277 | Constant `std::numeric_limits<T>::digits10` returns the number of | |
2278 | decimal digits that can be represented without change or loss. | |
2279 | ||
2280 | For example, `numeric_limits<unsigned char>::digits10` is 2. | |
2281 | ||
2282 | This somewhat inscrutable definition means that an `unsigned char` | |
2283 | can hold decimal values `0..99` | |
2284 | without loss of precision or accuracy, usually from truncation. | |
2285 | ||
2286 | Had the definition been 3 then that would imply it could hold 0..999, | |
2287 | but as we all know, an 8-bit `unsigned char` can only hold 0..255, | |
2288 | and an attempt to store 256 or more will involve loss or change. | |
2289 | ||
2290 | For bounded integers, it is thus [*one less] than number of decimal digits | |
2291 | you need to display the biggest integer `std::numeric_limits<T>::max()`. | |
2292 | This value can be used to predict the layout width required for | |
2293 | ||
2294 | [digits10_1] | |
2295 | ||
2296 | For example, `unsigned short` is often stored in 16 bits, | |
2297 | so the maximum value is 0xFFFF or 65535. | |
2298 | ||
2299 | [digits10_2] | |
2300 | ||
2301 | ||
2302 | For bounded floating-point types, | |
2303 | if we create a `double` with a value with `digits10` (usually 15) decimal digits, | |
2304 | `1e15` or `1000000000000000` : | |
2305 | ||
2306 | [digits10_3] | |
2307 | ||
2308 | and we can increment this value to `1000000000000001` | |
2309 | as expected and show the difference too. | |
2310 | ||
2311 | But if we try to repeat this with more than `digits10` digits, | |
2312 | ||
2313 | [digits10_4] | |
2314 | ||
2315 | then we find that when we add one it has no effect, | |
2316 | and display show that there is loss of precision. See | |
2317 | [@http://en.wikipedia.org/wiki/Loss_of_significance Loss of significance or cancellation error]. | |
2318 | ||
2319 | So `digits10` is the number of decimal digits [*guaranteed] to be correct. | |
2320 | ||
2321 | For example, 'round-tripping' for `double`: | |
2322 | ||
2323 | * If a decimal string with at most `digits10`( == 15) significant decimal digits | |
2324 | is converted to `double` and then converted back to the | |
2325 | same number of significant decimal digits, | |
2326 | then the final string will match the original 15 decimal digit string. | |
2327 | * If a `double` floating-point number is converted to a decimal string | |
2328 | with at least 17 decimal digits | |
2329 | and then converted back to `double`, | |
2330 | then the result will be binary identical to the original `double` value. | |
2331 | ||
2332 | For most purposes, you will much more likely want | |
2333 | `std::numeric_limits<>::max_digits10`, | |
2334 | the number of decimal digits that ensure that a change of one least significant bit (ULP) | |
2335 | produces a different decimal digits string. | |
2336 | ||
2337 | For the most common `double` floating-point type,`max_digits10` is `digits10+2`, | |
2338 | but you should use C++11 `max_digits10` | |
2339 | where possible (see [link boost_multiprecision.tut.limits.constants.max_digits10 below]). | |
2340 | ||
2341 | [h4:max_digits10 max_digits10] | |
2342 | ||
2343 | `std::numeric_limits<T>::max_digits10` was added for floating-point | |
2344 | because `digits10` decimal digits are insufficient to show | |
2345 | a least significant bit (ULP) change giving puzzling displays like | |
2346 | ||
2347 | 0.666666666666667 != 0.666666666666667 | |
2348 | ||
2349 | from failure to 'round-trip', for example: | |
2350 | ||
2351 | [max_digits10_2] | |
2352 | ||
2353 | If you wish to ensure that a change of one least significant bit (ULP) | |
2354 | produces a different decimal digits string, | |
2355 | then `max_digits10` is the precision to use. | |
2356 | ||
2357 | For example: | |
2358 | ||
2359 | [max_digits10_3] | |
2360 | ||
2361 | will display [pi] to the maximum possible precision using a `double`. | |
2362 | ||
2363 | [max_digits10_4] | |
2364 | ||
2365 | For integer types, `max_digits10` is implementation-dependent, | |
2366 | but is usually `digits10 + 2`. | |
2367 | This is the output field-width required for the maximum value of the type T | |
2368 | `std::numeric_limits<T>::max()` ['including a sign and a space]. | |
2369 | ||
2370 | So this will produce neat columns. | |
2371 | ||
2372 | std::cout << std::setw(std::numeric_limits<int>::max_digits10) ... | |
2373 | ||
2374 | The extra two or three least-significant digits are 'noisy' and may be junk, | |
2375 | but if you want to 'round-trip' - printing a value out as a decimal digit string and reading it back in - | |
2376 | (most commonly during serialization and de-serialization) | |
2377 | you must use `os.precision(std::numeric_limits<T>::max_digits10)`. | |
2378 | ||
2379 | [note For Microsoft Visual Studio 2010, | |
2380 | `std::numeric_limits<float>::max_digits10` is wrongly defined as 8. It should be 9. | |
2381 | ] | |
2382 | ||
2383 | [note For Microsoft Visual Studio before 2013, and default float format, | |
2384 | a small range of values approximately 0.0001 to 0.004, with exponent values of 3F2 to 3F6, | |
2385 | are wrongly input by one least significant bit, | |
2386 | probably every third value of significand. | |
2387 | ||
2388 | A workaround is using scientific or exponential format `<< std::scientific`. | |
2389 | ] | |
2390 | ||
2391 | [note BOOST_NO_CXX11_NUMERIC_LIMITS is a suitable feature-test macro to determine if | |
2392 | `std::numeric_limits<float>::max_digits10` is implemented on any platform. | |
2393 | ] [/note] | |
2394 | ||
2395 | If `max_digits10` is not available, you should use the | |
2396 | [@http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF Kahan formula for floating-point type T]. | |
2397 | ||
2398 | In C++, the equations for what Kahan (on page 4) describes as 'at least' and 'at most' are: | |
2399 | ||
2400 | static long double const log10Two = 0.30102999566398119521373889472449L; // log10(2.) | |
2401 | ||
2402 | static_cast<int>(floor((significand_digits - 1) * log10Two)); // == digits10 - 'at least' . | |
2403 | static_cast<int>(ceil(1 + significand_digits * log10Two)); // == max_digits10 - 'at most'. | |
2404 | ||
2405 | Unfortunately, these cannot be evaluated (at least by C++03) at [*compile-time]. | |
2406 | So the following expression is often used instead. | |
2407 | ||
2408 | max_digits10 = 2 + std::numeric_limits<T>::digits * 3010U/10000U; | |
2409 | ||
2410 | // == 2 + std::numeric_limits<T>::digits for double and 64-bit long double. | |
2411 | // == 3 + std::numeric_limits<T>::digits for float, 80-bit long-double and __float128. | |
2412 | ||
2413 | often the actual values are computed for the C limits macros: | |
2414 | ||
2415 | #define FLT_MAXDIG10 (2+FLT_MANT_DIG * 3010U/10000U) // 9 | |
2416 | #define DBL_MAXDIG10 (2+ (DBL_MANT_DIG * 3010U)/10000U) // 17 | |
2417 | #define LDBL_MAXDIG10 (2+ (LDBL_MANT_DIG * 3010U)/10000U) // 17 for MSVC, 18 for others. | |
2418 | ||
2419 | The factor 3010U/10000U is ['log[sub 10](2) = 0.3010] | |
2420 | that can be evaluated at compile-time using only `short unsigned int`s to be a desirable `const` or `constexpr` (and usually also `static`). | |
2421 | ||
2422 | Boost macros allow this to be done portably, see | |
2423 | [@http://www.boost.org/doc/libs/1_58_0/libs/config/doc/html/boost_config/boost_macro_reference.html BOOST_CONSTEXPR_OR_CONST or BOOST_STATIC_CONSTEXPR]. | |
2424 | ||
2425 | (See also | |
2426 | [@http://www.loria.fr/~zimmerma/mca/mca-cup-0.5.9.pdf Richard P. Brent and Paul Zimmerman, Modern Computer Arithmetic] | |
2427 | Equation 3.8 on page 116). | |
2428 | ||
2429 | [max_digits10_1] [/ example for using max_digits10] | |
2430 | ||
2431 | [h4 round_style] | |
2432 | ||
2433 | The rounding style determines how the result of floating-point operations | |
2434 | is treated when the result cannot be [*exactly represented] in the significand. | |
2435 | Various rounding modes may be provided: | |
2436 | ||
2437 | * round to nearest up or down (default for floating-point types). | |
2438 | * round up (toward positive infinity). | |
2439 | * round down (toward negative infinity). | |
2440 | * round toward zero (integer types). | |
2441 | * no rounding (if decimal radix). | |
2442 | * rounding mode is not determinable. | |
2443 | ||
2444 | For integer types, `std::numeric_limits<T>::round_style` is always towards zero, so | |
2445 | ||
2446 | std::numeric_limits<T>::round_style == std::round_to_zero; | |
2447 | ||
2448 | A decimal type, `cpp_dec_float` rounds in no particular direction, | |
2449 | which is to say it doesn't round at all. | |
2450 | And since there are several guard digits, | |
2451 | it's not really the same as truncation (round toward zero) either. | |
2452 | ||
2453 | For floating-point types, it is normal to round to nearest. | |
2454 | ||
2455 | std::numeric_limits<T>::round_style == std::round_to_nearest; | |
2456 | ||
2457 | See function `std::numeric_limits<T>::round_error` for the maximum error (in ULP) | |
2458 | that rounding can cause. | |
2459 | ||
2460 | [h4 has_denorm_loss] | |
2461 | ||
2462 | `true` if a loss of precision is detected as a | |
2463 | [@http://en.wikipedia.org/wiki/Denormalization denormalization] loss, | |
2464 | rather than an inexact result. | |
2465 | ||
2466 | Always `false` for integer types. | |
2467 | ||
2468 | `false` for all types which do not have `has_denorm` == `std::denorm_present`. | |
2469 | ||
2470 | [h4 denorm_style] | |
2471 | ||
2472 | [@http://en.wikipedia.org/wiki/Denormal_number Denormalized values] are | |
2473 | representations with a variable number of exponent bits that can permit | |
2474 | gradual underflow, so that, if type T is `double`. | |
2475 | ||
2476 | std::numeric_limits<T>::denorm_min() < std::numeric_limits<T>::min() | |
2477 | ||
2478 | A type may have any of the following `enum float_denorm_style` values: | |
2479 | ||
2480 | * `std::denorm_absent`, if it does not allow denormalized values. | |
2481 | (Always used for all integer and exact types). | |
2482 | * `std::denorm_present`, if the floating-point type allows denormalized values. | |
2483 | *`std::denorm_indeterminate`, if indeterminate at compile time. | |
2484 | ||
2485 | [h4 Tinyness before rounding] | |
2486 | ||
2487 | `bool std::numeric_limits<T>::tinyness_before` | |
2488 | ||
2489 | `true` if a type can determine that a value is too small | |
2490 | to be represent as a normalized value before rounding it. | |
2491 | ||
2492 | Generally true for `is_iec559` floating-point built-in types, | |
2493 | but false for integer types. | |
2494 | ||
2495 | Standard-compliant IEEE 754 floating-point implementations may detect the floating-point underflow at three predefined moments: | |
2496 | ||
2497 | # After computation of a result with absolute value smaller than | |
2498 | `std::numeric_limits<T>::min()`, | |
2499 | such implementation detects ['tinyness before rounding] (e.g. UltraSparc). | |
2500 | ||
2501 | # After rounding of the result to `std::numeric_limits<T>::digits` bits, | |
2502 | if the result is tiny, such implementation detects ['tinyness after rounding] | |
2503 | (e.g. SuperSparc). | |
2504 | ||
2505 | # If the conversion of the rounded tiny result to subnormal form | |
2506 | resulted in the loss of precision, such implementation detects ['denorm loss]. | |
2507 | ||
2508 | [endsect] [/section:constants std::numeric_limits<> Constants] | |
2509 | ||
2510 | [section:functions std::numeric_limits<> functions] | |
2511 | ||
2512 | [h4 max function] | |
2513 | ||
2514 | Function `std::numeric_limits<T>::max()` returns the largest finite value | |
2515 | that can be represented by the type T. If there is no such value (and | |
2516 | `numeric_limits<T>::bounded` is `false`) then returns `T()`. | |
2517 | ||
2518 | For built-in types there is usually a corresponding MACRO value TYPE_MAX, | |
2519 | where TYPE is CHAR, INT, FLOAT etc. | |
2520 | ||
2521 | Other types, including those provided by a typedef, | |
2522 | for example `INT64_T_MAX` for `int64_t`, may provide a macro definition. | |
2523 | ||
2524 | To cater for situations where no `numeric_limits` specialization is available | |
2525 | (for example because the precision of the type varies at runtime), | |
2526 | packaged versions of this (and other functions) are provided using | |
2527 | ||
2528 | #include <boost/math/tools/precision.hpp> | |
2529 | ||
2530 | T = boost::math::tools::max_value<T>(); | |
2531 | ||
2532 | Of course, these simply use `std::numeric_limits<T>::max()` if available, | |
2533 | but otherwise 'do something sensible'. | |
2534 | ||
2535 | [h4 lowest function] | |
2536 | ||
2537 | Since C++11: `std::numeric_limits<T>::lowest()` is | |
2538 | ||
2539 | * For integral types, the same as function `min()`. | |
2540 | * For floating-point types, generally the negative of `max()` | |
2541 | (but implementation-dependent). | |
2542 | ||
2543 | [digits10_5] | |
2544 | ||
2545 | [h4 min function] | |
2546 | ||
2547 | Function `std::numeric_limits<T>::min()` returns the minimum finite value | |
2548 | that can be represented by the type T. | |
2549 | ||
2550 | For built-in types there is usually a corresponding MACRO value TYPE_MIN, | |
2551 | where TYPE is CHAR, INT, FLOAT etc. | |
2552 | ||
2553 | Other types, including those provided by a typedef, | |
2554 | for example `INT64_T_MIN` for `int64_t`, may provide a macro definition. | |
2555 | ||
2556 | For floating-point types, | |
2557 | it is more fully defined as the ['minimum positive normalized value]. | |
2558 | ||
2559 | See `std::numeric_limits<T>::denorm_min()` for the smallest denormalized value, provided | |
2560 | ||
2561 | std::numeric_limits<T>::has_denorm == std::denorm_present | |
2562 | ||
2563 | ||
2564 | To cater for situations where no `numeric_limits` specialization is available | |
2565 | (for example because the precision of the type varies at runtime), | |
2566 | packaged versions of this (and other functions) are provided using | |
2567 | ||
2568 | #include <boost/math/tools/precision.hpp> | |
2569 | ||
2570 | T = boost::math::tools::min_value<T>(); | |
2571 | ||
2572 | Of course, these simply use `std::numeric_limits<T>::min()` if available. | |
2573 | ||
2574 | [h4 denorm_min function] | |
2575 | ||
2576 | Function `std::numeric_limits<T>::denorm_min()` | |
2577 | returns the smallest | |
2578 | [@http://en.wikipedia.org/wiki/Denormal_number denormalized value], | |
2579 | provided | |
2580 | ||
2581 | std::numeric_limits<T>::has_denorm == std::denorm_present | |
2582 | ||
2583 | [denorm_min_1] | |
2584 | ||
2585 | The exponent is effectively reduced from -308 to -324 | |
2586 | (though it remains encoded as zero and leading zeros appear in the significand, | |
2587 | thereby losing precision until the significand reaches zero). | |
2588 | ||
2589 | [h4 round_error] | |
2590 | ||
2591 | Function `std::numeric_limits<T>::round_error()` returns the maximum error | |
2592 | (in units of [@http://en.wikipedia.org/wiki/Unit_in_the_last_place ULP]) | |
2593 | that can be caused by any basic arithmetic operation. | |
2594 | ||
2595 | round_style == std::round_indeterminate; | |
2596 | ||
2597 | The rounding style is indeterminable at compile time. | |
2598 | ||
2599 | For floating-point types, when rounding is to nearest, | |
2600 | only half a bit is lost by rounding, and `round_error == 0.5`. | |
2601 | In contrast when rounding is towards zero, or plus/minus infinity, | |
2602 | we can loose up to one bit from rounding, and `round_error == 1`. | |
2603 | ||
2604 | For integer types, rounding always to zero, so at worst almost one bit can be rounded, | |
2605 | so `round_error == 1`. | |
2606 | ||
2607 | `round_error()` can be used with `std::numeric_limits<T>::epsilon()` to estimate | |
2608 | the maximum potential error caused by rounding. For typical floating-point types, | |
2609 | `round_error() = 1/2`, so half epsilon is the maximum potential error. | |
2610 | ||
2611 | [round_error_1] | |
2612 | ||
2613 | There are, of course, many occasions when much bigger loss of precision occurs, | |
2614 | for example, caused by | |
2615 | [@http://en.wikipedia.org/wiki/Loss_of_significance Loss of significance or cancellation error] | |
2616 | or very many iterations. | |
2617 | ||
2618 | [h4 epsilon] | |
2619 | ||
2620 | Function `std::numeric_limits<T>::epsilon()` is meaningful only for non-integral types. | |
2621 | ||
2622 | It returns the difference between `1.0` and the next value representable | |
2623 | by the floating-point type T. | |
2624 | So it is a one least-significant-bit change in this floating-point value. | |
2625 | ||
2626 | For `double` (`float_64t`) it is `2.2204460492503131e-016` | |
2627 | showing all possibly significant 17 decimal digits. | |
2628 | ||
2629 | [epsilon_1] | |
2630 | ||
2631 | We can explicitly increment by one bit using the function `boost::math::float_next()` | |
2632 | and the result is the same as adding `epsilon`. | |
2633 | ||
2634 | [epsilon_2] | |
2635 | ||
2636 | Adding any smaller value, like half `epsilon`, will have no effect on this value. | |
2637 | ||
2638 | [epsilon_3] | |
2639 | ||
2640 | So this cancellation error leaves the values equal, despite adding half `epsilon`. | |
2641 | ||
2642 | To achieve greater portability over platform and floating-point type, | |
2643 | Boost.Math and Boost.Multiprecion provide a package of functions that | |
2644 | 'do something sensible' if the standard `numeric_limits` is not available. | |
2645 | To use these `#include <boost/math/tools/precision.hpp>`. | |
2646 | ||
2647 | [epsilon_4] | |
2648 | ||
2649 | [h5 Tolerance for Floating-point Comparisons] | |
2650 | ||
2651 | `epsilon` is very useful to compute a tolerance when comparing floating-point values, | |
2652 | a much more difficult task than is commonly imagined. | |
2653 | ||
2654 | For more information you probably want (but still need) see | |
2655 | [@http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html What Every Computer Scientist Should Know About Floating-Point Arithmetic] | |
2656 | ||
2657 | The naive test comparing the absolute difference between two values and a tolerance | |
2658 | does not give useful results if the values are too large or too small. | |
2659 | ||
2660 | So Boost.Test uses an algorithm first devised by Knuth | |
2661 | for reliably checking if floating-point values are close enough. | |
2662 | ||
2663 | See Donald. E. Knuth. The art of computer programming (vol II). | |
2664 | Copyright 1998 Addison-Wesley Longman, Inc., 0-201-89684-2. | |
2665 | Addison-Wesley Professional; 3rd edition. | |
2666 | ||
2667 | See also: | |
2668 | ||
2669 | [@http://adtmag.com/articles/2000/03/15/comparing-floats-how-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been.aspx Alberto Squassia, Comparing floats] | |
2670 | ||
2671 | [@http://adtmag.com/articles/2000/03/16/comparing-floats-how-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been.aspx Alberto Squassia, Comparing floats code] | |
2672 | ||
2673 | [@boost:/libs/test/doc/html/utf/testing-tools/floating_point_comparison.html floating-point comparison]. | |
2674 | ||
2675 | [tolerance_1] | |
2676 | ||
2677 | used thus: | |
2678 | ||
2679 | BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance); | |
2680 | ||
2681 | (There is also a version using tolerance as a percentage rather than a fraction). | |
2682 | ||
2683 | [tolerance_2] | |
2684 | ||
2685 | [h4 Infinity - positive and negative] | |
2686 | ||
2687 | For floating-point types only, for which | |
2688 | `std::numeric_limits<T>::has_infinity == true`, | |
2689 | function `std::numeric_limits<T>::infinity()` | |
2690 | provides an implementation-defined representation for [infin]. | |
2691 | ||
2692 | The 'representation' is a particular bit pattern reserved for infinity. | |
2693 | For IEEE754 system (for which `std::numeric_limits<T>::is_iec559 == true`) | |
2694 | [@http://en.wikipedia.org/wiki/IEEE_754-1985#Positive_and_negative_infinity positive and negative infinity] | |
2695 | are assigned bit patterns for all defined floating-point types. | |
2696 | ||
2697 | Confusingly, the string resulting from outputting this representation, is also | |
2698 | implementation-defined. And the string that can be input to generate the representation is also implementation-defined. | |
2699 | ||
2700 | For example, the output is `1.#INF` on Microsoft systems, but `inf` on most *nix platforms. | |
2701 | ||
2702 | This implementation-defined-ness has hampered use of infinity (and NaNs) | |
2703 | but Boost.Math and Boost.Multiprecision work hard to provide a sensible representation | |
2704 | for [*all] floating-point types, not just the built-in types, | |
2705 | which with the use of suitable facets to define the input and output strings, makes it possible | |
2706 | to use these useful features portably and including Boost.Serialization. | |
2707 | ||
2708 | [h4 Not-A-Number NaN] | |
2709 | ||
2710 | [h5 Quiet_NaN] | |
2711 | ||
2712 | For floating-point types only, for which | |
2713 | `std::numeric_limits<T>::has_quiet_NaN == true`, | |
2714 | function `std::numeric_limits<T>::quiet_NaN()` | |
2715 | provides an implementation-defined representation for NaN. | |
2716 | ||
2717 | [@http://en.wikipedia.org/wiki/NaN NaNs] are values to indicate that the | |
2718 | result of an assignment or computation is meaningless. | |
2719 | A typical example is `0/0` but there are many others. | |
2720 | ||
2721 | NaNs may also be used, to represent missing values: for example, | |
2722 | these could, by convention, be ignored in calculations of statistics like means. | |
2723 | ||
2724 | Many of the problems with a representation for | |
2725 | [@http://en.wikipedia.org/wiki/NaN Not-A-Number] has hampered portable use, | |
2726 | similar to those with infinity. | |
2727 | ||
2728 | [nan_1] | |
2729 | ||
2730 | But using Boost.Math and suitable facets can permit portable use | |
2731 | of both NaNs and positive and negative infinity. | |
2732 | ||
2733 | [facet_1] | |
2734 | ||
2735 | [h5 Signaling NaN] | |
2736 | ||
2737 | For floating-point types only, for which | |
2738 | `std::numeric_limits<T>::has_signaling_NaN == true`, | |
2739 | function `std::numeric_limits<T>::signaling_NaN()` | |
2740 | provides an implementation-defined representation for NaN that causes a hardware trap. | |
2741 | It should be noted however, that at least one implementation of this function causes a hardware | |
2742 | trap to be triggered simply by calling `std::numeric_limits<T>::signaling_NaN()`, and not only | |
2743 | by using the value returned. | |
2744 | ||
2745 | [endsect] [/section:functions std::numeric_limits<> functions] | |
2746 | ||
2747 | [/ Tables of values for numeric_limits for various built-in and cpp_bin_float types] | |
2748 | [include numeric_limits_32_tables.qbk] | |
2749 | [/include numeric_limits_64_tables.qbk] | |
2750 | ||
2751 | [section:how_to_tell How to Determine the Kind of a Number From `std::numeric_limits`] | |
2752 | ||
2753 | Based on the information above, one can see that different kinds of numbers can be | |
2754 | differentiated based on the information stored in `std::numeric_limits`. This is | |
2755 | in addition to the traits class [link boost_multiprecision.ref.number.traits_class_support | |
2756 | number_category] provided by this library. | |
2757 | ||
2758 | [h4 Integer Types] | |
2759 | ||
2760 | For an integer type T, all of the following conditions hold: | |
2761 | ||
2762 | std::numeric_limits<T>::is_specialized == true | |
2763 | std::numeric_limits<T>::is_integer == true | |
2764 | std::numeric_limits<T>::is_exact == true | |
2765 | std::numeric_limits<T>::min_exponent == 0 | |
2766 | std::numeric_limits<T>::max_exponent == 0 | |
2767 | std::numeric_limits<T>::min_exponent10 == 0 | |
2768 | std::numeric_limits<T>::max_exponent10 == 0 | |
2769 | ||
2770 | In addition the type is /signed/ if: | |
2771 | ||
2772 | std::numeric_limits<T>::is_signed == true | |
2773 | ||
2774 | If the type is arbitrary precision then: | |
2775 | ||
2776 | std::numeric_limits<T>::is_bounded == false | |
2777 | ||
2778 | Otherwise the type is bounded, and returns a non zero value | |
2779 | from: | |
2780 | ||
2781 | std::numeric_limits<T>::max() | |
2782 | ||
2783 | and has: | |
2784 | ||
2785 | std::numeric_limits<T>::is_modulo == true | |
2786 | ||
2787 | if the type implements modulo arithmetic on overflow. | |
2788 | ||
2789 | [h4 Rational Types] | |
2790 | ||
2791 | Rational types are just like integers except that: | |
2792 | ||
2793 | std::numeric_limits<T>::is_integer == false | |
2794 | ||
2795 | [h4 Fixed Precision Types] | |
2796 | ||
2797 | There appears to be no way to tell these apart from rational types, unless they set: | |
2798 | ||
2799 | std::numeric_limits<T>::is_exact == false | |
2800 | ||
2801 | This is because these types are in essence a rational type with a fixed denominator. | |
2802 | ||
2803 | [h4 floating-point Types] | |
2804 | ||
2805 | For a floating-point type T, all of the following conditions hold: | |
2806 | ||
2807 | std::numeric_limits<T>::is_specialized == true | |
2808 | std::numeric_limits<T>::is_integer == false | |
2809 | std::numeric_limits<T>::is_exact == false | |
2810 | std::numeric_limits<T>::min_exponent != 0 | |
2811 | std::numeric_limits<T>::max_exponent != 0 | |
2812 | std::numeric_limits<T>::min_exponent10 != 0 | |
2813 | std::numeric_limits<T>::max_exponent10 != 0 | |
2814 | ||
2815 | In addition the type is /signed/ if: | |
2816 | ||
2817 | std::numeric_limits<T>::is_signed == true | |
2818 | ||
2819 | And the type may be decimal or binary depending on the value of: | |
2820 | ||
2821 | std::numeric_limits<T>::radix | |
2822 | ||
2823 | In general, there are no arbitrary precision floating-point types, and so: | |
2824 | ||
2825 | std::numeric_limits<T>::is_bounded == false | |
2826 | ||
2827 | [h4 Exact floating-point Types] | |
2828 | ||
2829 | Exact floating-point types are a [@http://en.wikipedia.org/wiki/Field_%28mathematics%29 field] | |
2830 | composed of an arbitrary precision integer scaled by an exponent. Such types | |
2831 | have no division operator and are the same as floating-point types except: | |
2832 | ||
2833 | std::numeric_limits<T>::is_exact == true | |
2834 | ||
2835 | [h4 Complex Numbers] | |
2836 | ||
2837 | For historical reasons, complex numbers do not specialize `std::numeric_limits`, instead you must | |
2838 | inspect `std::numeric_limits<T::value_type>`. | |
2839 | ||
2840 | [endsect] [/section:how_to_tell How to Determine the Kind of a Number From `std::numeric_limits`] | |
2841 | ||
2842 | ||
2843 | [endsect] [/section:limits Numeric Limits] | |
2844 | ||
2845 | ||
2846 | [section:input_output Input Output] | |
2847 | ||
2848 | ||
2849 | [h4 Loopback testing] | |
2850 | ||
2851 | ['Loopback] or ['round-tripping] refers to writing out a value as a decimal digit string using `std::iostream`, | |
2852 | usually to a `std::stringstream`, and then reading the string back in to another value, | |
2853 | and confirming that the two values are identical. A trivial example using `float` is: | |
2854 | ||
2855 | float write; // Value to round-trip. | |
2856 | std::stringstream ss; // Read and write std::stringstream. | |
2857 | ss.precision(std::numeric_limits<T>::max_digits10); // Ensure all potentially significant bits are output. | |
2858 | ss.flags(std::ios_base::fmtflags(std::ios_base::scientific)); // Use scientific format. | |
2859 | ss << write; // Output to string. | |
2860 | float read; // Expected. | |
2861 | ss >> read; // Read decimal digits string from stringstream. | |
2862 | BOOST_CHECK_EQUAL(write, read); // Should be the same. | |
2863 | ||
2864 | and this can be run in a loop for all possible values of a 32-bit float. | |
2865 | For other floating-point types `T`, including built-in `double`, | |
2866 | it takes far too long to test all values, | |
2867 | so a reasonable test strategy is to use a large number of random values. | |
2868 | ||
2869 | T write; | |
2870 | std::stringstream ss; | |
2871 | ss.precision(std::numeric_limits<T>::max_digits10); // Ensure all potentially significant bits are output. | |
2872 | ss.flags(f); // Changed from default iostream format flags if desired. | |
2873 | ss << write; // Output to stringstream. | |
2874 | ||
2875 | T read; | |
2876 | ss >> read; // Get read using operator>> from stringstream. | |
2877 | BOOST_CHECK_EQUAL(read, write); | |
2878 | ||
2879 | read = static_cast<T>(ss.str()); // Get read by converting from decimal digits string representation of write. | |
2880 | BOOST_CHECK_EQUAL(read, write); | |
2881 | ||
2882 | read = static_cast<T>(write.str(0, f)); // Get read using format specified when written. | |
2883 | BOOST_CHECK_EQUAL(read, write); | |
2884 | ||
2885 | ||
2886 | The test at | |
2887 | [@../../test/test_cpp_bin_float_io.cpp test_cpp_bin_float_io.cpp] | |
2888 | allows any floating-point type to be ['round_tripped] using a wide range of fairly random values. | |
2889 | It also includes tests compared a collection of | |
2890 | [@../../test/string_data.ipp stringdata] test cases in a file. | |
2891 | ||
2892 | [h4 Comparing with output using Built-in types] | |
2893 | ||
2894 | One can make some comparisons with the output of | |
2895 | ||
2896 | <number<cpp_bin_float<53, digit_count_2> > | |
2897 | ||
2898 | which has the same number of significant bits (53) as 64-bit double precision floating-point. | |
2899 | ||
2900 | However, although most outputs are identical, there are differences on some platforms | |
2901 | caused by the implementation-dependent behaviours allowed by the C99 specification | |
2902 | [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf C99 ISO/IEC 9899:TC2], | |
2903 | incorporated by C++. | |
2904 | ||
2905 | [:['"For e, E, f, F, g, and G conversions, if the number of significant decimal digits | |
2906 | is at most DECIMAL_DIG, then the result should be correctly rounded. | |
2907 | If the number of significant decimal digits is more than DECIMAL_DIG | |
2908 | but the source value is exactly representable with DECIMAL_DIG digits, | |
2909 | then the result should be an exact representation with trailing zeros. | |
2910 | Otherwise, the source value is bounded by two adjacent decimal strings L < U, | |
2911 | both having DECIMAL_DIG significant digits; | |
2912 | the value of the resultant decimal string D should satisfy L<= D <= U, | |
2913 | with the extra stipulation that the error should have a correct sign | |
2914 | for the current rounding direction."]] | |
2915 | ||
2916 | So not only is correct rounding for the full number of digits not required, | |
2917 | but even if the *optional* recommended practice is followed, | |
2918 | then the value of these last few digits is unspecified | |
2919 | as long as the value is within certain bounds. | |
2920 | ||
2921 | [note Do not expect the output from different platforms | |
2922 | to be [*identical], but `cpp_dec_float`, `cpp_bin_float` (and other backends) outputs should be | |
2923 | correctly rounded to the number of digits requested by the set precision and format.] | |
2924 | ||
2925 | ||
2926 | [h4 Macro BOOST_MP_MIN_EXPONENT_DIGITS] | |
2927 | ||
2928 | [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf C99 Standard] | |
2929 | for [/e and E] format specifiers, 7.19.6 Formatted input/output functions requires: | |
2930 | ||
2931 | \"The exponent always contains at least two digits, | |
2932 | and only as many more digits as necessary to represent the exponent.\" | |
2933 | ||
2934 | So to conform to the C99 standard (incorporated by C++) | |
2935 | ||
2936 | #define BOOST_MP_MIN_EXPONENT_DIGITS 2 | |
2937 | ||
2938 | Confusingly, Microsoft (and MinGW) do not conform to this standard and provide | |
2939 | [*at least three digits], for example `1e+001`. | |
2940 | So if you want the output to match that from | |
2941 | built-in floating-point types on compilers that use Microsofts runtime then use: | |
2942 | ||
2943 | #define BOOST_MP_MIN_EXPONENT_DIGITS 3 | |
2944 | ||
2945 | Also useful to get the minimum exponent field width is | |
2946 | ||
2947 | #define BOOST_MP_MIN_EXPONENT_DIGITS 1 | |
2948 | ||
2949 | producing a compact output like `2e+4`, | |
2950 | useful when conserving space is important. | |
2951 | ||
2952 | Larger values are also supported, for example, value 4 for `2e+0004` | |
2953 | which may be useful to ensure that columns line up. | |
2954 | ||
2955 | [endsect] [/section:input_output Input Output] | |
2956 | ||
2957 | [section:hash Hash Function Support] | |
2958 | ||
2959 | [hash1] | |
2960 | ||
2961 | [hash2] | |
2962 | ||
2963 | [hash3] | |
2964 | ||
2965 | [hash4] | |
2966 | ||
2967 | [endsect][/hash] | |
2968 | ||
2969 | ||
2970 | [endsect] | |
2971 | ||
2972 | [section:ref Reference] | |
2973 | ||
2974 | [section:number number] | |
2975 | ||
2976 | [h4 Synopsis] | |
2977 | ||
2978 | namespace boost{ namespace multiprecision{ | |
2979 | ||
2980 | enum expression_template_option { et_on = 1, et_off = 0 }; | |
2981 | ||
2982 | template <class Backend> struct expression_template_default | |
2983 | { static const expression_template_option value = et_on; }; | |
2984 | ||
2985 | template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value> | |
2986 | class number | |
2987 | { | |
2988 | number(); | |
2989 | number(see-below); | |
2990 | number& operator=(see-below); | |
2991 | number& assign(see-below); | |
2992 | ||
2993 | // Member operators | |
2994 | number& operator+=(const ``['see-below]``&); | |
2995 | number& operator-=(const ``['see-below]``&); | |
2996 | number& operator*=(const ``['see-below]``&); | |
2997 | number& operator/=(const ``['see-below]``&); | |
2998 | number& operator++(); | |
2999 | number& operator--(); | |
3000 | number operator++(int); | |
3001 | number operator--(int); | |
3002 | ||
3003 | number& operator%=(const ``['see-below]``&); | |
3004 | number& operator&=(const ``['see-below]``&); | |
3005 | number& operator|=(const ``['see-below]``&); | |
3006 | number& operator^=(const ``['see-below]``&); | |
3007 | number& operator<<=(const ``['integer-type]``&); | |
3008 | number& operator>>=(const ``['integer-type]``&); | |
3009 | ||
3010 | // Use in Boolean context: | |
3011 | operator ``['convertible-to-bool-type]``()const; | |
3012 | // swap: | |
3013 | void swap(number& other); | |
3014 | // Sign: | |
3015 | bool is_zero()const; | |
3016 | int sign()const; | |
3017 | // string conversion: | |
3018 | std::string str()const; | |
3019 | // Generic conversion mechanism | |
3020 | template <class T> | |
3021 | T convert_to()const; | |
3022 | template <class T> | |
3023 | explicit operator T ()const; | |
3024 | // precision control: | |
3025 | static unsigned default_precision(); | |
3026 | static void default_precision(unsigned digits10); | |
3027 | unsigned precision()const; | |
3028 | void precision(unsigned digits10); | |
3029 | // Comparison: | |
3030 | int compare(const number<Backend>& o)const; | |
3031 | template <class V> | |
3032 | typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type | |
3033 | compare(const V& o)const; | |
3034 | // Access to the underlying implementation: | |
3035 | Backend& backend(); | |
3036 | const Backend& backend()const; | |
3037 | }; | |
3038 | ||
3039 | // Non member operators: | |
3040 | ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&); | |
3041 | ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&); | |
3042 | ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&); | |
3043 | ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&); | |
3044 | ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&); | |
3045 | ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&); | |
3046 | // Integer only operations: | |
3047 | ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&); | |
3048 | ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&); | |
3049 | ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&); | |
3050 | ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&); | |
3051 | ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&); | |
3052 | ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&); | |
3053 | // Comparison operators: | |
3054 | bool operator==(const ``['see-below]``&, const ``['see-below]``&); | |
3055 | bool operator!=(const ``['see-below]``&, const ``['see-below]``&); | |
3056 | bool operator< (const ``['see-below]``&, const ``['see-below]``&); | |
3057 | bool operator> (const ``['see-below]``&, const ``['see-below]``&); | |
3058 | bool operator<=(const ``['see-below]``&, const ``['see-below]``&); | |
3059 | bool operator>=(const ``['see-below]``&, const ``['see-below]``&); | |
3060 | ||
3061 | // Swap: | |
3062 | template <class Backend, expression_template_option ExpressionTemplates> | |
3063 | void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b); | |
3064 | ||
3065 | // iostream support: | |
3066 | template <class Backend, expression_template_option ExpressionTemplates> | |
3067 | std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r); | |
3068 | std::ostream& operator << (std::ostream& os, const ``['unmentionable-expression-template-type]``& r); | |
3069 | template <class Backend, expression_template_option ExpressionTemplates> | |
3070 | std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r); | |
3071 | ||
3072 | // Arithmetic with a higher precision result: | |
3073 | template <class ResultType, class Source1 class Source2> | |
3074 | ResultType& add(ResultType& result, const Source1& a, const Source2& b); | |
3075 | template <class ResultType, class Source1 class Source2> | |
3076 | ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); | |
3077 | template <class ResultType, class Source1 class Source2> | |
3078 | ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); | |
3079 | ||
3080 | // min and max overloads: | |
3081 | ``['number]`` min (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3082 | ``['number]`` max (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3083 | ||
3084 | // C99 Non-member function standard library support: | |
3085 | ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&); | |
3086 | ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&); | |
3087 | ``['number]`` acosh (const ``['number-or-expression-template-type]``&); | |
3088 | ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&); | |
3089 | ``['number]`` asinh (const ``['number-or-expression-template-type]``&); | |
3090 | ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&); | |
3091 | ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3092 | ``['number]`` atanh (const ``['number-or-expression-template-type]``&); | |
3093 | ``['number]`` cbrt (const ``['number-or-expression-template-type]``&); | |
3094 | ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&); | |
3095 | ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3096 | ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&); | |
3097 | ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&); | |
3098 | ``['number]`` erf (const ``['number-or-expression-template-type]``&); | |
3099 | ``['number]`` erfc (const ``['number-or-expression-template-type]``&); | |
3100 | ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&); | |
3101 | ``['unmentionable-expression-template-type]`` exp2 (const ``['number-or-expression-template-type]``&); | |
3102 | ``['number]`` expm1 (const ``['number-or-expression-template-type]``&); | |
3103 | ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&); | |
3104 | ``['unmentionable-expression-template-type]`` fdim (const ``['number-or-expression-template-type]``&); | |
3105 | ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&); | |
3106 | ``['unmentionable-expression-template-type]`` fma (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3107 | ``['unmentionable-expression-template-type]`` fmin (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3108 | ``['unmentionable-expression-template-type]`` fmax (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3109 | ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3110 | ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``*); | |
3111 | ``['unmentionable-expression-template-type]`` hypot (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3112 | ``['integer-type]`` ilogb (const ``['number-or-expression-template-type]``&); | |
3113 | ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3114 | ``['number]`` lgamma (const ``['number-or-expression-template-type]``&); | |
3115 | long long llrint (const ``['number-or-expression-template-type]``&); | |
3116 | long long llround (const ``['number-or-expression-template-type]``&); | |
3117 | ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&); | |
3118 | ``['unmentionable-expression-template-type]`` log2 (const ``['number-or-expression-template-type]``&); | |
3119 | ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&); | |
3120 | ``['number]`` log1p (const ``['number-or-expression-template-type]``&); | |
3121 | ``['unmentionable-expression-template-type]`` logb (const ``['number-or-expression-template-type]``&); | |
3122 | long lrint (const ``['number-or-expression-template-type]``&); | |
3123 | long lround (const ``['number-or-expression-template-type]``&); | |
3124 | ``['unmentionable-expression-template-type]`` modf (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3125 | ``['unmentionable-expression-template-type]`` nearbyint (const ``['number-or-expression-template-type]``&); | |
3126 | ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3127 | ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3128 | ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3129 | ``['unmentionable-expression-template-type]`` remainder (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3130 | ``['unmentionable-expression-template-type]`` remquo (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, int*); | |
3131 | ``['unmentionable-expression-template-type]`` rint (const ``['number-or-expression-template-type]``&); | |
3132 | ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&); | |
3133 | ``['unmentionable-expression-template-type]`` scalbn (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3134 | ``['unmentionable-expression-template-type]`` scalbln (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3135 | ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&); | |
3136 | ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&); | |
3137 | ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&); | |
3138 | ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&); | |
3139 | ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&); | |
3140 | ``['number]`` tgamma (const ``['number-or-expression-template-type]``&); | |
3141 | ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&); | |
3142 | ||
3143 | int fpclassify (const ``['number-or-expression-template-type]``&); | |
3144 | bool isfinite (const ``['number-or-expression-template-type]``&); | |
3145 | bool isinf (const ``['number-or-expression-template-type]``&); | |
3146 | bool isnan (const ``['number-or-expression-template-type]``&); | |
3147 | bool isnormal (const ``['number-or-expression-template-type]``&); | |
3148 | int signbit (const ``['number-or-expression-template-type]``&); | |
3149 | ||
3150 | bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3151 | bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3152 | bool isless (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3153 | bool islessequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3154 | bool islessgreater(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3155 | bool isunordered(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3156 | // Misc other common C library functions: | |
3157 | ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&); | |
3158 | ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&); | |
3159 | ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&); | |
3160 | ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&); | |
3161 | ``['number]`` changesign(const ``['number-or-expression-template-type]``&); | |
3162 | ``['number]`` copysign(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3163 | ||
3164 | // Traits support: | |
3165 | template <class T> | |
3166 | struct component_type; | |
3167 | template <class T> | |
3168 | struct number_category; | |
3169 | template <class T> | |
3170 | struct is_number; | |
3171 | template <class T> | |
3172 | struct is_number_expression; | |
3173 | ||
3174 | // Integer specific functions: | |
3175 | ``['unmentionable-expression-template-type]`` gcd(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3176 | ``['unmentionable-expression-template-type]`` lcm(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3177 | ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``&, unsigned); | |
3178 | ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m); | |
3179 | ``['unmentionable-expression-template-type]`` sqrt(const ``['number-or-expression-template-type]``&); | |
3180 | template <class Backend, expression_template_option ExpressionTemplates> | |
3181 | number<Backend, EXpressionTemplates> sqrt(const ``['number-or-expression-template-type]``&, number<Backend, EXpressionTemplates>&); | |
3182 | template <class Backend, expression_template_option ExpressionTemplates> | |
3183 | void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y, | |
3184 | number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r); | |
3185 | template <class Integer> | |
3186 | Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val); | |
3187 | unsigned lsb(const ``['number-or-expression-template-type]``& x); | |
3188 | unsigned msb(const ``['number-or-expression-template-type]``& x); | |
3189 | template <class Backend, class ExpressionTemplates> | |
3190 | bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index); | |
3191 | template <class Backend, class ExpressionTemplates> | |
3192 | number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3193 | template <class Backend, class ExpressionTemplates> | |
3194 | number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3195 | template <class Backend, class ExpressionTemplates> | |
3196 | number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3197 | template <class Engine> | |
3198 | bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen); | |
3199 | bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials); | |
3200 | ||
3201 | // Rational number support: | |
3202 | typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); | |
3203 | typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); | |
3204 | ||
3205 | }} // namespaces | |
3206 | ||
3207 | namespace boost{ namespace math{ | |
3208 | ||
3209 | // Boost.Math interoperability functions: | |
3210 | int fpclassify (const ``['number-or-expression-template-type]``&, int); | |
3211 | bool isfinite (const ``['number-or-expression-template-type]``&, int); | |
3212 | bool isnan (const ``['number-or-expression-template-type]``&, int); | |
3213 | bool isinf (const ``['number-or-expression-template-type]``&, int); | |
3214 | bool isnormal (const ``['number-or-expression-template-type]``&, int); | |
3215 | ||
3216 | }} // namespaces | |
3217 | ||
3218 | // numeric_limits support: | |
3219 | namespace std{ | |
3220 | ||
3221 | template <class Backend, expression_template_option ExpressionTemplates> | |
3222 | struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> > | |
3223 | { | |
3224 | /* Usual members here */ | |
3225 | }; | |
3226 | ||
3227 | } | |
3228 | ||
3229 | [h4 Description] | |
3230 | ||
3231 | enum expression_template_option { et_on = 1, et_off = 0 }; | |
3232 | ||
3233 | This enumerated type is used to specify whether expression templates are turned on (et_on) or turned off (et_off). | |
3234 | ||
3235 | template <class Backend> struct expression_template_default | |
3236 | { static const expression_template_option value = et_on; }; | |
3237 | ||
3238 | This traits class specifies the default expression template option to be used with a particular Backend type. | |
3239 | It defaults to `et_on`. | |
3240 | ||
3241 | template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value> | |
3242 | class number; | |
3243 | ||
3244 | Class `number` has two template arguments: | |
3245 | ||
3246 | [variablelist | |
3247 | [[Backend][The actual arithmetic back-end that does all the work.]] | |
3248 | [[ExpressionTemplates][A Boolean value: when `et_on`, then expression templates are enabled, otherwise when set to `et_off` they are disabled. | |
3249 | The default for this parameter is computed via the traits class `expression_template_default` whose member `value` defaults to `et_on` unless | |
3250 | the traits class is specialized for a particular backend.]] | |
3251 | ] | |
3252 | ||
3253 | number(); | |
3254 | number(see-below); | |
3255 | number& operator=(see-below); | |
3256 | number& assign(see-below); | |
3257 | ||
3258 | Type `number` is default constructible, and both copy constructible and assignable from: | |
3259 | ||
3260 | * Itself. | |
3261 | * An expression template which is the result of one of the arithmetic operators. | |
3262 | * Any builtin arithmetic type, as long as the result would not be lossy (for example float to integer conversion). | |
3263 | * Any type that the Backend is implicitly constructible or assignable from. | |
3264 | * An rvalue reference to another `number`. Move-semantics are used for construction if the backend also | |
3265 | supports rvalue reference construction. In the case of assignment, move semantics are always supported | |
3266 | when the argument is an rvalue reference irrespective of the backend. | |
3267 | * Any type in the same family, as long as no loss of precision is involved. For example from `int128_t` to `int256_t`, | |
3268 | or `cpp_dec_float_50` to `cpp_dec_float_100`. | |
3269 | ||
3270 | Type `number` is explicitly constructible from: | |
3271 | ||
3272 | * Any type mentioned above. | |
3273 | * A `std::string` or any type which is convertible to `const char*`. | |
3274 | * Any arithmetic type (including those that would result in lossy conversions). | |
3275 | * Any type in the same family, including those that result in loss of precision. | |
3276 | * Any type that the Backend is explicitly constructible from. | |
3277 | * Any pair of types for which a generic interconversion exists: that is from integer to integer, integer | |
3278 | to rational, integer to float, rational to rational, rational to float, or float to float. | |
3279 | ||
3280 | The assign member function is available for any type for which an explicit converting constructor exists. | |
3281 | It is intended to be used where a temporary generated from an explicit assignment would be expensive, for example: | |
3282 | ||
3283 | mpfr_float_50 f50; | |
3284 | mpfr_float_100 f100; | |
3285 | ||
3286 | f50 = static_cast<mpfr_float_50>(f100); // explicit cast create a temporary | |
3287 | f50.assign(f100); // explicit call to assign create no temporary | |
3288 | ||
3289 | In addition, if the type has multiple components (for example rational or complex number types), then there is a | |
3290 | two argument constructor: | |
3291 | ||
3292 | number(arg1, arg2); | |
3293 | ||
3294 | Where the two args must either be arithmetic types, or types that are convertible to the two components of `this`. | |
3295 | ||
3296 | number& operator+=(const ``['see-below]``&); | |
3297 | number& operator-=(const ``['see-below]``&); | |
3298 | number& operator*=(const ``['see-below]``&); | |
3299 | number& operator/=(const ``['see-below]``&); | |
3300 | number& operator++(); | |
3301 | number& operator--(); | |
3302 | number operator++(int); | |
3303 | number operator--(int); | |
3304 | // Integer only operations: | |
3305 | number& operator%=(const ``['see-below]``&); | |
3306 | number& operator&=(const ``['see-below]``&); | |
3307 | number& operator|=(const ``['see-below]``&); | |
3308 | number& operator^=(const ``['see-below]``&); | |
3309 | number& operator<<=(const ``['integer-type]``&); | |
3310 | number& operator>>=(const ``['integer-type]``&); | |
3311 | ||
3312 | These operators all take their usual arithmetic meanings. | |
3313 | ||
3314 | The arguments to these operators is either: | |
3315 | ||
3316 | * Another `number<Backend, ExpressionTemplates>`. | |
3317 | * An expression template derived from `number<Backend>`. | |
3318 | * Any type implicitly convertible to `number<Backend, ExpressionTemplates>`, including some other instance of class `number`. | |
3319 | ||
3320 | For the left and right shift operations, the argument must be a builtin | |
3321 | integer type with a positive value (negative values result in a `std::runtime_error` being thrown). | |
3322 | ||
3323 | operator ``['convertible-to-bool-type]``()const; | |
3324 | ||
3325 | Returns an ['unmentionable-type] that is usable in Boolean contexts (this allows `number` to be used in any | |
3326 | Boolean context - if statements, conditional statements, or as an argument to a logical operator - without | |
3327 | type `number` being convertible to type `bool`. | |
3328 | ||
3329 | This operator also enables the use of `number` with any of the following operators: | |
3330 | `!`, `||`, `&&` and `?:`. | |
3331 | ||
3332 | void swap(number& other); | |
3333 | ||
3334 | Swaps `*this` with `other`. | |
3335 | ||
3336 | bool is_zero()const; | |
3337 | ||
3338 | Returns `true` is `*this` is zero, otherwise `false`. | |
3339 | ||
3340 | int sign()const; | |
3341 | ||
3342 | Returns a value less than zero if `*this` is negative, a value greater than zero if `*this` is positive, and zero | |
3343 | if `*this` is zero. | |
3344 | ||
3345 | std::string str(unsigned precision, bool scientific = true)const; | |
3346 | ||
3347 | Returns the number formatted as a string, with at least /precision/ digits, and in scientific format | |
3348 | if /scientific/ is true. | |
3349 | ||
3350 | template <class T> | |
3351 | T convert_to()const; | |
3352 | ||
3353 | template <class T> | |
3354 | explicit operator T ()const; | |
3355 | ||
3356 | Provides a generic conversion mechanism to convert `*this` to type `T`. Type `T` may be any arithmetic type. | |
3357 | Optionally other types may also be supported by specific `Backend` types. | |
3358 | ||
3359 | ||
3360 | static unsigned default_precision(); | |
3361 | static void default_precision(unsigned digits10); | |
3362 | unsigned precision()const; | |
3363 | void precision(unsigned digits10); | |
3364 | ||
3365 | These functions are only available if the Backend template parameter supports runtime changes to precision. They get and set | |
3366 | the default precision and the precision of `*this` respectively. | |
3367 | ||
3368 | int compare(const number<Backend, ExpressionTemplates>& o)const; | |
3369 | template <class V> | |
3370 | typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type | |
3371 | compare(const V& other)const; | |
3372 | ||
3373 | Returns: | |
3374 | ||
3375 | * A value less that 0 for `*this < other` | |
3376 | * A value greater that 0 for `*this > other` | |
3377 | * Zero for `*this == other` | |
3378 | ||
3379 | Backend& backend(); | |
3380 | const Backend& backend()const; | |
3381 | ||
3382 | Returns the underlying back-end instance used by `*this`. | |
3383 | ||
3384 | [h4 Non-member operators] | |
3385 | ||
3386 | // Non member operators: | |
3387 | ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&); | |
3388 | ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&); | |
3389 | ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&); | |
3390 | ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&); | |
3391 | ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&); | |
3392 | ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&); | |
3393 | // Integer only operations: | |
3394 | ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&); | |
3395 | ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&); | |
3396 | ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&); | |
3397 | ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&); | |
3398 | ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&); | |
3399 | ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&); | |
3400 | // Comparison operators: | |
3401 | bool operator==(const ``['see-below]``&, const ``['see-below]``&); | |
3402 | bool operator!=(const ``['see-below]``&, const ``['see-below]``&); | |
3403 | bool operator< (const ``['see-below]``&, const ``['see-below]``&); | |
3404 | bool operator> (const ``['see-below]``&, const ``['see-below]``&); | |
3405 | bool operator<=(const ``['see-below]``&, const ``['see-below]``&); | |
3406 | bool operator>=(const ``['see-below]``&, const ``['see-below]``&); | |
3407 | ||
3408 | These operators all take their usual arithmetic meanings. | |
3409 | ||
3410 | The arguments to these functions must contain at least one of the following: | |
3411 | ||
3412 | * A `number`. | |
3413 | * An expression template type derived from `number`. | |
3414 | * Any type for which `number` has an implicit constructor - for example a builtin arithmetic type. | |
3415 | ||
3416 | The return type of these operators is either: | |
3417 | ||
3418 | * An ['unmentionable-type] expression template type when `ExpressionTemplates` is `true`. | |
3419 | * Type `number<Backend, et_off>` when `ExpressionTemplates` is `false`. | |
3420 | * Type `bool` if the operator is a comparison operator. | |
3421 | ||
3422 | Finally note that the second argument to the left and right shift operations must be a builtin integer type, | |
3423 | and that the argument must be positive (negative arguments result in a `std::runtime_error` being thrown). | |
3424 | ||
3425 | [h4 swap] | |
3426 | ||
3427 | template <class Backend, ExpressionTemplates> | |
3428 | void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b); | |
3429 | ||
3430 | Swaps `a` and `b`. | |
3431 | ||
3432 | [h4 Iostream Support] | |
3433 | ||
3434 | template <class Backend, expression_template_option ExpressionTemplates> | |
3435 | std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r); | |
3436 | template <class Unspecified...> | |
3437 | std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r); | |
3438 | template <class Backend, expression_template_option ExpressionTemplates> | |
3439 | inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r) | |
3440 | ||
3441 | These operators provided formatted input-output operations on `number` types, and expression templates derived from them. | |
3442 | ||
3443 | It's down to the back-end type to actually implement string conversion. However, the back-ends provided with | |
3444 | this library support all of the iostream formatting flags, field width and precision settings. | |
3445 | ||
3446 | [h4 Arithmetic with a higher precision result] | |
3447 | ||
3448 | template <class ResultType, class Source1 class Source2> | |
3449 | ResultType& add(ResultType& result, const Source1& a, const Source2& b); | |
3450 | ||
3451 | template <class ResultType, class Source1 class Source2> | |
3452 | ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); | |
3453 | ||
3454 | template <class ResultType, class Source1 class Source2> | |
3455 | ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); | |
3456 | ||
3457 | These functions apply the named operator to the arguments ['a] and ['b] and store the | |
3458 | result in ['result], returning ['result]. In all cases they behave "as if" | |
3459 | arguments ['a] and ['b] were first promoted to type `ResultType` before applying the | |
3460 | operator, though particular backends may well avoid that step by way of an optimization. | |
3461 | ||
3462 | The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2` | |
3463 | may be either instances of class `number` or native integer types. The latter is an optimization | |
3464 | that allows arithmetic to be performed on native integer types producing an extended precision result. | |
3465 | ||
3466 | [h4 Non-member standard library function support] | |
3467 | ||
3468 | ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&); | |
3469 | ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&); | |
3470 | ``['number]`` acosh (const ``['number-or-expression-template-type]``&); | |
3471 | ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&); | |
3472 | ``['number]`` asinh (const ``['number-or-expression-template-type]``&); | |
3473 | ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&); | |
3474 | ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3475 | ``['number]`` atanh (const ``['number-or-expression-template-type]``&); | |
3476 | ``['number]`` cbrt (const ``['number-or-expression-template-type]``&); | |
3477 | ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&); | |
3478 | ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3479 | ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&); | |
3480 | ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&); | |
3481 | ``['number]`` erf (const ``['number-or-expression-template-type]``&); | |
3482 | ``['number]`` erfc (const ``['number-or-expression-template-type]``&); | |
3483 | ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&); | |
3484 | ``['unmentionable-expression-template-type]`` exp2 (const ``['number-or-expression-template-type]``&); | |
3485 | ``['number]`` expm1 (const ``['number-or-expression-template-type]``&); | |
3486 | ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&); | |
3487 | ``['unmentionable-expression-template-type]`` fdim (const ``['number-or-expression-template-type]``&); | |
3488 | ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&); | |
3489 | ``['unmentionable-expression-template-type]`` fma (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3490 | ``['unmentionable-expression-template-type]`` fmin (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3491 | ``['unmentionable-expression-template-type]`` fmax (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3492 | ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3493 | ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``*); | |
3494 | ``['unmentionable-expression-template-type]`` hypot (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3495 | ``['integer-type]`` ilogb (const ``['number-or-expression-template-type]``&); | |
3496 | ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3497 | ``['number]`` lgamma (const ``['number-or-expression-template-type]``&); | |
3498 | long long llrint (const ``['number-or-expression-template-type]``&); | |
3499 | long long llround (const ``['number-or-expression-template-type]``&); | |
3500 | ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&); | |
3501 | ``['unmentionable-expression-template-type]`` log2 (const ``['number-or-expression-template-type]``&); | |
3502 | ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&); | |
3503 | ``['number]`` log1p (const ``['number-or-expression-template-type]``&); | |
3504 | ``['unmentionable-expression-template-type]`` logb (const ``['number-or-expression-template-type]``&); | |
3505 | long lrint (const ``['number-or-expression-template-type]``&); | |
3506 | long lround (const ``['number-or-expression-template-type]``&); | |
3507 | ``['unmentionable-expression-template-type]`` modf (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3508 | ``['unmentionable-expression-template-type]`` nearbyint (const ``['number-or-expression-template-type]``&); | |
3509 | ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3510 | ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3511 | ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3512 | ``['unmentionable-expression-template-type]`` remainder (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3513 | ``['unmentionable-expression-template-type]`` remquo (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&, int*); | |
3514 | ``['unmentionable-expression-template-type]`` rint (const ``['number-or-expression-template-type]``&); | |
3515 | ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&); | |
3516 | ``['unmentionable-expression-template-type]`` scalbn (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3517 | ``['unmentionable-expression-template-type]`` scalbln (const ``['number-or-expression-template-type]``&, ``['integer-type]``); | |
3518 | ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&); | |
3519 | ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&); | |
3520 | ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&); | |
3521 | ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&); | |
3522 | ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&); | |
3523 | ``['number]`` tgamma (const ``['number-or-expression-template-type]``&); | |
3524 | ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&); | |
3525 | ||
3526 | int fpclassify (const ``['number-or-expression-template-type]``&); | |
3527 | bool isfinite (const ``['number-or-expression-template-type]``&); | |
3528 | bool isinf (const ``['number-or-expression-template-type]``&); | |
3529 | bool isnan (const ``['number-or-expression-template-type]``&); | |
3530 | bool isnormal (const ``['number-or-expression-template-type]``&); | |
3531 | int signbit (const ``['number-or-expression-template-type]``&); | |
3532 | ||
3533 | bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3534 | bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3535 | bool isless (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3536 | bool islessequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3537 | bool islessgreater(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3538 | bool isunordered(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3539 | ||
3540 | These functions all behave exactly as their standard library C++11 counterparts do: their argument is either an instance of `number` or | |
3541 | an expression template derived from it; If the argument is of type `number<Backend, et_off>` then that is also the return type, | |
3542 | otherwise the return type is an expression template unless otherwise stated. | |
3543 | ||
3544 | The integer type arguments to `ldexp`, `frexp`, `scalbn` and `ilogb` may be either type `int`, or the actual | |
3545 | type of the exponent of the number type. | |
3546 | ||
3547 | There are also some functions implemented for compatibility with the Boost.Math functions of the same name: | |
3548 | ||
3549 | ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&); | |
3550 | ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&); | |
3551 | ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&); | |
3552 | ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&); | |
3553 | ``['number]`` changesign(const ``['number-or-expression-template-type]``&); | |
3554 | ``['number]`` copysign(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
3555 | ||
3556 | All these functions are normally implemented by the Backend type. However, default versions are provided for Backend types that | |
3557 | don't have native support for these functions. Please note however, that this default support requires the precision of the type | |
3558 | 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 | |
3559 | used at variable precision. | |
3560 | ||
3561 | Also note that with the exception of `abs` that these functions can only be used with floating-point Backend types (if any other types | |
3562 | such as fixed precision or complex types are added to the library later, then these functions may be extended to support those number types). | |
3563 | ||
3564 | The precision of these functions is generally determined by the backend implementation. For example the precision | |
3565 | of these functions when used with __mpfr_float_backend is determined entirely by [mpfr]. When these functions use our own | |
3566 | implementations, the accuracy of the transcendental functions is generally a few epsilon. Note however, that the trigonometrical | |
3567 | functions incur the usual accuracy loss when reducing arguments by large multiples of [pi]. Also note that both __mpf_float | |
3568 | and __cpp_dec_float have a number of guard digits beyond their stated precision, so the error rates listed for these | |
3569 | are in some sense artificially low. | |
3570 | ||
3571 | The following table shows the error rates we observe for these functions with various backend types, functions not listed | |
3572 | here are exact (tested on Win32 with VC++10, MPFR-3.0.0, MPIR-2.1.1): | |
3573 | ||
3574 | [table | |
3575 | [[Function][mpfr_float_50][mpf_float_50][cpp_dec_float_50]] | |
3576 | [[sqrt][1eps][0eps][0eps]] | |
3577 | [[exp][1eps][0eps][0eps]] | |
3578 | [[log][1eps][0eps][0eps]] | |
3579 | [[log10][1eps][0eps][0eps]] | |
3580 | [[cos][700eps][0eps][0eps]] | |
3581 | [[sin][1eps][0eps][0eps]] | |
3582 | [[tan][0eps][0eps][0eps]] | |
3583 | [[acos][0eps][0eps][0eps]] | |
3584 | [[asin][0eps][0eps][0eps]] | |
3585 | [[atan][1eps][0eps][0eps]] | |
3586 | [[cosh][1045eps[footnote It's likely that the inherent error in the input values to our test cases are to blame here.]][0eps][0eps]] | |
3587 | [[sinh][2eps][0eps][0eps]] | |
3588 | [[tanh][1eps][0eps][0eps]] | |
3589 | [[pow][0eps][4eps][3eps]] | |
3590 | [[atan2][1eps][0eps][0eps]] | |
3591 | ] | |
3592 | [h4 Traits Class Support] | |
3593 | ||
3594 | template <class T> | |
3595 | struct component_type; | |
3596 | ||
3597 | If this is a type with multiple components (for example rational or complex types), then this trait has a single member | |
3598 | `type` that is the type of those components. | |
3599 | ||
3600 | template <class T> | |
3601 | struct number_category; | |
3602 | ||
3603 | A traits class that inherits from `mpl::int_<N>` where `N` is one of the enumerated values `number_kind_integer`, `number_kind_floating_point`, | |
3604 | `number_kind_rational`, `number_kind_fixed_point`, or `number_kind_unknown`. This traits class is specialized for any type that has | |
3605 | `std::numeric_limits` support as well as for classes in this library: which means it can be used for generic code that must work | |
3606 | with built in arithmetic types as well as multiprecision ones. | |
3607 | ||
3608 | template <class T> | |
3609 | struct is_number; | |
3610 | ||
3611 | A traits class that inherits from `mpl::true_` if T is an instance of `number<>`, otherwise from `mpl::false_`. | |
3612 | ||
3613 | template <class T> | |
3614 | struct is_number_expression; | |
3615 | ||
3616 | A traits class that inherits from `mpl::true_` if T is an expression template type derived from `number<>`, otherwise from `mpl::false_`. | |
3617 | ||
3618 | ||
3619 | ||
3620 | [h4 Integer functions] | |
3621 | ||
3622 | In addition to functioning with types from this library, these functions are also overloaded for built in integer | |
3623 | types if you include `<boost/multiprecision/integer.hpp>`. Further, when used with fixed precision types (whether | |
3624 | built in integers or multiprecision ones), the functions will promote to a wider type internally when the algorithm | |
3625 | requires it. Versions overloaded for built in integer types return that integer type rather than an expression | |
3626 | template. | |
3627 | ||
3628 | ``['unmentionable-expression-template-type]`` gcd(const ``['number-or-expression-template-type]``& a, const ``['number-or-expression-template-type]``& b); | |
3629 | ||
3630 | Returns the largest integer `x` that divides both `a` and `b`. | |
3631 | ||
3632 | ``['unmentionable-expression-template-type]`` lcm(const ``['number-or-expression-template-type]``& a, const ``['number-or-expression-template-type]``& b); | |
3633 | ||
3634 | Returns the smallest integer `x` that is divisible by both `a` and `b`. | |
3635 | ||
3636 | ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``& b, unsigned p); | |
3637 | ||
3638 | Returns ['b[super p]] as an expression template. Note that this function should be used with extreme care as the result can grow so | |
3639 | large as to take "effectively forever" to compute, or else simply run the host machine out of memory. This is the one function in | |
3640 | this category that is not overloaded for built in integer types, further, it's probably not a good idea to use it with | |
3641 | fixed precision `cpp_int`'s either. | |
3642 | ||
3643 | ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m); | |
3644 | ||
3645 | Returns ['b[super p] mod m] as an expression template. Fixed precision types are promoted internally to ensure accuracy. | |
3646 | ||
3647 | ``['unmentionable-expression-template-type]`` sqrt(const ``['number-or-expression-template-type]``& a); | |
3648 | ||
3649 | Returns the largest integer `x` such that `x * x < a`. | |
3650 | ||
3651 | template <class Backend, expression_template_option ExpressionTemplates> | |
3652 | number<Backend, EXpressionTemplates> sqrt(const ``['number-or-expression-template-type]``& a, number<Backend, EXpressionTemplates>& r); | |
3653 | ||
3654 | Returns the largest integer `x` such that `x * x < a`, and sets the remainder `r` such that `r = a - x * x`. | |
3655 | ||
3656 | template <class Backend, expression_template_option ExpressionTemplates> | |
3657 | void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y, | |
3658 | number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r); | |
3659 | ||
3660 | Divides x by y and returns both the quotient and remainder. After the call `q = x / y` and `r = x % y`. | |
3661 | ||
3662 | template <class Integer> | |
3663 | Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val); | |
3664 | ||
3665 | Returns the absolute value of `x % val`. | |
3666 | ||
3667 | unsigned lsb(const ``['number-or-expression-template-type]``& x); | |
3668 | ||
3669 | Returns the (zero-based) index of the least significant bit that is set to 1. | |
3670 | ||
3671 | Throws a `std::range_error` if the argument is <= 0. | |
3672 | ||
3673 | unsigned msb(const ``['number-or-expression-template-type]``& x); | |
3674 | ||
3675 | Returns the (zero-based) index of the most significant bit. | |
3676 | ||
3677 | Throws a `std::range_error` if the argument is <= 0. | |
3678 | ||
3679 | template <class Backend, class ExpressionTemplates> | |
3680 | bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index); | |
3681 | ||
3682 | Returns `true` if the bit at /index/ in /val/ is set. | |
3683 | ||
3684 | template <class Backend, class ExpressionTemplates> | |
3685 | number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3686 | ||
3687 | Sets the bit at /index/ in /val/, and returns /val/. | |
3688 | ||
3689 | template <class Backend, class ExpressionTemplates> | |
3690 | number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3691 | ||
3692 | Unsets the bit at /index/ in /val/, and returns /val/. | |
3693 | ||
3694 | template <class Backend, class ExpressionTemplates> | |
3695 | number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index); | |
3696 | ||
3697 | Flips the bit at /index/ in /val/, and returns /val/. | |
3698 | ||
3699 | template <class Engine> | |
3700 | bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen); | |
3701 | bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials); | |
3702 | ||
3703 | Tests to see if the number /n/ is probably prime - the test excludes the vast majority of composite numbers | |
3704 | by excluding small prime factors and performing a single Fermat test. Then performs /trials/ Miller-Rabin | |
3705 | tests. Returns `false` if /n/ is definitely composite, or `true` if /n/ is probably prime with the | |
3706 | probability of it being composite less than 0.25^trials. Fixed precision types are promoted internally | |
3707 | to ensure accuracy. | |
3708 | ||
3709 | [h4 Rational Number Functions] | |
3710 | ||
3711 | typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); | |
3712 | typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); | |
3713 | ||
3714 | These functions return the numerator and denominator of a rational number respectively. | |
3715 | ||
3716 | [h4 Boost.Math Interoperability Support] | |
3717 | ||
3718 | namespace boost{ namespace math{ | |
3719 | ||
3720 | int fpclassify (const ``['number-or-expression-template-type]``&, int); | |
3721 | bool isfinite (const ``['number-or-expression-template-type]``&, int); | |
3722 | bool isnan (const ``['number-or-expression-template-type]``&, int); | |
3723 | bool isinf (const ``['number-or-expression-template-type]``&, int); | |
3724 | bool isnormal (const ``['number-or-expression-template-type]``&, int); | |
3725 | ||
3726 | }} // namespaces | |
3727 | ||
3728 | These floating-point classification functions behave exactly as their Boost.Math equivalents. | |
3729 | ||
3730 | Other Boost.Math functions and templates may also be | |
3731 | specialized or overloaded to ensure interoperability. | |
3732 | ||
3733 | [h4 std::numeric_limits support] | |
3734 | ||
3735 | namespace std{ | |
3736 | ||
3737 | template <class Backend, ExpressionTemplates> | |
3738 | struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> > | |
3739 | { | |
3740 | /* Usual members here */ | |
3741 | }; | |
3742 | ||
3743 | } | |
3744 | ||
3745 | Class template `std::numeric_limits` is specialized for all instantiations of `number` whose precision is known at compile time, plus those | |
3746 | types whose precision is unlimited (though it is much less useful in those cases). It is not specialized for types | |
3747 | whose precision can vary at compile time (such as `mpf_float`). | |
3748 | ||
3749 | [endsect] | |
3750 | ||
3751 | [section:cpp_int_ref cpp_int] | |
3752 | ||
3753 | namespace boost{ namespace multiprecision{ | |
3754 | ||
3755 | typedef unspecified-type limb_type; | |
3756 | ||
3757 | enum cpp_integer_type { signed_magnitude, unsigned_magnitude }; | |
3758 | enum cpp_int_check_type { checked, unchecked }; | |
3759 | ||
3760 | template <unsigned MinDigits = 0, | |
3761 | unsigned MaxDits = 0, | |
3762 | cpp_integer_type SignType = signed_magnitude, | |
3763 | cpp_int_check_type Checked = unchecked, | |
3764 | class Allocator = std::allocator<limb_type> > | |
3765 | class cpp_int_backend; | |
3766 | // | |
3767 | // Expression templates default to et_off if there is no allocator: | |
3768 | // | |
3769 | template <unsigned MinDigits, unsigned MaxDigits, cpp_integer_type SignType, cpp_int_check_type Checked> | |
3770 | struct expression_template_default<cpp_int_backend<MinDigits, MaxDigits, SignType, Checked, void> > | |
3771 | { static const expression_template_option value = et_off; }; | |
3772 | ||
3773 | typedef number<cpp_int_backend<> > cpp_int; // arbitrary precision integer | |
3774 | typedef rational_adaptor<cpp_int_backend<> > cpp_rational_backend; | |
3775 | typedef number<cpp_rational_backend> cpp_rational; // arbitrary precision rational number | |
3776 | ||
3777 | // Fixed precision unsigned types: | |
3778 | typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> > uint128_t; | |
3779 | typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> > uint256_t; | |
3780 | typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> > uint512_t; | |
3781 | typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t; | |
3782 | ||
3783 | // Fixed precision signed types: | |
3784 | typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> > int128_t; | |
3785 | typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > int256_t; | |
3786 | typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> > int512_t; | |
3787 | typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> > int1024_t; | |
3788 | ||
3789 | // Over again, but with checking enabled this time: | |
3790 | typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_int; | |
3791 | typedef rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> > checked_cpp_rational_backend; | |
3792 | typedef number<checked_cpp_rational_backend> checked_cpp_rational; | |
3793 | ||
3794 | // Checked fixed precision unsigned types: | |
3795 | typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> > checked_uint128_t; | |
3796 | typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> > checked_uint256_t; | |
3797 | typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> > checked_uint512_t; | |
3798 | typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> > checked_uint1024_t; | |
3799 | ||
3800 | // Fixed precision signed types: | |
3801 | typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> > checked_int128_t; | |
3802 | typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> > checked_int256_t; | |
3803 | typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> > checked_int512_t; | |
3804 | typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> > checked_int1024_t; | |
3805 | ||
3806 | }} // namespaces | |
3807 | ||
3808 | Class template `cpp_int_backend` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3809 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3810 | to change. | |
3811 | ||
3812 | The template arguments are: | |
3813 | ||
3814 | [variablelist | |
3815 | [[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory | |
3816 | allocation. When zero, this field is determined automatically based on how many bits can be stored | |
3817 | in union with the dynamic storage header: setting a larger value may improve performance as larger integer | |
3818 | values will be stored internally before memory allocation is required.]] | |
3819 | [[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type. | |
3820 | When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic | |
3821 | memory allocation will ever be performed: in this situation the Allocator parameter should be set to | |
3822 | type `void`. Note that this parameter should not be used simply to prevent large memory | |
3823 | allocations, not only is that role better performed by the allocator, but fixed precision | |
3824 | integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]] | |
3825 | [[SignType][Determines whether the resulting type is signed or not. Note that for | |
3826 | [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types | |
3827 | this parameter must be `signed_magnitude`. For fixed precision | |
3828 | types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]] | |
3829 | [[Checked][This parameter has two values: `checked` or `unchecked`. See the [link boost_multiprecision.tut.ints.cpp_int tutorial] for more information.]] | |
3830 | [[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]] | |
3831 | ] | |
3832 | ||
3833 | The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`. | |
3834 | ||
3835 | More information on this type can be found in the [link boost_multiprecision.tut.ints.cpp_int tutorial]. | |
3836 | ||
3837 | [endsect] | |
3838 | ||
3839 | [section:gmp_int_ref gmp_int] | |
3840 | ||
3841 | namespace boost{ namespace multiprecision{ | |
3842 | ||
3843 | class gmp_int; | |
3844 | ||
3845 | typedef number<gmp_int > mpz_int; | |
3846 | ||
3847 | }} // namespaces | |
3848 | ||
3849 | Class template `gmp_int` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3850 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3851 | to change. | |
3852 | ||
3853 | The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`. | |
3854 | ||
3855 | More information on this type can be found in the [link boost_multiprecision.tut.ints.gmp_int tutorial]. | |
3856 | ||
3857 | [endsect] | |
3858 | ||
3859 | [section:tom_int_ref tom_int] | |
3860 | ||
3861 | namespace boost{ namespace multiprecision{ | |
3862 | ||
3863 | class tommath_int; | |
3864 | ||
3865 | typedef number<tommath_int > tom_int; | |
3866 | ||
3867 | }} // namespaces | |
3868 | ||
3869 | Class template `tommath_int` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3870 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3871 | to change. | |
3872 | ||
3873 | The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_integer>`. | |
3874 | ||
3875 | More information on this type can be found in the [link boost_multiprecision.tut.ints.tom_int tutorial]. | |
3876 | ||
3877 | [endsect] | |
3878 | ||
3879 | [section:mpf_ref gmp_float] | |
3880 | ||
3881 | namespace boost{ namespace multiprecision{ | |
3882 | ||
3883 | template <unsigned Digits10> | |
3884 | class gmp_float; | |
3885 | ||
3886 | typedef number<gmp_float<50> > mpf_float_50; | |
3887 | typedef number<gmp_float<100> > mpf_float_100; | |
3888 | typedef number<gmp_float<500> > mpf_float_500; | |
3889 | typedef number<gmp_float<1000> > mpf_float_1000; | |
3890 | typedef number<gmp_float<0> > mpf_float; | |
3891 | ||
3892 | }} // namespaces | |
3893 | ||
3894 | Class template `gmp_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3895 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3896 | to change. | |
3897 | ||
3898 | The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type | |
3899 | should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision` | |
3900 | and `number::precision`. Note that this type does not in any way change the GMP library's global state (for example | |
3901 | it does not change the default precision of the mpf_t data type), therefore you can safely mix this type with existing | |
3902 | code that uses GMP, and also mix `gmp_float`s of differing precision. | |
3903 | ||
3904 | The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_floating_point>`. | |
3905 | ||
3906 | More information on this type can be found in the [link boost_multiprecision.tut.floats.gmp_float tutorial]. | |
3907 | ||
3908 | [endsect] | |
3909 | ||
3910 | [section:mpfr_ref mpfr_float_backend] | |
3911 | ||
3912 | namespace boost{ namespace multiprecision{ | |
3913 | ||
3914 | template <unsigned Digits10> | |
3915 | class mpfr_float_backend; | |
3916 | ||
3917 | typedef number<mpfr_float_backend<50> > mpfr_float_50; | |
3918 | typedef number<mpfr_float_backend<100> > mpfr_float_100; | |
3919 | typedef number<mpfr_float_backend<500> > mpfr_float_500; | |
3920 | typedef number<mpfr_float_backend<1000> > mpfr_float_1000; | |
3921 | typedef number<mpfr_float_backend<0> > mpfr_float; | |
3922 | ||
3923 | }} // namespaces | |
3924 | ||
3925 | Class template `mpfr_float_backend` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3926 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3927 | to change. | |
3928 | ||
3929 | The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type | |
3930 | should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision` | |
3931 | and `number::precision`. Note that this type does not in any way change the GMP or MPFR library's global state (for example | |
3932 | it does not change the default precision of the mpfr_t data type), therefore you can safely mix this type with existing | |
3933 | code that uses GMP or MPFR, and also mix `mpfr_float_backend`s of differing precision. | |
3934 | ||
3935 | The type of `number_category<cpp_int<Args...> >::type` is `mpl::int_<number_kind_floating_point>`. | |
3936 | ||
3937 | More information on this type can be found in the [link boost_multiprecision.tut.floats.mpfr_float tutorial]. | |
3938 | ||
3939 | [endsect] | |
3940 | ||
3941 | [section:cpp_bin_float_ref cpp_bin_float] | |
3942 | ||
3943 | namespace boost{ namespace multiprecision{ | |
3944 | ||
3945 | enum digit_base_type | |
3946 | { | |
3947 | digit_base_2 = 2, | |
3948 | digit_base_10 = 10 | |
3949 | }; | |
3950 | ||
3951 | template <unsigned Digits, digit_base_type base = digit_base_10, class Allocator = void, class Exponent = int, ExponentMin = 0, ExponentMax = 0> | |
3952 | class cpp_bin_float; | |
3953 | ||
3954 | typedef number<cpp_bin_float<50> > cpp_bin_float_50; | |
3955 | typedef number<cpp_bin_float<100> > cpp_bin_float_100; | |
3956 | ||
3957 | typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single; | |
3958 | typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double; | |
3959 | typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended; | |
3960 | typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad; | |
3961 | ||
3962 | }} // namespaces | |
3963 | ||
3964 | Class template `cpp_bin_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
3965 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
3966 | to change. | |
3967 | ||
3968 | The class takes six template parameters: | |
3969 | ||
3970 | [variablelist | |
3971 | [[Digits][The number of digits precision the type | |
3972 | should support. This is normally expressed as base-10 digits, but that can be changed via the second template parameter.]] | |
3973 | [[base][An enumerated value (either `digit_base_10` or `digit_base_2`) that indicates whether `Digits` is base-10 or base-2]] | |
3974 | [[Allocator][The allocator used: defaults to type `void`, meaning all storage is within the class, and no dynamic | |
3975 | allocation is performed, but can be set to a standard library allocator if dynamic allocation makes more sense.]] | |
3976 | [[Exponent][A signed integer type to use as the type of the exponent - defaults to `int`.]] | |
3977 | [[ExponentMin][The smallest (most negative) permitted exponent, defaults to zero, meaning "define as small as possible | |
3978 | given the limitations of the type and our internal requirements".]] | |
3979 | [[ExponentMax][The largest (most positive) permitted exponent, defaults to zero, meaning "define as large as possible | |
3980 | given the limitations of the type and our internal requirements".]] | |
3981 | ] | |
3982 | ||
3983 | The type of `number_category<cpp_bin_float<Args...> >::type` is `mpl::int_<number_kind_floating_point>`. | |
3984 | ||
3985 | More information on this type can be found in the [link boost_multiprecision.tut.floats.cpp_bin_float tutorial]. | |
3986 | ||
3987 | [h4 Implementation Notes] | |
3988 | ||
3989 | Internally, an N-bit `cpp_bin_float` is represented as an N-bit unsigned integer along with an exponent and a sign. | |
3990 | The integer part is normalized so that it's most significant bit is always 1. The decimal point is assumed to be | |
3991 | directly after the most significant bit of the integer part. The special values zero, infinity and NaN all have | |
3992 | the integer part set to zero, and the exponent to one of 3 special values above the maximum permitted exponent. | |
3993 | ||
3994 | Multiplication is trivial: multiply the two N-bit integer mantissa's to obtain a 2N-bit number, then round and | |
3995 | adjust the sign and exponent. | |
3996 | ||
3997 | Addition and subtraction proceed similarly - if the exponents are such that there is overlap between the two | |
3998 | values, then left shift the larger value to produce a number with between N and 2N bits, then perform integer | |
3999 | addition or subtraction, round, and adjust the exponent. | |
4000 | ||
4001 | Division proceeds as follows: first scale the numerator by some power of 2 so that integer division will | |
4002 | produce either an N-bit or N+1 bit result plus a remainder. If we get an N bit result then the size of | |
4003 | twice the remainder compared to the denominator gives us the rounding direction. Otherwise we have one extra bit | |
4004 | in the result which we can use to determine rounding (in this case ties occur only if the remainder is zero and | |
4005 | the extra bit is a 1). | |
4006 | ||
4007 | Square root uses integer square root in a manner analogous to division. | |
4008 | ||
4009 | Decimal string to binary conversion proceeds as follows: first parse the digits to | |
4010 | produce an integer multiplied by a decimal exponent. Note that we stop parsing digits | |
4011 | once we have parsed as many as can possibly effect the result - this stops the integer | |
4012 | part growing too large when there are a very large number of input digits provided. | |
4013 | At this stage if the decimal exponent is positive then the result is an integer and we | |
4014 | can in principle simply multiply by 10^N to get an exact integer result. In practice | |
4015 | however, that could produce some very large integers. We also need to be able to divide | |
4016 | by 10^N in the event that the exponent is negative. Therefore calculation of the 10^N | |
4017 | values plus the multiplication or division are performed using limited precision | |
4018 | integer arithmetic, plus an exponent, and a track of the accumulated error. At the end of | |
4019 | the calculation we will either be able to round unambiguously, or the error will be such | |
4020 | that we can't tell which way to round. In the latter case we simply up the precision and try | |
4021 | again until we have an unambiguously rounded result. | |
4022 | ||
4023 | Binary to decimal conversion proceeds very similarly to the above, our aim is to calculate | |
4024 | `mantissa * 2^shift * 10^E` where `E` is the decimal exponent and `shift` is calculated | |
4025 | so that the result is an N bit integer assuming we want N digits printed in the result. | |
4026 | As before we use limited precision arithmetic to calculate the result and up the | |
4027 | precision as necessary until the result is unambiguously correctly rounded. In addition | |
4028 | our initial calculation of the decimal exponent may be out by 1, so we have to correct | |
4029 | that and loop as well in the that case. | |
4030 | ||
4031 | [endsect] | |
4032 | ||
4033 | [section:cpp_dec_ref cpp_dec_float] | |
4034 | ||
4035 | namespace boost{ namespace multiprecision{ | |
4036 | ||
4037 | template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void> | |
4038 | class cpp_dec_float; | |
4039 | ||
4040 | typedef number<cpp_dec_float<50> > cpp_dec_float_50; | |
4041 | typedef number<cpp_dec_float<100> > cpp_dec_float_100; | |
4042 | ||
4043 | }} // namespaces | |
4044 | ||
4045 | Class template `cpp_dec_float` fulfils all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. | |
4046 | Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject | |
4047 | to change. | |
4048 | ||
4049 | The class takes three template parameters: | |
4050 | ||
4051 | [variablelist | |
4052 | [[Digits10][The number of decimal digits precision the type | |
4053 | should support. Note that this type does not normally perform any dynamic memory allocation, and as a result the `Digits10` | |
4054 | template argument should not be set too high or the class's size will grow unreasonably large.]] | |
4055 | [[ExponentType][A signed integer type that represents the exponent of the number]] | |
4056 | [[Allocator][The allocator used: defaults to type `void`, meaning all storage is within the class, and no dynamic | |
4057 | allocation is performed, but can be set to a standard library allocator if dynamic allocation makes more sense.]] | |
4058 | ] | |
4059 | ||
4060 | The type of `number_category<cpp_dec_float<Args...> >::type` is `mpl::int_<number_kind_floating_point>`. | |
4061 | ||
4062 | More information on this type can be found in the [link boost_multiprecision.tut.floats.cpp_dec_float tutorial]. | |
4063 | ||
4064 | [endsect] | |
4065 | ||
4066 | [section:internals Internal Support Code] | |
4067 | ||
4068 | There are some traits classes which authors of new backends should be aware of: | |
4069 | ||
4070 | namespace boost{ namespace multiprecision{ namespace detail{ | |
4071 | ||
4072 | template<typename From, typename To> | |
4073 | struct is_explicitly_convertible; | |
4074 | ||
4075 | }}} | |
4076 | ||
4077 | Inherits from `boost::integral_constant<bool,true>` if type `From` has an explicit conversion from `To`. | |
4078 | ||
4079 | For compilers that support C++11 SFINAE-expressions this trait should "just work". Otherwise it inherits | |
4080 | from `boost::is_convertible<From, To>::type`, and will need to be specialised for Backends that have | |
4081 | constructors marked as `explicit`. | |
4082 | ||
4083 | template <class From, class To> | |
4084 | struct is_lossy_conversion | |
4085 | { | |
4086 | static const bool value = see below; | |
4087 | }; | |
4088 | ||
4089 | Member `value` is true if the conversion from `From` to `To` would result in a loss of precision, and `false` otherwise. | |
4090 | ||
4091 | The default version of this trait simply checks whether the ['kind] of conversion (for example from a floating-point to an integer type) | |
4092 | is inherently lossy. Note that if either of the types `From` or `To` are of an unknown number category (because `number_category` is not | |
4093 | specialised for that type) then this trait will be `true`. | |
4094 | ||
4095 | template<typename From, typename To> | |
4096 | struct is_restricted_conversion | |
4097 | { | |
4098 | static const bool value = see below; | |
4099 | }; | |
4100 | ||
4101 | Member `value` is `true` if `From` is only explicitly convertible to `To` and not implicitly convertible, or | |
4102 | if `is_lossy_conversion<From, To>::value` is `true`. Otherwise `false`. | |
4103 | ||
4104 | Note that while this trait is the ultimate arbiter of which constructors are marked as `explicit` in class `number`, | |
4105 | authors of backend types should generally specialise one of the traits above, rather than this one directly. | |
4106 | ||
4107 | template <class T> | |
4108 | is_signed_number; | |
4109 | template <class T> | |
4110 | is_unsigned_number; | |
4111 | ||
4112 | These two traits inherit from either `mpl::true_` or `mpl::false_`, by default types are assumed to be signed unless | |
4113 | `is_unsigned_number` is specialized for that type. | |
4114 | ||
4115 | [endsect] | |
4116 | ||
4117 | [section:backendconc Backend Requirements] | |
4118 | ||
4119 | The requirements on the `Backend` template argument to `number` are split up into | |
4120 | sections: compulsory and optional. | |
4121 | ||
4122 | Compulsory requirements have no default implementation in the library, therefore if the feature | |
4123 | they implement is to be supported at all, then they must be implemented by the backend. | |
4124 | ||
4125 | Optional requirements have default implementations that are called if the backend doesn't provide | |
4126 | it's own. Typically the backend will implement these to improve performance. | |
4127 | ||
4128 | In the following tables, type B is the `Backend` template argument to `number`, `b` and `b2` are | |
4129 | a variables of type B, `pb` is a variable of type B*, `cb`, `cb2` and `cb3` are constant variables of type `const B`, | |
4130 | `rb` is a variable of type `B&&`, `a` and `a2` are variables of Arithmetic type, | |
4131 | `s` is a variable of type `const char*`, `ui` is a variable of type `unsigned`, `bb` is a variable of type `bool`, | |
4132 | `pa` is a variable of type pointer-to-arithmetic-type, `exp` is a variable of type `B::exp_type`, | |
4133 | `pexp` is a variable of type `B::exp_type*`, `i` is a variable of type `int`, `pi` pointer to a variable of type `int`, | |
4134 | B2 is another type that meets these requirements, b2 is a variable of type B2, `ss` is variable of type `std::streamsize` | |
4135 | and `ff` is a variable of type `std::ios_base::fmtflags`. | |
4136 | ||
4137 | [table Compulsory Requirements on the Backend type. | |
4138 | [[Expression][Return Type][Comments][Throws]] | |
4139 | [[`B::signed_types`][`mpl::list<type-list>`][A list of signed integral types that can be assigned to type B. The types shall be | |
4140 | listed in order of size, smallest first, and shall terminate in the type that is `std::intmax_t`.][[space]]] | |
4141 | [[`B::unsigned_types`][`mpl::list<type-list>`][A list of unsigned integral types that can be assigned to type B. The types shall be | |
4142 | listed in order of size, smallest first, and shall terminate in the type that is `std::uintmax_t`.][[space]]] | |
4143 | [[`B::float_types`][`mpl::list<type-list>`][A list of floating-point types that can be assigned to type B.The types shall be | |
4144 | listed in order of size, smallest first, and shall terminate in type `long double`.][[space]]] | |
4145 | [[`B::exponent_type`][A signed integral type.][The type of the exponent of type B. This type is required only for floating-point types.][[space]]] | |
4146 | [[`B()`][ ][Default constructor.][[space]]] | |
4147 | [[`B(cb)`][ ][Copy Constructor.][[space]]] | |
4148 | [[`b = b`][`B&`][Assignment operator.][[space]]] | |
4149 | [[`b = a`][`B&`][Assignment from an Arithmetic type. The type of `a` shall be listed in one of the type lists | |
4150 | `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] | |
4151 | [[`b = s`][`B&`][Assignment from a string.][Throws a `std::runtime_error` if the string could not be interpreted as a valid number.]] | |
4152 | [[`b.swap(b)`][`void`][Swaps the contents of its arguments.][`noexcept`]] | |
4153 | [[`cb.str(ss, ff)`][`std::string`][Returns the string representation of `b` with `ss` digits and formatted according to the flags set in `ff`. | |
4154 | If `ss` is zero, then returns as many digits as are required to reconstruct the original value.][[space]]] | |
4155 | [[`b.negate()`][`void`][Negates `b`.][[space]]] | |
4156 | [[`cb.compare(cb2)`][`int`][Compares `cb` and `cb2`, returns a value less than zero if `cb < cb2`, a value greater than zero if `cb > cb2` and zero | |
4157 | if `cb == cb2`.][`noexcept`]] | |
4158 | [[`cb.compare(a)`][`int`][Compares `cb` and `a`, returns a value less than zero if `cb < a`, a value greater than zero if `cb > a` and zero | |
4159 | if `cb == a`. The type of `a` shall be listed in one of the type lists | |
4160 | `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] | |
4161 | [[`eval_add(b, cb)`][`void`][Adds `cb` to `b`.][[space]]] | |
4162 | [[`eval_subtract(b, cb)`][`void`][Subtracts `cb` from `b`.][[space]]] | |
4163 | [[`eval_multiply(b, cb)`][`void`][Multiplies `b` by `cb`.][[space]]] | |
4164 | [[`eval_divide(b, cb)`][`void`][Divides `b` by `cb`.] | |
4165 | [`std::overflow_error` if cb has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]] | |
4166 | [[`eval_modulus(b, cb)`][`void`][Computes `b %= cb`, only required when `B` is an integer type.] | |
4167 | [`std::overflow_error` if cb has the value zero.]] | |
4168 | [[`eval_bitwise_and(b, cb)`][`void`][Computes `b &= cb`, only required when `B` is an integer type.][[space]]] | |
4169 | [[`eval_bitwise_or(b, cb)`][`void`][Computes `b |= cb`, only required when `B` is an integer type.][[space]]] | |
4170 | [[`eval_bitwise_xor(b, cb)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type.][[space]]] | |
4171 | [[`eval_complement(b, cb)`][`void`][Computes the ones-complement of `cb` and stores the result in `b`, only required when `B` is an integer type.][[space]]] | |
4172 | [[`eval_left_shift(b, ui)`][`void`][Computes `b <<= ui`, only required when `B` is an integer type.][[space]]] | |
4173 | [[`eval_right_shift(b, ui)`][`void`][Computes `b >>= ui`, only required when `B` is an integer type.][[space]]] | |
4174 | [[`eval_convert_to(pa, cb)`][`void`][Converts `cb` to the type of `*pa` and store the result in `*pa`. Type `B` shall support | |
4175 | conversion to at least types `std::intmax_t`, `std::uintmax_t` and `long long`. | |
4176 | Conversion to other arithmetic types can then be synthesised using other operations. | |
4177 | Conversions to other types are entirely optional.][[space]]] | |
4178 | [[`eval_frexp(b, cb, pexp)`][`void`][Stores values in `b` and `*pexp` such that the value of `cb` is b * 2[super *pexp], only required when `B` is a floating-point type.][[space]]] | |
4179 | [[`eval_ldexp(b, cb, exp)`][`void`][Stores a value in `b` that is cb * 2[super exp], only required when `B` is a floating-point type.][[space]]] | |
4180 | [[`eval_frexp(b, cb, pi)`][`void`][Stores values in `b` and `*pi` such that the value of `cb` is b * 2[super *pi], only required when `B` is a floating-point type.] | |
4181 | [`std::runtime_error` if the exponent of cb is too large to be stored in an `int`.]] | |
4182 | [[`eval_ldexp(b, cb, i)`][`void`][Stores a value in `b` that is cb * 2[super i], only required when `B` is a floating-point type.][[space]]] | |
4183 | [[`eval_floor(b, cb)`][`void`][Stores the floor of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] | |
4184 | [[`eval_ceil(b, cb)`][`void`][Stores the ceiling of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] | |
4185 | [[`eval_sqrt(b, cb)`][`void`][Stores the square root of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] | |
4186 | [[`boost::multiprecision::number_category<B>::type`][`mpl::int_<N>`][`N` is one of the values `number_kind_integer`, `number_kind_floating_point`, `number_kind_rational` or `number_kind_fixed_point`. | |
4187 | Defaults to `number_kind_floating_point`.][[space]]] | |
4188 | ] | |
4189 | ||
4190 | [table Optional Requirements on the Backend Type | |
4191 | [[Expression][Returns][Comments][Throws]] | |
4192 | ||
4193 | [[['Construct and assign:]]] | |
4194 | [[`B(rb)`][`B`][Move constructor. Afterwards variable `rb` shall be in sane state, albeit with unspecified value. | |
4195 | Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]] | |
4196 | [[`b = rb`][`B&`][Move-assign. Afterwards variable `rb` shall be in sane state, albeit with unspecified value. | |
4197 | Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]] | |
4198 | [[`B(a)`][`B`][Direct construction from an arithmetic type. The type of `a` shall be listed in one of the type lists | |
4199 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4200 | When not provided, this operation is simulated using default-construction followed by assignment.][[space]]] | |
4201 | [[`B(b2)`][`B`][Copy constructor from a different back-end type. When not provided, a generic interconversion routine is used. | |
4202 | This constructor may be `explicit` if the corresponding frontend constructor should also be `explicit`.][[space]]] | |
4203 | [[`b = b2`][`b&`][Assignment operator from a different back-end type. When not provided, a generic interconversion routine is used.][[space]]] | |
4204 | [[`assign_components(b, a, a)`][`void`][Assigns to `b` the two components in the following arguments. | |
4205 | Only applies to rational and complex number types. | |
4206 | When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]] | |
4207 | [[`assign_components(b, b2, b2)`][`void`][Assigns to `b` the two components in the following arguments. | |
4208 | Only applies to rational and complex number types. | |
4209 | When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]] | |
4210 | ||
4211 | [[['Comparisons:]]] | |
4212 | [[`eval_eq(cb, cb2)`][`bool`][Returns `true` if `cb` and `cb2` are equal in value. | |
4213 | When not provided, the default implementation returns `cb.compare(cb2) == 0`.][`noexcept`]] | |
4214 | [[`eval_eq(cb, a)`][`bool`][Returns `true` if `cb` and `a` are equal in value. | |
4215 | The type of `a` shall be listed in one of the type lists | |
4216 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4217 | When not provided, return the equivalent of `eval_eq(cb, B(a))`.][[space]]] | |
4218 | [[`eval_eq(a, cb)`][`bool`][Returns `true` if `cb` and `a` are equal in value. | |
4219 | The type of `a` shall be listed in one of the type lists | |
4220 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4221 | When not provided, the default version returns `eval_eq(cb, a)`.][[space]]] | |
4222 | [[`eval_lt(cb, cb2)`][`bool`][Returns `true` if `cb` is less than `cb2` in value. | |
4223 | When not provided, the default implementation returns `cb.compare(cb2) < 0`.][`noexcept`]] | |
4224 | [[`eval_lt(cb, a)`][`bool`][Returns `true` if `cb` is less than `a` in value. | |
4225 | The type of `a` shall be listed in one of the type lists | |
4226 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4227 | When not provided, the default implementation returns `eval_lt(cb, B(a))`.][[space]]] | |
4228 | [[`eval_lt(a, cb)`][`bool`][Returns `true` if `a` is less than `cb` in value. | |
4229 | The type of `a` shall be listed in one of the type lists | |
4230 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4231 | When not provided, the default implementation returns `eval_gt(cb, a)`.][[space]]] | |
4232 | [[`eval_gt(cb, cb2)`][`bool`][Returns `true` if `cb` is greater than `cb2` in value. | |
4233 | When not provided, the default implementation returns `cb.compare(cb2) > 0`.][`noexcept`]] | |
4234 | [[`eval_gt(cb, a)`][`bool`][Returns `true` if `cb` is greater than `a` in value. | |
4235 | The type of `a` shall be listed in one of the type lists | |
4236 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4237 | When not provided, the default implementation returns `eval_gt(cb, B(a))`.][[space]]] | |
4238 | [[`eval_gt(a, cb)`][`bool`][Returns `true` if `a` is greater than `cb` in value. | |
4239 | The type of `a` shall be listed in one of the type lists | |
4240 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4241 | When not provided, the default implementation returns `eval_lt(cb, a)`.][[space]]] | |
4242 | [[`eval_is_zero(cb)`][`bool`][Returns `true` if `cb` is zero, otherwise `false`. The default version of this function | |
4243 | returns `cb.compare(ui_type(0)) == 0`, where `ui_type` is `ui_type` is | |
4244 | `typename mpl::front<typename B::unsigned_types>::type`.][[space]]] | |
4245 | [[`eval_get_sign(cb)`][`int`][Returns a value < zero if `cb` is negative, a value > zero if `cb` is positive, and zero if `cb` is zero. | |
4246 | The default version of this function | |
4247 | returns `cb.compare(ui_type(0))`, where `ui_type` is `ui_type` is | |
4248 | `typename mpl::front<typename B::unsigned_types>::type`.][[space]]] | |
4249 | ||
4250 | [[['Basic arithmetic:]]] | |
4251 | [[`eval_add(b, a)`][`void`][Adds `a` to `b`. The type of `a` shall be listed in one of the type lists | |
4252 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4253 | When not provided, the default version calls `eval_add(b, B(a))`][[space]]] | |
4254 | [[`eval_add(b, cb, cb2)`][`void`][Add `cb` to `cb2` and stores the result in `b`. | |
4255 | When not provided, does the equivalent of `b = cb; eval_add(b, cb2)`.][[space]]] | |
4256 | [[`eval_add(b, cb, a)`][`void`][Add `cb` to `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4257 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4258 | When not provided, does the equivalent of `eval_add(b, cb, B(a))`.][[space]]] | |
4259 | [[`eval_add(b, a, cb)`][`void`][Add `a` to `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4260 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4261 | When not provided, does the equivalent of `eval_add(b, cb, a)`.][[space]]] | |
4262 | [[`eval_subtract(b, a)`][`void`][Subtracts `a` from `b`. The type of `a` shall be listed in one of the type lists | |
4263 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4264 | When not provided, the default version calls `eval_subtract(b, B(a))`][[space]]] | |
4265 | [[`eval_subtract(b, cb, cb2)`][`void`][Subtracts `cb2` from `cb` and stores the result in `b`. | |
4266 | When not provided, does the equivalent of `b = cb; eval_subtract(b, cb2)`.][[space]]] | |
4267 | [[`eval_subtract(b, cb, a)`][`void`][Subtracts `a` from `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4268 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4269 | When not provided, does the equivalent of `eval_subtract(b, cb, B(a))`.][[space]]] | |
4270 | [[`eval_subtract(b, a, cb)`][`void`][Subtracts `cb` from `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4271 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4272 | When not provided, does the equivalent of `eval_subtract(b, cb, a); b.negate();`.][[space]]] | |
4273 | [[`eval_multiply(b, a)`][`void`][Multiplies `b` by `a`. The type of `a` shall be listed in one of the type lists | |
4274 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4275 | When not provided, the default version calls `eval_multiply(b, B(a))`][[space]]] | |
4276 | [[`eval_multiply(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and stores the result in `b`. | |
4277 | When not provided, does the equivalent of `b = cb; eval_multiply(b, cb2)`.][[space]]] | |
4278 | [[`eval_multiply(b, cb, a)`][`void`][Multiplies `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4279 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4280 | When not provided, does the equivalent of `eval_multiply(b, cb, B(a))`.][[space]]] | |
4281 | [[`eval_multiply(b, a, cb)`][`void`][Multiplies `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4282 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4283 | When not provided, does the equivalent of `eval_multiply(b, cb, a)`.][[space]]] | |
4284 | [[`eval_multiply_add(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and adds the result to `b`. | |
4285 | When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by | |
4286 | `eval_add(b, t)`.][[space]]] | |
4287 | [[`eval_multiply_add(b, cb, a)`][`void`][Multiplies `a` by `cb` and adds the result to `b`. | |
4288 | The type of `a` shall be listed in one of the type lists | |
4289 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4290 | When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by | |
4291 | `eval_add(b, t)`.][[space]]] | |
4292 | [[`eval_multiply_add(b, a, cb)`][`void`][Multiplies `a` by `cb` and adds the result to `b`. | |
4293 | The type of `a` shall be listed in one of the type lists | |
4294 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4295 | When not provided does the equivalent of `eval_multiply_add(b, cb, a)`.][[space]]] | |
4296 | [[`eval_multiply_subtract(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and subtracts the result from `b`. | |
4297 | When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by | |
4298 | `eval_subtract(b, t)`.][[space]]] | |
4299 | [[`eval_multiply_subtract(b, cb, a)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`. | |
4300 | The type of `a` shall be listed in one of the type lists | |
4301 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4302 | When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by | |
4303 | `eval_subtract(b, t)`.][[space]]] | |
4304 | [[`eval_multiply_subtract(b, a, cb)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`. | |
4305 | The type of `a` shall be listed in one of the type lists | |
4306 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4307 | When not provided does the equivalent of `eval_multiply_subtract(b, cb, a)`.][[space]]] | |
4308 | [[`eval_multiply_add(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and adds the result to `cb3` storing the result in `b`. | |
4309 | When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by | |
4310 | `eval_add(b, cb3)`. | |
4311 | For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of | |
4312 | `cb`, `cb2` and `cb3` with any type listed in one of the type lists | |
4313 | `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] | |
4314 | [[`eval_multiply_subtract(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and subtracts from the result `cb3` storing the result in `b`. | |
4315 | When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by | |
4316 | `eval_subtract(b, cb3)`. | |
4317 | For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of | |
4318 | `cb`, `cb2` and `cb3` with any type listed in one of the type lists | |
4319 | `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] | |
4320 | [[`eval_divide(b, a)`][`void`][Divides `b` by `a`. The type of `a` shall be listed in one of the type lists | |
4321 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4322 | When not provided, the default version calls `eval_divide(b, B(a))`] | |
4323 | [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]] | |
4324 | [[`eval_divide(b, cb, cb2)`][`void`][Divides `cb` by `cb2` and stores the result in `b`. | |
4325 | When not provided, does the equivalent of `b = cb; eval_divide(b, cb2)`.] | |
4326 | [`std::overflow_error` if `cb2` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]] | |
4327 | [[`eval_divide(b, cb, a)`][`void`][Divides `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4328 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4329 | When not provided, does the equivalent of `eval_divide(b, cb, B(a))`.] | |
4330 | [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]] | |
4331 | [[`eval_divide(b, a, cb)`][`void`][Divides `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists | |
4332 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4333 | When not provided, does the equivalent of `eval_divide(b, B(a), cb)`.] | |
4334 | [`std::overflow_error` if cb has the value zero, and `std::numeric_limits<number<B> >::has_infinity == false`]] | |
4335 | [[`eval_increment(b)`][void][Increments the value of `b` by one. | |
4336 | When not provided, does the equivalent of `eval_add(b, static_cast<ui_type>(1u))`. | |
4337 | Where `ui_type` is `typename mpl::front<typename B::unsigned_types>::type`.][[space]]] | |
4338 | [[`eval_decrement(b)`][void][Decrements the value of `b` by one. | |
4339 | When not provided, does the equivalent of `eval_subtract(b, static_cast<ui_type>(1u))`. | |
4340 | Where `ui_type` is `typename mpl::front<typename B::unsigned_types>::type`.][[space]]] | |
4341 | ||
4342 | [[['Integer specific operations:]]] | |
4343 | [[`eval_modulus(b, a)`][`void`][Computes `b %= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4344 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4345 | When not provided, the default version calls `eval_modulus(b, B(a))`] | |
4346 | [`std::overflow_error` if `a` has the value zero.]] | |
4347 | [[`eval_modulus(b, cb, cb2)`][`void`][Computes `cb % cb2` and stores the result in `b`, only required when `B` is an integer type. | |
4348 | When not provided, does the equivalent of `b = cb; eval_modulus(b, cb2)`.] | |
4349 | [`std::overflow_error` if `a` has the value zero.]] | |
4350 | [[`eval_modulus(b, cb, a)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4351 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4352 | When not provided, does the equivalent of `eval_modulus(b, cb, B(a))`.] | |
4353 | [`std::overflow_error` if `a` has the value zero.]] | |
4354 | [[`eval_modulus(b, a, cb)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4355 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4356 | When not provided, does the equivalent of `eval_modulus(b, B(a), cb)`.] | |
4357 | [`std::overflow_error` if `a` has the value zero.]] | |
4358 | [[`eval_bitwise_and(b, a)`][`void`][Computes `b &= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4359 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4360 | When not provided, the default version calls `eval_bitwise_and(b, B(a))`][[space]]] | |
4361 | [[`eval_bitwise_and(b, cb, cb2)`][`void`][Computes `cb & cb2` and stores the result in `b`, only required when `B` is an integer type. | |
4362 | When not provided, does the equivalent of `b = cb; eval_bitwise_and(b, cb2)`.][[space]]] | |
4363 | [[`eval_bitwise_and(b, cb, a)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4364 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4365 | When not provided, does the equivalent of `eval_bitwise_and(b, cb, B(a))`.][[space]]] | |
4366 | [[`eval_bitwise_and(b, a, cb)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4367 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4368 | When not provided, does the equivalent of `eval_bitwise_and(b, cb, a)`.][[space]]] | |
4369 | [[`eval_bitwise_or(b, a)`][`void`][Computes `b |= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4370 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4371 | When not provided, the default version calls `eval_bitwise_or(b, B(a))`][[space]]] | |
4372 | [[`eval_bitwise_or(b, cb, cb2)`][`void`][Computes `cb | cb2` and stores the result in `b`, only required when `B` is an integer type. | |
4373 | When not provided, does the equivalent of `b = cb; eval_bitwise_or(b, cb2)`.][[space]]] | |
4374 | [[`eval_bitwise_or(b, cb, a)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4375 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4376 | When not provided, does the equivalent of `eval_bitwise_or(b, cb, B(a))`.][[space]]] | |
4377 | [[`eval_bitwise_or(b, a, cb)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4378 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4379 | When not provided, does the equivalent of `eval_bitwise_or(b, cb, a)`.][[space]]] | |
4380 | [[`eval_bitwise_xor(b, a)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4381 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4382 | When not provided, the default version calls `eval_bitwise_xor(b, B(a))`][[space]]] | |
4383 | [[`eval_bitwise_xor(b, cb, cb2)`][`void`][Computes `cb ^ cb2` and stores the result in `b`, only required when `B` is an integer type. | |
4384 | When not provided, does the equivalent of `b = cb; eval_bitwise_xor(b, cb2)`.][[space]]] | |
4385 | [[`eval_bitwise_xor(b, cb, a)`][`void`][Computes `cb ^ a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4386 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4387 | When not provided, does the equivalent of `eval_bitwise_xor(b, cb, B(a))`.][[space]]] | |
4388 | [[`eval_bitwise_xor(b, a, cb)`][`void`][Computes `a ^ cb` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists | |
4389 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4390 | When not provided, does the equivalent of `eval_bitwise_xor(b, cb, a)`.][[space]]] | |
4391 | [[`eval_left_shift(b, cb, ui)`][`void`][Computes `cb << ui` and stores the result in `b`, only required when `B` is an integer type. | |
4392 | When not provided, does the equivalent of `b = cb; eval_left_shift(b, a);`.][[space]]] | |
4393 | [[`eval_right_shift(b, cb, ui)`][`void`][Computes `cb >> ui` and stores the result in `b`, only required when `B` is an integer type. | |
4394 | When not provided, does the equivalent of `b = cb; eval_right_shift(b, a);`.][[space]]] | |
4395 | [[`eval_qr(cb, cb2, b, b2)`][`void`][Sets `b` to the result of `cb / cb2` and `b2` to the result of `cb % cb2`. Only required when `B` is an integer type. | |
4396 | The default version of this function is synthesised from other operations above.] | |
4397 | [`std::overflow_error` if `a` has the value zero.]] | |
4398 | [[`eval_integer_modulus(cb, ui)`][`unsigned`][Returns the result of `cb % ui`. Only required when `B` is an integer type. | |
4399 | The default version of this function is synthesised from other operations above.] | |
4400 | [`std::overflow_error` if `a` has the value zero.]] | |
4401 | [[`eval_lsb(cb)`][`unsigned`][Returns the index of the least significant bit that is set. Only required when `B` is an integer type. | |
4402 | The default version of this function is synthesised from other operations above.][[space]]] | |
4403 | [[`eval_msb(cb)`][`unsigned`][Returns the index of the most significant bit that is set. Only required when `B` is an integer type. | |
4404 | The default version of this function is synthesised from other operations above.][[space]]] | |
4405 | [[`eval_bit_test(cb, ui)`][`bool`][Returns true if `cb` has bit `ui` set. Only required when `B` is an integer type. | |
4406 | The default version of this function is synthesised from other operations above.][[space]]] | |
4407 | [[`eval_bit_set(b, ui)`][`void`][Sets the bit at index `ui` in `b`. Only required when `B` is an integer type. | |
4408 | The default version of this function is synthesised from other operations above.][[space]]] | |
4409 | [[`eval_bit_unset(b, ui)`][`void`][Unsets the bit at index `ui` in `b`. Only required when `B` is an integer type. | |
4410 | The default version of this function is synthesised from other operations above.][[space]]] | |
4411 | [[`eval_bit_flip(b, ui)`][`void`][Flips the bit at index `ui` in `b`. Only required when `B` is an integer type. | |
4412 | The default version of this function is synthesised from other operations above.][[space]]] | |
4413 | [[`eval_gcd(b, cb, cb2)`][`void`][Sets `b` to the greatest common divisor of `cb` and `cb2`. Only required when `B` is an integer type. | |
4414 | The default version of this function is synthesised from other operations above.][[space]]] | |
4415 | [[`eval_lcm(b, cb, cb2)`][`void`][Sets `b` to the least common multiple of `cb` and `cb2`. Only required when `B` is an integer type. | |
4416 | The default version of this function is synthesised from other operations above.][[space]]] | |
4417 | [[`eval_gcd(b, cb, a)`][`void`][Sets `b` to the greatest common divisor of `cb` and `cb2`. Only required when `B` is an integer type. | |
4418 | The type of `a` shall be listed in one of the type lists | |
4419 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4420 | The default version of this function calls `eval_gcd(b, cb, B(a))`.][[space]]] | |
4421 | [[`eval_lcm(b, cb, a)`][`void`][Sets `b` to the least common multiple of `cb` and `cb2`. Only required when `B` is an integer type. | |
4422 | The type of `a` shall be listed in one of the type lists | |
4423 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4424 | The default version of this function calls `eval_lcm(b, cb, B(a))`.][[space]]] | |
4425 | [[`eval_gcd(b, a, cb)`][`void`][Sets `b` to the greatest common divisor of `cb` and `a`. Only required when `B` is an integer type. | |
4426 | The type of `a` shall be listed in one of the type lists | |
4427 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4428 | The default version of this function calls `eval_gcd(b, cb, a)`.][[space]]] | |
4429 | [[`eval_lcm(b, a, cb)`][`void`][Sets `b` to the least common multiple of `cb` and `a`. Only required when `B` is an integer type. | |
4430 | The type of `a` shall be listed in one of the type lists | |
4431 | `B::signed_types`, `B::unsigned_types` or `B::float_types`. | |
4432 | The default version of this function calls `eval_lcm(b, cb, a)`.][[space]]] | |
4433 | [[`eval_powm(b, cb, cb2, cb3)`][`void`][Sets `b` to the result of ['(cb^cb2)%cb3]. | |
4434 | The default version of this function is synthesised from other operations above.][[space]]] | |
4435 | [[`eval_powm(b, cb, cb2, a)`][`void`][Sets `b` to the result of ['(cb^cb2)%a]. | |
4436 | The type of `a` shall be listed in one of the type lists | |
4437 | `B::signed_types`, `B::unsigned_types`. | |
4438 | The default version of this function is synthesised from other operations above.][[space]]] | |
4439 | [[`eval_powm(b, cb, a, cb2)`][`void`][Sets `b` to the result of ['(cb^a)%cb2]. | |
4440 | The type of `a` shall be listed in one of the type lists | |
4441 | `B::signed_types`, `B::unsigned_types`. | |
4442 | The default version of this function is synthesised from other operations above.][[space]]] | |
4443 | [[`eval_powm(b, cb, a, a2)`][`void`][Sets `b` to the result of ['(cb^a)%a2]. | |
4444 | The type of `a` shall be listed in one of the type lists | |
4445 | `B::signed_types`, `B::unsigned_types`. | |
4446 | The default version of this function is synthesised from other operations above.][[space]]] | |
4447 | [[`eval_integer_sqrt(b, cb, b2)`][`void`][Sets `b` to the largest integer which when squared is less than `cb`, also | |
4448 | sets `b2` to the remainder, ie to ['cb - b[super 2]]. | |
4449 | The default version of this function is synthesised from other operations above.][[space]]] | |
4450 | ||
4451 | [[['Sign manipulation:]]] | |
4452 | [[`eval_abs(b, cb)`][`void`][Set `b` to the absolute value of `cb`. | |
4453 | The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if | |
4454 | `eval_get_sign(cb) < 0`.][[space]]] | |
4455 | [[`eval_fabs(b, cb)`][`void`][Set `b` to the absolute value of `cb`. | |
4456 | The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if | |
4457 | `eval_get_sign(cb) < 0`.][[space]]] | |
4458 | ||
4459 | [[['floating-point functions:]]] | |
4460 | [[`eval_fpclassify(cb)`][`int`][Returns one of the same values returned by `std::fpclassify`. Only required when `B` is an floating-point type. | |
4461 | The default version of this function will only test for zero `cb`.][[space]]] | |
4462 | [[`eval_trunc(b, cb)`][`void`][Performs the equivalent operation to `std::trunc` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4463 | The default version of this function is synthesised from other operations above.][[space]]] | |
4464 | [[`eval_round(b, cb)`][`void`][Performs the equivalent operation to `std::round` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4465 | The default version of this function is synthesised from other operations above.][[space]]] | |
4466 | [[`eval_exp(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4467 | The default version of this function is synthesised from other operations above.][[space]]] | |
4468 | [[`eval_exp2(b, cb)`][`void`][Performs the equivalent operation to `std::exp2` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4469 | The default version of this function is implemented in terms of `eval_pow`.][[space]]] | |
4470 | [[`eval_log(b, cb)`][`void`][Performs the equivalent operation to `std::log` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4471 | The default version of this function is synthesised from other operations above.][[space]]] | |
4472 | [[`eval_log10(b, cb)`][`void`][Performs the equivalent operation to `std::log10` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4473 | The default version of this function is synthesised from other operations above.][[space]]] | |
4474 | [[`eval_sin(b, cb)`][`void`][Performs the equivalent operation to `std::sin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4475 | The default version of this function is synthesised from other operations above.][[space]]] | |
4476 | [[`eval_cos(b, cb)`][`void`][Performs the equivalent operation to `std::cos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4477 | The default version of this function is synthesised from other operations above.][[space]]] | |
4478 | [[`eval_tan(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4479 | The default version of this function is synthesised from other operations above.][[space]]] | |
4480 | [[`eval_asin(b, cb)`][`void`][Performs the equivalent operation to `std::asin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4481 | The default version of this function is synthesised from other operations above.][[space]]] | |
4482 | [[`eval_acos(b, cb)`][`void`][Performs the equivalent operation to `std::acos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4483 | The default version of this function is synthesised from other operations above.][[space]]] | |
4484 | [[`eval_atan(b, cb)`][`void`][Performs the equivalent operation to `std::atan` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4485 | The default version of this function is synthesised from other operations above.][[space]]] | |
4486 | [[`eval_sinh(b, cb)`][`void`][Performs the equivalent operation to `std::sinh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4487 | The default version of this function is synthesised from other operations above.][[space]]] | |
4488 | [[`eval_cosh(b, cb)`][`void`][Performs the equivalent operation to `std::cosh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4489 | The default version of this function is synthesised from other operations above.][[space]]] | |
4490 | [[`eval_tanh(b, cb)`][`void`][Performs the equivalent operation to `std::tanh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating-point type. | |
4491 | The default version of this function is synthesised from other operations above.][[space]]] | |
4492 | [[`eval_fmod(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::fmod` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type. | |
4493 | The default version of this function is synthesised from other operations above.][[space]]] | |
4494 | [[`eval_modf(b, cb, pb)`][`void`][Performs the equivalent operation to `std::modf` on argument `cb`, and store the integer result in `*pb` and the fractional part in `b`. | |
4495 | Only required when `B` is an floating-point type. | |
4496 | The default version of this function is synthesised from other operations above.][[space]]] | |
4497 | [[`eval_pow(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::pow` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type. | |
4498 | The default version of this function is synthesised from other operations above.][[space]]] | |
4499 | [[`eval_atan2(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::atan` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating-point type. | |
4500 | The default version of this function is synthesised from other operations above.][[space]]] | |
4501 | [[`eval_scalbn(b, cb, e)`][`void`][Scales value `cb` by ['r[super e]], where ['r] is the radix of the type. The default version of this function | |
4502 | is implemented in terms of eval_ldexp, consequently this function must be provided for types with a radix other than 2.]] | |
4503 | [[`eval_scalbln(b, cb, e)`][`void`][Calls `eval_scalbn(b, cb, e)`.]] | |
4504 | [[`eval_ilogb(cb)`][`B::exponent_type`][Returns the exponent ['e] of value `cb` such that ['1 <= cb*r[super -e] < r], where ['r] is the radix of type B. | |
4505 | The default version of this function is implemented in terms of eval_frexp, consequently this function must be provided for types with a radix other than 2.]] | |
4506 | [[`eval_remquo(b, cb, cb2, pi)`][`void`][Sets `b = cb - n * cb2` and stores `n` in `*pi`.]] | |
4507 | [[`eval_remquo(b, cb, a, pi)`][`void`][Default version converts a to type B and calls the overload above.]] | |
4508 | [[`eval_remquo(b, a, cb, pi)`][`void`][Default version converts a to type B and calls the overload above.]] | |
4509 | [[`eval_remainder(b, cb, cb2)`][`void`][Default version calls eval_remquo with a dummy final argument.]] | |
4510 | [[`eval_remainder(b, cb, a)`][`void`][Default version calls eval_remquo with a dummy final argument.]] | |
4511 | [[`eval_remainder(b, a, cb)`][`void`][Default version calls eval_remquo with a dummy final argument.]] | |
4512 | ||
4513 | [[`eval_fdim(b, cb, cb2)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]] | |
4514 | [[`eval_fdim(b, cb, a)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]] | |
4515 | [[`eval_fdim(b, a, cb)`][`void`][Default version sets `b = cb - cb2` if `cb > cb2` and zero otherwise. Special cases are handled as in the C99 annex.]] | |
4516 | ||
4517 | [[`eval_fmax(b, cb, cb2)`][`void`][Sets `b` to the larger of `cb` and `cb2`.]] | |
4518 | [[`eval_fmax(b, cb, a)`][`void`][Sets `b` to the larger of `cb` and `a`.]] | |
4519 | [[`eval_fmax(b, a, cb)`][`void`][Sets `b` to the larger of `cb` and `a`.]] | |
4520 | [[`eval_fmin(b, cb, cb2)`][`void`][Sets `b` to the smaller of `cb` and `cb2`.]] | |
4521 | [[`eval_fmin(b, cb, a)`][`void`][Sets `b` to the smaller of `cb` and `a`.]] | |
4522 | [[`eval_fmin(b, a, cb)`][`void`][Sets `b` to the smaller of `cb` and `a`.]] | |
4523 | ||
4524 | [[`eval_hypot(b, cb, cb2)`][`void`][Sets `b` to the square root of the sum of the squares of `cb` and `cb2` without undue over or under flow.]] | |
4525 | [[`eval_hypot(b, cb, a)`][`void`][As above.]] | |
4526 | [[`eval_hypot(b, a, cb)`][`void`][As above.]] | |
4527 | ||
4528 | [[`eval_logb(b, cb)`][`B::exponent_type`][Sets `b` to the exponent ['e] of value `cb` such that ['1 <= cb*r[super -b] < r], where ['r] is the radix of type B. | |
4529 | The default version of this function is implemented in terms of `eval_ilogb`.]] | |
4530 | [[`eval_nearbyint(b, cb)`][`void`][Calls `eval_round(b, cb)`.]] | |
4531 | [[`eval_rint(b, cb)`][`void`][Calls `eval_nearbyint(b, cb)`.]] | |
4532 | [[`eval_log2(b, cb)`][`void`][Sets `b` to the logarithm base 2 of `cb`.]] | |
4533 | ||
4534 | [[['hashing:]]] | |
4535 | [[`hash_value(cb)`][`std::size_t`] | |
4536 | [Returns a hash value for the argument that is suitable for use with `std::hash` etc. If not provided then no automatic hashing support will be available for the number type.]] | |
4537 | ] | |
4538 | ||
4539 | When the tables above place no ['throws] requirements on an operation, then it is up to each type modelling this concept to | |
4540 | decide when or whether throwing an exception is desirable. However, thrown exceptions should always either be the type, or | |
4541 | inherit from the type `std::runtime_error`. For example, a floating-point type might choose to throw `std::overflow_error` | |
4542 | whenever the result of an operation would be infinite, and `std::underflow_error` whenever it would round to zero. | |
4543 | ||
4544 | [note | |
4545 | The non-member functions are all named with an "eval_" prefix to avoid conflicts with template classes of the same name - | |
4546 | in point of fact this naming convention shouldn't be necessary, but rather works around some compiler bugs.] | |
4547 | ||
4548 | [h4 Overloadable Functions] | |
4549 | ||
4550 | Some of the C99 math functions do not have `eval_` functions but must be overloaded directly: these functions | |
4551 | are either trivial or are forwarded to the Boost.Math implementations by default. | |
4552 | The full list of these functions is: | |
4553 | ||
4554 | int sign (const ``['number-or-expression-template-type]``&); | |
4555 | int signbit (const ``['number-or-expression-template-type]``&); | |
4556 | ``['number]`` changesign (const ``['number-or-expression-template-type]``&); | |
4557 | ``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
4558 | ``['number]`` asinh (const ``['number-or-expression-template-type]``&); | |
4559 | ``['number]`` acosh (const ``['number-or-expression-template-type]``&); | |
4560 | ``['number]`` atanh (const ``['number-or-expression-template-type]``&); | |
4561 | ``['number]`` cbrt (const ``['number-or-expression-template-type]``&); | |
4562 | ``['number]`` erf (const ``['number-or-expression-template-type]``&); | |
4563 | ``['number]`` erfc (const ``['number-or-expression-template-type]``&); | |
4564 | ``['number]`` expm1 (const ``['number-or-expression-template-type]``&); | |
4565 | ``['number]`` log1p (const ``['number-or-expression-template-type]``&); | |
4566 | ``['number]`` tgamma (const ``['number-or-expression-template-type]``&); | |
4567 | ``['number]`` lgamma (const ``['number-or-expression-template-type]``&); | |
4568 | long lrint (const ``['number-or-expression-template-type]``&); | |
4569 | long long llrint (const ``['number-or-expression-template-type]``&); | |
4570 | ``['number]`` nextafter (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
4571 | ``['number]`` nexttoward (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); | |
4572 | ||
4573 | [endsect] | |
4574 | ||
4575 | [section:headers Header File Structure] | |
4576 | ||
4577 | [table Top level headers | |
4578 | [[Header][Contains]] | |
4579 | [[cpp_int.hpp][The `cpp_int` backend type.]] | |
4580 | [[gmp.hpp][Defines all [gmp] related backends.]] | |
4581 | [[miller_rabin.hpp][Miller Rabin primality testing code.]] | |
4582 | [[number.hpp][Defines the `number` backend, is included by all the backend headers.]] | |
4583 | [[mpfr.hpp][Defines the mpfr_float_backend backend.]] | |
4584 | [[random.hpp][Defines code to interoperate with Boost.Random.]] | |
4585 | [[rational_adaptor.hpp][Defines the `rational_adaptor` backend.]] | |
4586 | [[cpp_dec_float.hpp][Defines the `cpp_dec_float` backend.]] | |
4587 | [[tommath.hpp][Defines the `tommath_int` backend.]] | |
4588 | [[concepts/number_archetypes.hpp][Defines a backend concept archetypes for testing use.]] | |
4589 | ] | |
4590 | ||
4591 | [table Implementation Headers | |
4592 | [[Header][Contains]] | |
4593 | [[cpp_int/add.hpp][Add and subtract operators for `cpp_int_backend`.]] | |
4594 | [[cpp_int/bitwise.hpp][Bitwise operators for `cpp_int_backend`.]] | |
4595 | [[cpp_int/checked.hpp][Helper functions for checked arithmetic for `cpp_int_backend`.]] | |
4596 | [[cpp_int/comparison.hpp][Comparison operators for `cpp_int_backend`.]] | |
4597 | [[cpp_int/cpp_int_config.hpp][Basic setup and configuration for `cpp_int_backend`.]] | |
4598 | [[cpp_int/divide.hpp][Division and modulus operators for `cpp_int_backend`.]] | |
4599 | [[cpp_int/limits.hpp][`numeric_limits` support for `cpp_int_backend`.]] | |
4600 | [[cpp_int/misc.hpp][Miscellaneous operators for `cpp_int_backend`.]] | |
4601 | [[cpp_int/multiply.hpp][Multiply operators for `cpp_int_backend`.]] | |
4602 | [[detail/big_lanczos.hpp][Lanczos support for Boost.Math integration.]] | |
4603 | [[detail/default_ops.hpp][Default versions of the optional backend non-member functions.]] | |
4604 | [[detail/generic_interconvert.hpp][Generic interconversion routines.]] | |
4605 | [[detail/number_base.hpp][All the expression template code, metaprogramming, and operator overloads for `number`.]] | |
4606 | [[detail/no_et_ops.hpp][The non-expression template operators.]] | |
4607 | [[detail/functions/constants.hpp][Defines constants used by the floating-point functions.]] | |
4608 | [[detail/functions/pow.hpp][Defines default versions of the power and exponential related floating-point functions.]] | |
4609 | [[detail/functions/trig.hpp][Defines default versions of the trigonometric related floating-point functions.]] | |
4610 | ] | |
4611 | ||
4612 | [endsect] | |
4613 | ||
4614 | [endsect] | |
4615 | ||
4616 | [section:perf Performance Comparison] | |
4617 | ||
4618 | [section:overhead The Overhead in the Number Class Wrapper] | |
4619 | ||
4620 | Using a simple [@../../performance/arithmetic_backend.hpp backend class] that wraps any built in arithmetic type | |
4621 | we can measure the overhead involved in wrapping a type inside the `number` frontend, and the effect that turning | |
4622 | on expression templates has. The following table compares the performance between `double` and a `double` wrapped | |
4623 | inside class `number`: | |
4624 | ||
4625 | [table | |
4626 | [[Type][Bessel Function Evaluation][Non-Central T Evaluation]] | |
4627 | [[`double`] [[*1.0 (0.016s)]] [[*1.0] (0.46s)]] | |
4628 | [[`number<arithmetic_backend<double>, et_off>`] [1.2 (0.019s)] [[*1.0](0.46s)]] | |
4629 | [[`number<arithmetic_backend<double>, et_on>`] [1.2 (0.019s)] [1.7 (0.79s)]] | |
4630 | ] | |
4631 | ||
4632 | As you can see whether or not there is an overhead, and how large it is depends on the actual situation, | |
4633 | but the overhead is in any cases small. Expression templates generally add a greater overhead the | |
4634 | more complex the expression becomes due to the logic of figuring out how to best unpack and evaluate | |
4635 | the expression, but of course this is also the situation where you save more temporaries. For a | |
4636 | "trivial" backend like this, saving temporaries has no benefit, but for larger types it becomes | |
4637 | a bigger win. | |
4638 | ||
4639 | The following table compares arithmetic using either `long long` or `number<arithmetic_backend<long long> >` | |
4640 | for the [@../../performance/voronoi_performance.cpp voronoi-diagram builder test]: | |
4641 | ||
4642 | [table | |
4643 | [[Type][Relative time]] | |
4644 | [[`long long`][[*1.0](0.0823s)]] | |
4645 | [[`number<arithmetic_backend<long long>, et_off>`][1.05 (0.0875s)]] | |
4646 | ] | |
4647 | ||
4648 | This test involves mainly creating a lot of temporaries and performing a small amount of arithmetic on them, | |
4649 | with very little difference in performance between the native and "wrapped" types. | |
4650 | ||
4651 | The test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
4652 | turned on (/Ox), and used MPIR-2.3.0 and [tommath]-0.42.0. The tests were run on 32-bit | |
4653 | Windows Vista machine. | |
4654 | ||
4655 | [endsect] | |
4656 | ||
4657 | [section:realworld Floating-Point Real World Tests] | |
4658 | ||
4659 | These tests test the total time taken to execute all of Boost.Math's test cases for these functions. | |
4660 | In each case the best performing library gets a relative score of 1, with the total execution time | |
4661 | given in brackets. The first three libraries listed are the various floating-point types provided | |
4662 | by this library, while for comparison, two popular C++ front-ends to [mpfr] ([mpfr_class] and [mpreal]) | |
4663 | are also shown. | |
4664 | ||
4665 | [table Bessel Function Performance | |
4666 | [[Library][50 Decimal Digits][100 Decimal Digits]] | |
4667 | [[mpfr_float] [1.2 (5.78s)] [1.2 (9.56s)]] | |
4668 | [[static_mpfr_float] [1.1 (5.47s)] [1.1 (9.09s)]] | |
4669 | [[mpf_float] [[*1.0] (4.82s)] [[*1.0](8.07s)]] | |
4670 | [[cpp_dec_float] [1.8 (8.54s)] [2.6 (20.66s)]] | |
4671 | [[[mpfr_class]] [1.3 (6.28s)] [1.2(10.06s)]] | |
4672 | [[[mpreal]] [2.0 (9.54s)] [1.7 (14.08s)]] | |
4673 | ] | |
4674 | ||
4675 | [table Non-Central T Distribution Performance | |
4676 | [[Library][50 Decimal Digits]] | |
4677 | [[mpfr_float] [1.3 (263.27s)]] | |
4678 | [[static_mpfr_float] [1.2 (232.88s)]] | |
4679 | [[mpf_float] [[*1.0] (195.73s)]] | |
4680 | [[cpp_dec_float] [1.9 (366.38s)]] | |
4681 | [[[mpfr_class]] [1.5 (286.94s)]] | |
4682 | [[[mpreal]] [2.0 (388.70s)]] | |
4683 | ] | |
4684 | ||
4685 | Test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
4686 | turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit | |
4687 | Windows Vista machine. | |
4688 | ||
4689 | [endsect] | |
4690 | ||
4691 | [section:int_real_world Integer Real World Tests] | |
4692 | ||
4693 | The first set of [@../../performance/voronoi_performance.cpp tests] measure the times taken to | |
4694 | execute the multiprecision part of the Voronoi-diagram builder from Boost.Polygon. The tests | |
4695 | mainly create a large number of temporaries "just in case" multiprecision arithmetic is required, | |
4696 | for comparison, also included in the tests is Boost.Polygon's own partial-multiprecision integer | |
4697 | type which was custom written for this specific task: | |
4698 | ||
4699 | [table | |
4700 | [[Integer Type][Relative Performance (Actual time in parenthesis)]] | |
4701 | [[polygon::detail::extended_int][1(0.138831s)]] | |
4702 | [[int256_t][1.19247(0.165551s)]] | |
4703 | [[int512_t][1.23301(0.17118s)]] | |
4704 | [[int1024_t][1.21463(0.168628s)]] | |
4705 | [[checked_int256_t][1.31711(0.182855s)]] | |
4706 | [[checked_int512_t][1.57413(0.218538s)]] | |
4707 | [[checked_int1024_t][1.36992(0.190187s)]] | |
4708 | [[cpp_int][1.63244(0.226632s)]] | |
4709 | [[mpz_int][5.42511(0.753172s)]] | |
4710 | [[tom_int][29.0793(4.03709s)]] | |
4711 | ] | |
4712 | ||
4713 | Note how for this use case, any dynamic allocation is a performance killer. | |
4714 | ||
4715 | The next [@../../performance/miller_rabin_performance.cpp tests] measure the time taken to generate 1000 128-bit | |
4716 | random numbers and test for primality using the Miller Rabin test. This is primarily a test of modular-exponentiation | |
4717 | since that is the rate limiting step: | |
4718 | ||
4719 | [table | |
4720 | [[Integer Type][Relative Performance (Actual time in parenthesis)]] | |
4721 | [[cpp_int][5.25827(0.379597s)]] | |
4722 | [[cpp_int (no Expression templates)][5.15675(0.372268s)]] | |
4723 | [[cpp_int (128-bit cache)][5.10882(0.368808s)]] | |
4724 | [[cpp_int (256-bit cache)][5.50623(0.397497s)]] | |
4725 | [[cpp_int (512-bit cache)][4.82257(0.348144s)]] | |
4726 | [[cpp_int (1024-bit cache)][5.00053(0.360991s)]] | |
4727 | [[int1024_t][4.37589(0.315897s)]] | |
4728 | [[checked_int1024_t][4.52396(0.326587s)]] | |
4729 | [[mpz_int][1(0.0721905s)]] | |
4730 | [[mpz_int (no Expression templates)][1.0248(0.0739806s)]] | |
4731 | [[tom_int][2.60673(0.188181s)]] | |
4732 | [[tom_int (no Expression templates)][2.64997(0.191303s)]] | |
4733 | ] | |
4734 | ||
4735 | It's interesting to note that expression templates have little effect here - perhaps because the actual expressions involved | |
4736 | are relatively trivial in this case - so the time taken for multiplication and division tends to dominate. Also note | |
4737 | how increasing the internal cache size used by `cpp_int` is quite effective in this case in cutting out memory allocations | |
4738 | altogether - cutting about a third off the total runtime. Finally the much quicker times from GMP and tommath are down to their | |
4739 | much better modular-exponentiation algorithms (GMP's is about 5x faster). That's an issue which needs to be addressed | |
4740 | in a future release for __cpp_int. | |
4741 | ||
4742 | Test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
4743 | turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit | |
4744 | Windows Vista machine. | |
4745 | ||
4746 | [endsect] | |
4747 | ||
4748 | [section:float_performance Float Algorithm Performance] | |
4749 | ||
4750 | Note that these tests are carefully designed to test performance of the underlying algorithms | |
4751 | and not memory allocation or variable copying. As usual, performance results should be taken | |
4752 | with a healthy dose of scepticism, and real-world performance may vary widely depending upon the | |
4753 | specifics of the program. In each table relative times are given first, with the best performer | |
4754 | given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 | |
4755 | operations. | |
4756 | ||
4757 | [table Operator + | |
4758 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4759 | [[cpp_dec_float][[*1] (0.0575156s)][[*1] (0.0740086s)][[*1] (0.219073s)]] | |
4760 | [[gmp_float][2.45065 (0.14095s)][2.01398 (0.149052s)][1.09608 (0.240122s)]] | |
4761 | [[mpfr_float][2.6001 (0.149546s)][2.12079 (0.156957s)][1.09078 (0.23896s)]] | |
4762 | ] | |
4763 | [table Operator +(int) | |
4764 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4765 | [[cpp_dec_float][1.46115 (0.0855392s)][2.60353 (0.114398s)][3.62562 (0.264905s)]] | |
4766 | [[gmp_float][[*1] (0.0585424s)][[*1] (0.0439398s)][[*1] (0.0730648s)]] | |
4767 | [[mpfr_float][2.40441 (0.14076s)][3.2877 (0.144461s)][2.40379 (0.175632s)]] | |
4768 | ] | |
4769 | [table Operator +(unsigned long long) | |
4770 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4771 | [[cpp_dec_float][[*1] (0.118146s)][[*1] (0.144714s)][[*1] (0.315639s)]] | |
4772 | [[gmp_float][4.5555 (0.538213s)][3.83096 (0.554395s)][1.95079 (0.615745s)]] | |
4773 | [[mpfr_float][5.74477 (0.678719s)][4.85295 (0.702291s)][2.70354 (0.853342s)]] | |
4774 | ] | |
4775 | [table Operator +=(unsigned long long) | |
4776 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4777 | [[cpp_dec_float][[*1] (0.101188s)][[*1] (0.122394s)][[*1] (0.251975s)]] | |
4778 | [[gmp_float][5.199 (0.526079s)][4.39327 (0.537712s)][2.42151 (0.610159s)]] | |
4779 | [[mpfr_float][6.08318 (0.615547s)][5.18525 (0.634645s)][3.1022 (0.781677s)]] | |
4780 | ] | |
4781 | [table Operator - | |
4782 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4783 | [[cpp_dec_float][[*1] (0.0895163s)][[*1] (0.129248s)][1.5088 (0.374512s)]] | |
4784 | [[gmp_float][1.72566 (0.154474s)][1.22567 (0.158415s)][[*1] (0.248219s)]] | |
4785 | [[mpfr_float][1.83764 (0.164499s)][1.34284 (0.173559s)][1.00226 (0.248781s)]] | |
4786 | ] | |
4787 | [table Operator -(int) | |
4788 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4789 | [[cpp_dec_float][[*1] (0.105285s)][[*1] (0.142741s)][[*1] (0.278718s)]] | |
4790 | [[gmp_float][2.34437 (0.246828s)][1.28814 (0.183871s)][1.00731 (0.280754s)]] | |
4791 | [[mpfr_float][2.8032 (0.295136s)][2.09178 (0.298582s)][1.25213 (0.34899s)]] | |
4792 | ] | |
4793 | [table Operator -(unsigned long long) | |
4794 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4795 | [[cpp_dec_float][[*1] (0.13719s)][[*1] (0.184428s)][[*1] (0.344212s)]] | |
4796 | [[gmp_float][4.0804 (0.559791s)][3.06776 (0.565781s)][2.07736 (0.715053s)]] | |
4797 | [[mpfr_float][5.10114 (0.699828s)][3.88684 (0.716843s)][2.50074 (0.860784s)]] | |
4798 | ] | |
4799 | [table Operator -=(unsigned long long) | |
4800 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4801 | [[cpp_dec_float][[*1] (0.100984s)][[*1] (0.123148s)][[*1] (0.246181s)]] | |
4802 | [[gmp_float][5.68353 (0.573944s)][4.68636 (0.577116s)][2.6958 (0.663655s)]] | |
4803 | [[mpfr_float][6.19738 (0.625834s)][5.18544 (0.638577s)][3.18738 (0.784673s)]] | |
4804 | ] | |
4805 | [table Operator * | |
4806 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4807 | [[cpp_dec_float][1.03667 (0.284251s)][1.30576 (0.536527s)][1.44686 (4.81057s)]] | |
4808 | [[gmp_float][[*1] (0.274196s)][[*1] (0.410891s)][[*1] (3.32484s)]] | |
4809 | [[mpfr_float][1.24537 (0.341477s)][1.15785 (0.475749s)][1.1796 (3.92199s)]] | |
4810 | ] | |
4811 | [table Operator *(int) | |
4812 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4813 | [[cpp_dec_float][3.97453 (0.240262s)][9.91222 (0.463473s)][50.7926 (4.36527s)]] | |
4814 | [[gmp_float][[*1] (0.0604505s)][[*1] (0.0467577s)][[*1] (0.0859431s)]] | |
4815 | [[mpfr_float][2.56974 (0.155342s)][3.56312 (0.166603s)][3.22964 (0.277565s)]] | |
4816 | ] | |
4817 | [table Operator *(unsigned long long) | |
4818 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4819 | [[cpp_dec_float][[*1] (0.331877s)][1.01058 (0.586122s)][6.688 (4.7931s)]] | |
4820 | [[gmp_float][1.72433 (0.572266s)][[*1] (0.579987s)][[*1] (0.716672s)]] | |
4821 | [[mpfr_float][2.5553 (0.848047s)][1.74987 (1.0149s)][1.80403 (1.2929s)]] | |
4822 | ] | |
4823 | [table Operator *=(unsigned long long) | |
4824 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4825 | [[cpp_dec_float][[*1] (0.321397s)][1.00772 (0.574887s)][6.65946 (4.7468s)]] | |
4826 | [[gmp_float][1.77419 (0.570218s)][[*1] (0.570482s)][[*1] (0.712791s)]] | |
4827 | [[mpfr_float][2.62172 (0.842611s)][1.77691 (1.01369s)][1.77511 (1.26528s)]] | |
4828 | ] | |
4829 | [table Operator / | |
4830 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4831 | [[cpp_dec_float][2.96096 (4.00777s)][4.53244 (7.86435s)][6.11936 (51.5509s)]] | |
4832 | [[gmp_float][[*1] (1.35354s)][[*1] (1.73512s)][[*1] (8.42422s)]] | |
4833 | [[mpfr_float][1.30002 (1.75963s)][1.39045 (2.41261s)][1.66762 (14.0484s)]] | |
4834 | ] | |
4835 | [table Operator /(int) | |
4836 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4837 | [[cpp_dec_float][8.60726 (1.8181s)][15.4122 (3.67479s)][34.5119 (24.729s)]] | |
4838 | [[gmp_float][1.24394 (0.262756s)][[*1] (0.238433s)][[*1] (0.716536s)]] | |
4839 | [[mpfr_float][[*1] (0.211229s)][1.12178 (0.26747s)][1.02237 (0.732562s)]] | |
4840 | ] | |
4841 | [table Operator /(unsigned long long) | |
4842 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4843 | [[cpp_dec_float][2.10976 (1.97569s)][3.73601 (3.9133s)][11.3085 (25.4533s)]] | |
4844 | [[gmp_float][[*1] (0.936452s)][[*1] (1.04746s)][[*1] (2.25081s)]] | |
4845 | [[mpfr_float][1.3423 (1.257s)][1.51575 (1.58768s)][3.31513 (7.46175s)]] | |
4846 | ] | |
4847 | [table Operator /=(unsigned long long) | |
4848 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4849 | [[cpp_dec_float][2.17401 (1.96883s)][3.79591 (3.8965s)][11.2328 (25.2606s)]] | |
4850 | [[gmp_float][[*1] (0.905621s)][[*1] (1.0265s)][[*1] (2.24882s)]] | |
4851 | [[mpfr_float][1.37953 (1.24933s)][1.53073 (1.57129s)][3.30546 (7.43339s)]] | |
4852 | ] | |
4853 | [table Operator construct | |
4854 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4855 | [[cpp_dec_float][[*1] (0.00929804s)][[*1] (0.0268321s)][[*1] (0.0310685s)]] | |
4856 | [[gmp_float][30.8781 (0.287106s)][7.59969 (0.203916s)][6.51873 (0.202527s)]] | |
4857 | [[mpfr_float][23.5296 (0.218779s)][8.11058 (0.217624s)][7.16325 (0.222552s)]] | |
4858 | ] | |
4859 | [table Operator construct(unsigned) | |
4860 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4861 | [[cpp_dec_float][[*1] (0.0603971s)][[*1] (0.0735485s)][[*1] (0.116464s)]] | |
4862 | [[gmp_float][3.91573 (0.236498s)][2.88171 (0.211945s)][1.81075 (0.210887s)]] | |
4863 | [[mpfr_float][4.90052 (0.295977s)][4.01118 (0.295017s)][2.62005 (0.305141s)]] | |
4864 | ] | |
4865 | [table Operator construct(unsigned long long) | |
4866 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4867 | [[cpp_dec_float][[*1] (0.0610288s)][[*1] (0.0759005s)][[*1] (0.118511s)]] | |
4868 | [[gmp_float][8.26247 (0.504249s)][6.69042 (0.507806s)][4.32819 (0.51294s)]] | |
4869 | [[mpfr_float][10.1593 (0.620013s)][8.45884 (0.64203s)][5.51472 (0.653557s)]] | |
4870 | ] | |
4871 | [table Operator str | |
4872 | [[Backend][50 Bits][100 Bits][500 Bits]] | |
4873 | [[cpp_dec_float][2.95848 (0.0223061s)][3.33461 (0.033471s)][3.0159 (0.132732s)]] | |
4874 | [[gmp_float][[*1] (0.00753971s)][[*1] (0.0100374s)][[*1] (0.0440106s)]] | |
4875 | [[mpfr_float][1.25424 (0.00945658s)][1.24943 (0.012541s)][1.09428 (0.0481601s)]] | |
4876 | ] | |
4877 | ||
4878 | Test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
4879 | turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit | |
4880 | Windows Vista machine. | |
4881 | ||
4882 | [endsect] | |
4883 | ||
4884 | [section:integer_performance Integer Algorithm Performance] | |
4885 | ||
4886 | Note that these tests are carefully designed to test performance of the underlying algorithms | |
4887 | and not memory allocation or variable copying. As usual, performance results should be taken | |
4888 | with a healthy dose of scepticism, and real-world performance may vary widely depending upon the | |
4889 | specifics of the program. In each table relative times are given first, with the best performer | |
4890 | given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 | |
4891 | operations. | |
4892 | ||
4893 | [table Operator + | |
4894 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4895 | [[cpp_int][1.23704 (0.0274266s)][1.09358 (0.0383278s)][1.26645 (0.0558828s)][1.32188 (0.0916899s)]] | |
4896 | [[cpp_int(fixed)][1.62044 (0.0359271s)][1.5277 (0.053543s)][1.73059 (0.076363s)][1.71537 (0.118983s)]] | |
4897 | [[gmp_int][1.87515 (0.0415741s)][1.21699 (0.042653s)][1.15599 (0.0510088s)][[*1] (0.0693631s)]] | |
4898 | [[tommath_int][[*1] (0.0221711s)][[*1] (0.035048s)][[*1] (0.0441255s)][1.04441 (0.0724435s)]] | |
4899 | ] | |
4900 | [table Operator +(int) | |
4901 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4902 | [[cpp_int][[*1] (0.0155377s)][[*1] (0.0209523s)][[*1] (0.0306377s)][[*1] (0.043125s)]] | |
4903 | [[cpp_int(fixed)][1.31904 (0.0204948s)][1.76211 (0.0369203s)][1.52941 (0.0468577s)][1.60412 (0.0691778s)]] | |
4904 | [[gmp_int][1.96204 (0.0304855s)][2.02569 (0.0424428s)][2.11505 (0.0648002s)][2.65993 (0.114709s)]] | |
4905 | [[tommath_int][14.0654 (0.218543s)][10.8239 (0.226786s)][7.76691 (0.23796s)][6.10039 (0.263079s)]] | |
4906 | ] | |
4907 | [table Operator +(unsigned long long) | |
4908 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4909 | [[cpp_int][[*1] (0.026624s)][[*1] (0.0291407s)][[*1] (0.0373209s)][[*1] (0.0464919s)]] | |
4910 | [[cpp_int(fixed)][1.31378 (0.034978s)][1.54897 (0.045138s)][1.53649 (0.0573431s)][1.27833 (0.0594319s)]] | |
4911 | [[gmp_int][25.5775 (0.680974s)][24.0117 (0.699717s)][19.5633 (0.730121s)][16.8939 (0.785432s)]] | |
4912 | [[tommath_int][19.4694 (0.518354s)][18.4246 (0.536907s)][14.7715 (0.551288s)][12.3637 (0.574812s)]] | |
4913 | ] | |
4914 | [table Operator +=(unsigned long long) | |
4915 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4916 | [[cpp_int][1.18405 (0.0196905s)][1.22304 (0.0206476s)][1.25861 (0.0217397s)][1.29525 (0.0220829s)]] | |
4917 | [[cpp_int(fixed)][[*1] (0.0166298s)][[*1] (0.0168822s)][[*1] (0.0172728s)][[*1] (0.0170492s)]] | |
4918 | [[gmp_int][39.9082 (0.663668s)][39.4584 (0.666147s)][38.5504 (0.665873s)][39.2231 (0.668722s)]] | |
4919 | [[tommath_int][30.6219 (0.509238s)][30.4135 (0.513447s)][30.9077 (0.533863s)][32.3086 (0.550835s)]] | |
4920 | ] | |
4921 | [table Operator - | |
4922 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4923 | [[cpp_int][1.06986 (0.0296064s)][[*1] (0.0381508s)][1.05932 (0.053186s)][1.1766 (0.0844721s)]] | |
4924 | [[cpp_int(fixed)][1.3304 (0.0368163s)][1.44506 (0.0551303s)][1.4431 (0.0724545s)][1.57255 (0.112898s)]] | |
4925 | [[gmp_int][1.48072 (0.0409761s)][1.19003 (0.0454007s)][1.0794 (0.0541942s)][[*1] (0.0717934s)]] | |
4926 | [[tommath_int][[*1] (0.0276731s)][1.10891 (0.0423057s)][[*1] (0.0502076s)][1.08479 (0.0778811s)]] | |
4927 | ] | |
4928 | [table Operator -(int) | |
4929 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4930 | [[cpp_int][[*1] (0.0147372s)][[*1] (0.0170001s)][[*1] (0.0232882s)][[*1] (0.0310734s)]] | |
4931 | [[cpp_int(fixed)][1.4267 (0.0210256s)][1.98887 (0.0338109s)][1.83788 (0.0428009s)][1.81269 (0.0563264s)]] | |
4932 | [[gmp_int][2.07504 (0.0305803s)][2.40928 (0.0409579s)][2.58711 (0.0602493s)][3.26438 (0.101435s)]] | |
4933 | [[tommath_int][13.5424 (0.199577s)][12.1793 (0.207048s)][9.28855 (0.216314s)][7.49327 (0.232842s)]] | |
4934 | ] | |
4935 | [table Operator -(unsigned long long) | |
4936 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4937 | [[cpp_int][[*1] (0.0277377s)][[*1] (0.0296807s)][[*1] (0.0372392s)][[*1] (0.0455855s)]] | |
4938 | [[cpp_int(fixed)][1.19867 (0.0332484s)][1.48639 (0.0441169s)][1.43253 (0.0533464s)][1.27697 (0.0582111s)]] | |
4939 | [[gmp_int][24.1794 (0.670683s)][22.9073 (0.679904s)][18.8758 (0.702922s)][16.5837 (0.755975s)]] | |
4940 | [[tommath_int][18.149 (0.503413s)][17.4116 (0.516787s)][14.0411 (0.52288s)][11.8237 (0.538987s)]] | |
4941 | ] | |
4942 | [table Operator -=(unsigned long long) | |
4943 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4944 | [[cpp_int][1.26896 (0.0203467s)][1.25722 (0.0206147s)][1.36108 (0.0225485s)][1.18351 (0.0226161s)]] | |
4945 | [[cpp_int(fixed)][[*1] (0.0160342s)][[*1] (0.0163971s)][[*1] (0.0165667s)][[*1] (0.0191094s)]] | |
4946 | [[gmp_int][41.1339 (0.659547s)][40.3982 (0.662411s)][39.925 (0.661425s)][34.636 (0.661874s)]] | |
4947 | [[tommath_int][31.1543 (0.499533s)][31.0303 (0.508806s)][30.7699 (0.509756s)][27.7054 (0.529434s)]] | |
4948 | ] | |
4949 | [table Operator * | |
4950 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4951 | [[cpp_int][1.11839 (0.0757577s)][1.61061 (0.207951s)][1.4501 (0.696912s)][1.72796 (2.64108s)]] | |
4952 | [[cpp_int(fixed)][1.01115 (0.0684934s)][1.28687 (0.166152s)][[*1] (0.480595s)][[*1] (1.52844s)]] | |
4953 | [[gmp_int][[*1] (0.0677384s)][[*1] (0.129113s)][1.09011 (0.523902s)][1.03374 (1.58s)]] | |
4954 | [[tommath_int][1.6322 (0.110562s)][2.71751 (0.350866s)][2.05222 (0.986288s)][2.0644 (3.15531s)]] | |
4955 | ] | |
4956 | [table Operator *(int) | |
4957 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4958 | [[cpp_int][1.01611 (0.0229536s)][1.12175 (0.0298152s)][1.16413 (0.0416439s)][1.31747 (0.0666043s)]] | |
4959 | [[cpp_int(fixed)][1.30215 (0.0294152s)][1.669 (0.0443606s)][1.72395 (0.0616701s)][1.88315 (0.095202s)]] | |
4960 | [[gmp_int][[*1] (0.0225897s)][[*1] (0.0265791s)][[*1] (0.0357725s)][[*1] (0.0505547s)]] | |
4961 | [[tommath_int][10.8281 (0.244603s)][10.1516 (0.26982s)][8.76424 (0.313519s)][8.04364 (0.406644s)]] | |
4962 | ] | |
4963 | [table Operator *(unsigned long long) | |
4964 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4965 | [[cpp_int][[*1] (0.0570721s)][[*1] (0.0856141s)][[*1] (0.143279s)][[*1] (0.252785s)]] | |
4966 | [[cpp_int(fixed)][1.10857 (0.0632686s)][1.2951 (0.110878s)][1.20827 (0.173121s)][1.18463 (0.299456s)]] | |
4967 | [[gmp_int][12.0605 (0.68832s)][8.13434 (0.696415s)][5.21762 (0.747577s)][3.11601 (0.787681s)]] | |
4968 | [[tommath_int][10.0524 (0.57371s)][7.33116 (0.627651s)][4.85202 (0.695193s)][3.35808 (0.848871s)]] | |
4969 | ] | |
4970 | [table Operator *=(unsigned long long) | |
4971 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4972 | [[cpp_int][111.27 (7.43118s)][67.7078 (7.34138s)][43.3851 (7.4075s)][25.3089 (7.55455s)]] | |
4973 | [[cpp_int(fixed)][[*1] (0.0667848s)][[*1] (0.108427s)][[*1] (0.170738s)][[*1] (0.298493s)]] | |
4974 | [[gmp_int][46.3718 (3.09693s)][28.4639 (3.08626s)][18.1719 (3.10264s)][10.5223 (3.14083s)]] | |
4975 | [[tommath_int][276.674 (18.4776s)][169.146 (18.34s)][108.491 (18.5236s)][63.3261 (18.9024s)]] | |
4976 | ] | |
4977 | [table Operator / | |
4978 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4979 | [[cpp_int][2.68035 (0.595251s)][2.04702 (0.707471s)][1.62314 (0.921536s)][1.43112 (1.38811s)]] | |
4980 | [[cpp_int(fixed)][[*1] (0.222079s)][[*1] (0.34561s)][[*1] (0.567748s)][[*1] (0.969945s)]] | |
4981 | [[gmp_int][3.79283 (0.842308s)][2.73668 (0.945824s)][1.86649 (1.05969s)][1.32141 (1.2817s)]] | |
4982 | [[tommath_int][13.2531 (2.94324s)][11.2054 (3.87271s)][9.83293 (5.58262s)][13.0164 (12.6252s)]] | |
4983 | ] | |
4984 | [table Operator /(int) | |
4985 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4986 | [[cpp_int][4.06026 (0.225473s)][3.45732 (0.340049s)][3.00195 (0.547957s)][2.80587 (0.978029s)]] | |
4987 | [[cpp_int(fixed)][2.43766 (0.135367s)][2.56264 (0.252052s)][2.44011 (0.445402s)][2.38009 (0.829617s)]] | |
4988 | [[gmp_int][[*1] (0.0555316s)][[*1] (0.0983563s)][[*1] (0.182534s)][[*1] (0.348566s)]] | |
4989 | [[tommath_int][35.9988 (1.99907s)][27.1024 (2.66569s)][21.8333 (3.98531s)][25.8066 (8.99528s)]] | |
4990 | ] | |
4991 | [table Operator /(unsigned long long) | |
4992 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
4993 | [[cpp_int][1.50505 (0.705756s)][1.39347 (1.58556s)][2.63348 (3.57438s)][4.75451 (8.52733s)]] | |
4994 | [[cpp_int(fixed)][[*1] (0.468925s)][1.12378 (1.27869s)][2.29966 (3.12128s)][4.4844 (8.04288s)]] | |
4995 | [[gmp_int][2.17234 (1.01866s)][[*1] (1.13785s)][[*1] (1.35728s)][[*1] (1.79352s)]] | |
4996 | [[tommath_int][4.74612 (2.22557s)][2.70088 (3.07319s)][3.65634 (4.96268s)][6.79408 (12.1853s)]] | |
4997 | ] | |
4998 | [table Operator /=(unsigned long long) | |
4999 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5000 | [[cpp_int][1.76281 (0.0574966s)][1.76471 (0.0604224s)][1.56085 (0.0716403s)][1.31422 (0.124043s)]] | |
5001 | [[cpp_int(fixed)][[*1] (0.0326164s)][[*1] (0.0342393s)][[*1] (0.0458981s)][[*1] (0.0943852s)]] | |
5002 | [[gmp_int][20.2862 (0.661664s)][19.4043 (0.664389s)][14.4881 (0.664976s)][7.14238 (0.674135s)]] | |
5003 | [[tommath_int][32.9555 (1.07489s)][30.1525 (1.0324s)][22.8324 (1.04796s)][11.7456 (1.10861s)]] | |
5004 | ] | |
5005 | [table Operator % | |
5006 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5007 | [[cpp_int][1.8501 (0.364131s)][1.46527 (0.476653s)][1.27509 (0.689738s)][1.20064 (1.11769s)]] | |
5008 | [[cpp_int(fixed)][[*1] (0.196817s)][[*1] (0.325301s)][[*1] (0.540932s)][[*1] (0.930916s)]] | |
5009 | [[gmp_int][3.2533 (0.640305s)][2.15441 (0.700832s)][1.47898 (0.800029s)][1.07439 (1.00016s)]] | |
5010 | [[tommath_int][15.3501 (3.02116s)][12.1106 (3.9396s)][11.0689 (5.98752s)][13.5535 (12.6172s)]] | |
5011 | ] | |
5012 | [table Operator %(int) | |
5013 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5014 | [[cpp_int][1.82761 (0.104331s)][2.01496 (0.202512s)][2.10004 (0.389523s)][2.17252 (0.768097s)]] | |
5015 | [[cpp_int(fixed)][1.78851 (0.102099s)][1.96844 (0.197838s)][2.02956 (0.376451s)][2.07257 (0.73276s)]] | |
5016 | [[gmp_int][[*1] (0.057086s)][[*1] (0.100505s)][[*1] (0.185483s)][[*1] (0.353552s)]] | |
5017 | [[tommath_int][36.3018 (2.07233s)][26.3075 (2.64402s)][21.9525 (4.07183s)][25.6759 (9.07775s)]] | |
5018 | ] | |
5019 | [table Operator construct | |
5020 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5021 | [[cpp_int][1.40211 (0.0026854s)][[*1] (0.00278639s)][[*1] (0.00322813s)][[*1] (0.0027185s)]] | |
5022 | [[cpp_int(fixed)][[*1] (0.00191526s)][1.40721 (0.00392103s)][1.90346 (0.00614463s)][2.14621 (0.00583447s)]] | |
5023 | [[gmp_int][98.705 (0.189046s)][68.9726 (0.192184s)][58.8994 (0.190135s)][70.0525 (0.190438s)]] | |
5024 | [[tommath_int][105.602 (0.202255s)][74.1994 (0.206748s)][63.6455 (0.205456s)][76.8935 (0.209035s)]] | |
5025 | ] | |
5026 | [table Operator construct(unsigned) | |
5027 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5028 | [[cpp_int][1.73436 (0.00348927s)][[*1] (0.00263476s)][[*1] (0.0027009s)][[*1] (0.00318651s)]] | |
5029 | [[cpp_int(fixed)][[*1] (0.00201185s)][1.36851 (0.0036057s)][2.07362 (0.00560064s)][1.66856 (0.00531688s)]] | |
5030 | [[gmp_int][97.2414 (0.195635s)][76.3759 (0.201232s)][72.7396 (0.196462s)][63.8129 (0.20334s)]] | |
5031 | [[tommath_int][210.112 (0.422713s)][162.652 (0.42855s)][158.33 (0.427634s)][134.626 (0.428987s)]] | |
5032 | ] | |
5033 | [table Operator construct(unsigned long long) | |
5034 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5035 | [[cpp_int][2.34403 (0.00739542s)][1.66376 (0.00713834s)][1.22989 (0.0074969s)][1.23708 (0.00711417s)]] | |
5036 | [[cpp_int(fixed)][[*1] (0.00315501s)][[*1] (0.00429049s)][[*1] (0.00609561s)][[*1] (0.0057508s)]] | |
5037 | [[gmp_int][222.866 (0.703144s)][164.331 (0.705059s)][115.363 (0.70321s)][122.347 (0.703596s)]] | |
5038 | [[tommath_int][218.681 (0.689941s)][163.796 (0.702765s)][114.57 (0.698376s)][122.422 (0.704027s)]] | |
5039 | ] | |
5040 | [table Operator gcd | |
5041 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5042 | [[cpp_int][1.16358 (2.74442s)][1.39847 (8.11559s)][1.64677 (22.2518s)][1.95096 (64.4961s)]] | |
5043 | [[cpp_int(fixed)][[*1] (2.35859s)][1.30986 (7.60133s)][1.67681 (22.6577s)][2.0895 (69.0758s)]] | |
5044 | [[gmp_int][1.03392 (2.4386s)][[*1] (5.80319s)][[*1] (13.5124s)][[*1] (33.0586s)]] | |
5045 | [[tommath_int][5.25978 (12.4057s)][4.4619 (25.8932s)][4.15577 (56.1542s)][3.91192 (129.323s)]] | |
5046 | ] | |
5047 | [table Operator powm | |
5048 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5049 | [[cpp_int][2.50722 (2.91621s)][3.5561 (13.406s)][4.37066 (73.483s)][4.88831 (473.91s)]] | |
5050 | [[cpp_int(fixed)][1.93385 (2.24931s)][3.18107 (11.9922s)][4.20753 (70.7403s)][4.8158 (466.88s)]] | |
5051 | [[gmp_int][[*1] (1.16313s)][[*1] (3.76986s)][[*1] (16.8128s)][[*1] (96.9476s)]] | |
5052 | [[tommath_int][1.44081 (1.67584s)][1.8794 (7.08507s)][2.19115 (36.8394s)][2.17186 (210.557s)]] | |
5053 | ] | |
5054 | [table Operator str | |
5055 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5056 | [[cpp_int][1.17175 (0.00160006s)][1.41999 (0.00329476s)][1.40856 (0.00813784s)][1.52964 (0.0229767s)]] | |
5057 | [[cpp_int(fixed)][[*1] (0.00136554s)][[*1] (0.00232027s)][[*1] (0.00577741s)][1.14754 (0.0172372s)]] | |
5058 | [[gmp_int][1.50501 (0.00205515s)][1.52968 (0.00354926s)][1.01989 (0.0058923s)][[*1] (0.015021s)]] | |
5059 | [[tommath_int][12.2161 (0.0166816s)][16.9577 (0.0393463s)][18.7474 (0.108311s)][22.7368 (0.341528s)]] | |
5060 | ] | |
5061 | [table Operator | | |
5062 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5063 | [[cpp_int][[*1] (0.0301617s)][[*1] (0.0423404s)][[*1] (0.0522358s)][[*1] (0.0813156s)]] | |
5064 | [[cpp_int(fixed)][1.0638 (0.0320861s)][1.22566 (0.0518951s)][1.28515 (0.0671305s)][1.16118 (0.094422s)]] | |
5065 | [[gmp_int][1.76553 (0.0532514s)][1.51489 (0.0641408s)][1.70708 (0.0891706s)][1.77346 (0.14421s)]] | |
5066 | [[tommath_int][4.37637 (0.131999s)][3.46212 (0.146587s)][2.91875 (0.152463s)][4.19621 (0.341217s)]] | |
5067 | ] | |
5068 | [table Operator |(int) | |
5069 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5070 | [[cpp_int][[*1] (0.0289129s)][[*1] (0.0351119s)][[*1] (0.0406779s)][[*1] (0.0525891s)]] | |
5071 | [[cpp_int(fixed)][1.06091 (0.030674s)][1.25979 (0.0442336s)][1.36194 (0.0554009s)][1.37438 (0.0722772s)]] | |
5072 | [[gmp_int][4.92854 (0.142498s)][4.34687 (0.152627s)][3.71442 (0.151095s)][2.981 (0.156768s)]] | |
5073 | [[tommath_int][10.9847 (0.317598s)][9.37065 (0.329021s)][8.53651 (0.347248s)][11.2155 (0.589813s)]] | |
5074 | ] | |
5075 | [table Operator ^ | |
5076 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5077 | [[cpp_int][[*1] (0.0305149s)][[*1] (0.04217s)][[*1] (0.0525977s)][[*1] (0.0816632s)]] | |
5078 | [[cpp_int(fixed)][1.01544 (0.0309861s)][1.24872 (0.0526585s)][1.26661 (0.066621s)][1.15965 (0.0947007s)]] | |
5079 | [[gmp_int][1.64675 (0.0502505s)][1.47181 (0.0620663s)][1.66038 (0.0873322s)][1.67895 (0.137108s)]] | |
5080 | [[tommath_int][4.30668 (0.131418s)][3.45859 (0.145849s)][2.91462 (0.153303s)][4.15538 (0.339342s)]] | |
5081 | ] | |
5082 | [table Operator ^(int) | |
5083 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5084 | [[cpp_int][1.01566 (0.0296088s)][[*1] (0.0356634s)][[*1] (0.0401898s)][[*1] (0.0514097s)]] | |
5085 | [[cpp_int(fixed)][[*1] (0.0291524s)][1.2393 (0.0441976s)][1.38556 (0.0556856s)][1.38899 (0.0714075s)]] | |
5086 | [[gmp_int][4.68027 (0.136441s)][4.15243 (0.14809s)][3.74237 (0.150405s)][3.0483 (0.156712s)]] | |
5087 | [[tommath_int][10.919 (0.318314s)][9.16311 (0.326788s)][8.62554 (0.346659s)][11.6212 (0.597442s)]] | |
5088 | ] | |
5089 | [table Operator & | |
5090 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5091 | [[cpp_int][1.0346 (0.0303431s)][[*1] (0.0427309s)][[*1] (0.0535587s)][1.06945 (0.0828084s)]] | |
5092 | [[cpp_int(fixed)][[*1] (0.0293284s)][1.10435 (0.04719s)][1.05262 (0.0563769s)][[*1] (0.0774309s)]] | |
5093 | [[gmp_int][1.86057 (0.0545675s)][1.58432 (0.0676995s)][1.69164 (0.0906018s)][1.86625 (0.144505s)]] | |
5094 | [[tommath_int][4.4157 (0.129506s)][3.60396 (0.154s)][2.95985 (0.158525s)][4.4032 (0.340944s)]] | |
5095 | ] | |
5096 | [table Operator &(int) | |
5097 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5098 | [[cpp_int][1.05874 (0.038946s)][[*1] (0.0483903s)][[*1] (0.063842s)][[*1] (0.100361s)]] | |
5099 | [[cpp_int(fixed)][[*1] (0.0367853s)][1.05827 (0.0512099s)][1.09114 (0.0696605s)][1.09432 (0.109826s)]] | |
5100 | [[gmp_int][3.92298 (0.144308s)][2.99447 (0.144903s)][2.228 (0.14224s)][1.42296 (0.142809s)]] | |
5101 | [[tommath_int][8.79208 (0.323419s)][7.02288 (0.339839s)][5.65271 (0.36088s)][6.27104 (0.629365s)]] | |
5102 | ] | |
5103 | [table Operator << | |
5104 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5105 | [[cpp_int][[*1] (0.0248801s)][1.23196 (0.04s)][[*1] (0.0424149s)][[*1] (0.060157s)]] | |
5106 | [[cpp_int(fixed)][1.08931 (0.027102s)][1.40572 (0.0456418s)][1.3475 (0.0571542s)][1.24573 (0.0749397s)]] | |
5107 | [[gmp_int][1.05561 (0.0262636s)][[*1] (0.0324686s)][1.09914 (0.0466199s)][1.16315 (0.0699719s)]] | |
5108 | [[tommath_int][1.60497 (0.0399319s)][2.13048 (0.0691737s)][2.31219 (0.0980712s)][2.74695 (0.165248s)]] | |
5109 | ] | |
5110 | [table Operator >> | |
5111 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5112 | [[cpp_int][[*1] (0.0213349s)][1.02127 (0.0295019s)][[*1] (0.0327116s)][1.13168 (0.0433804s)]] | |
5113 | [[cpp_int(fixed)][1.13514 (0.0242181s)][1.16938 (0.0337803s)][1.46999 (0.0480859s)][1.60077 (0.061362s)]] | |
5114 | [[gmp_int][1.26614 (0.0270129s)][[*1] (0.0288873s)][1.42219 (0.0465221s)][[*1] (0.0383329s)]] | |
5115 | [[tommath_int][12.0066 (0.25616s)][10.2837 (0.297067s)][9.99696 (0.327017s)][16.0943 (0.616942s)]] | |
5116 | ] | |
5117 | ||
5118 | Test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
5119 | turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit | |
5120 | Windows Vista machine. | |
5121 | ||
5122 | Linux x86_64 results are broadly similar, except that libtommath performs much better there. | |
5123 | ||
5124 | [endsect] | |
5125 | ||
5126 | [section:rational_performance Rational Type Performance] | |
5127 | ||
5128 | Note that these tests are carefully designed to test performance of the underlying algorithms | |
5129 | and not memory allocation or variable copying. As usual, performance results should be taken | |
5130 | with a healthy dose of scepticism, and real-world performance may vary widely depending upon the | |
5131 | specifics of the program. In each table relative times are given first, with the best performer | |
5132 | given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 | |
5133 | operations. | |
5134 | ||
5135 | [table Operator + | |
5136 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5137 | [[cpp_rational][5.89417 (18.4116s)][6.87256 (47.4698s)][6.65008 (107.715s)][6.53801 (256.244s)]] | |
5138 | [[mpq_rational][[*1] (3.1237s)][[*1] (6.90715s)][[*1] (16.1975s)][[*1] (39.1929s)]] | |
5139 | ] | |
5140 | [table Operator +(int) | |
5141 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5142 | [[cpp_rational][3.62367 (2.46488s)][4.18291 (2.94603s)][4.726 (3.74866s)][6.1388 (5.56817s)]] | |
5143 | [[mpq_rational][[*1] (0.680215s)][[*1] (0.704303s)][[*1] (0.7932s)][[*1] (0.907046s)]] | |
5144 | ] | |
5145 | [table Operator +(unsigned long long) | |
5146 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5147 | [[cpp_rational][1.1527 (2.6378s)][1.31751 (3.09863s)][1.58996 (4.00714s)][2.15642 (5.75702s)]] | |
5148 | [[mpq_rational][[*1] (2.28837s)][[*1] (2.35189s)][[*1] (2.52028s)][[*1] (2.66971s)]] | |
5149 | ] | |
5150 | [table Operator +=(unsigned long long) | |
5151 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5152 | [[cpp_rational][1.18436 (2.7059s)][1.32279 (3.11099s)][1.61398 (4.05389s)][2.20048 (5.84623s)]] | |
5153 | [[mpq_rational][[*1] (2.2847s)][[*1] (2.35183s)][[*1] (2.51174s)][[*1] (2.6568s)]] | |
5154 | ] | |
5155 | [table Operator - | |
5156 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5157 | [[cpp_rational][5.81893 (18.3457s)][6.82209 (47.1928s)][6.64143 (107.498s)][6.51362 (255.137s)]] | |
5158 | [[mpq_rational][[*1] (3.15277s)][[*1] (6.91765s)][[*1] (16.1859s)][[*1] (39.1698s)]] | |
5159 | ] | |
5160 | [table Operator -(int) | |
5161 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5162 | [[cpp_rational][3.72441 (2.48756s)][4.27663 (2.98713s)][4.62109 (3.72114s)][6.17605 (5.56503s)]] | |
5163 | [[mpq_rational][[*1] (0.667908s)][[*1] (0.698479s)][[*1] (0.805252s)][[*1] (0.901066s)]] | |
5164 | ] | |
5165 | [table Operator -(unsigned long long) | |
5166 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5167 | [[cpp_rational][1.15627 (2.63239s)][1.32096 (3.12092s)][1.61044 (4.00106s)][2.19378 (5.7644s)]] | |
5168 | [[mpq_rational][[*1] (2.27663s)][[*1] (2.36262s)][[*1] (2.48445s)][[*1] (2.62761s)]] | |
5169 | ] | |
5170 | [table Operator -=(unsigned long long) | |
5171 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5172 | [[cpp_rational][1.1984 (2.73444s)][1.34141 (3.15698s)][1.64159 (4.06997s)][2.23017 (5.88108s)]] | |
5173 | [[mpq_rational][[*1] (2.28174s)][[*1] (2.35348s)][[*1] (2.47929s)][[*1] (2.63706s)]] | |
5174 | ] | |
5175 | [table Operator * | |
5176 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5177 | [[cpp_rational][5.4306 (32.5882s)][6.91805 (89.9436s)][6.94556 (207.307s)][6.88704 (492.151s)]] | |
5178 | [[mpq_rational][[*1] (6.00084s)][[*1] (13.0013s)][[*1] (29.8475s)][[*1] (71.4604s)]] | |
5179 | ] | |
5180 | [table Operator *(int) | |
5181 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5182 | [[cpp_rational][2.12892 (2.51376s)][2.47245 (3.07841s)][2.86832 (3.93619s)][3.94086 (6.02565s)]] | |
5183 | [[mpq_rational][[*1] (1.18077s)][[*1] (1.24508s)][[*1] (1.3723s)][[*1] (1.52902s)]] | |
5184 | ] | |
5185 | [table Operator *(unsigned long long) | |
5186 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5187 | [[cpp_rational][1.32254 (5.43565s)][1.56078 (6.73163s)][1.97701 (9.32522s)][2.85404 (15.1573s)]] | |
5188 | [[mpq_rational][[*1] (4.11002s)][[*1] (4.313s)][[*1] (4.71682s)][[*1] (5.31082s)]] | |
5189 | ] | |
5190 | [table Operator *=(unsigned long long) | |
5191 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5192 | [[cpp_rational][6.29806 (58.1188s)][6.30556 (59.5076s)][6.3385 (62.1007s)][6.55345 (67.6905s)]] | |
5193 | [[mpq_rational][[*1] (9.22804s)][[*1] (9.43733s)][[*1] (9.79739s)][[*1] (10.329s)]] | |
5194 | ] | |
5195 | [table Operator / | |
5196 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5197 | [[cpp_rational][4.4269 (66.8031s)][6.40103 (173.527s)][6.32347 (348.193s)][6.61148 (824.063s)]] | |
5198 | [[mpq_rational][[*1] (15.0903s)][[*1] (27.1093s)][[*1] (55.0637s)][[*1] (124.641s)]] | |
5199 | ] | |
5200 | [table Operator /(int) | |
5201 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5202 | [[cpp_rational][1.78772 (2.50984s)][2.10623 (3.10606s)][2.46986 (3.99358s)][3.37428 (5.96678s)]] | |
5203 | [[mpq_rational][[*1] (1.40393s)][[*1] (1.4747s)][[*1] (1.61693s)][[*1] (1.76831s)]] | |
5204 | ] | |
5205 | [table Operator /(unsigned long long) | |
5206 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5207 | [[cpp_rational][1.29695 (5.45454s)][1.55248 (6.85353s)][1.93237 (9.28765s)][2.75211 (14.8541s)]] | |
5208 | [[mpq_rational][[*1] (4.20568s)][[*1] (4.41458s)][[*1] (4.80635s)][[*1] (5.39734s)]] | |
5209 | ] | |
5210 | [table Operator /=(unsigned long long) | |
5211 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5212 | [[cpp_rational][6.19401 (58.4278s)][6.20135 (59.643s)][6.21327 (62.0338s)][6.40576 (67.6778s)]] | |
5213 | [[mpq_rational][[*1] (9.43295s)][[*1] (9.61774s)][[*1] (9.98407s)][[*1] (10.5652s)]] | |
5214 | ] | |
5215 | [table Operator construct | |
5216 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5217 | [[cpp_rational][[*1] (0.00978288s)][[*1] (0.0100574s)][[*1] (0.0101393s)][[*1] (0.0101847s)]] | |
5218 | [[mpq_rational][39.1516 (0.383015s)][38.3523 (0.385725s)][37.5812 (0.381048s)][37.6007 (0.382953s)]] | |
5219 | ] | |
5220 | [table Operator construct(unsigned) | |
5221 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5222 | [[cpp_rational][[*1] (0.0548151s)][[*1] (0.0557542s)][[*1] (0.055825s)][[*1] (0.0552808s)]] | |
5223 | [[mpq_rational][7.21073 (0.395257s)][7.1016 (0.395944s)][7.02046 (0.391917s)][7.16881 (0.396297s)]] | |
5224 | ] | |
5225 | [table Operator construct(unsigned long long) | |
5226 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5227 | [[cpp_rational][[*1] (0.0605156s)][[*1] (0.0616657s)][[*1] (0.0592056s)][[*1] (0.0603081s)]] | |
5228 | [[mpq_rational][35.1604 (2.12775s)][34.7575 (2.14335s)][35.7232 (2.11502s)][35.0437 (2.11342s)]] | |
5229 | ] | |
5230 | [table Operator str | |
5231 | [[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] | |
5232 | [[cpp_rational][5.48898 (0.0208949s)][8.49668 (0.0546688s)][10.107 (0.121897s)][10.5339 (0.310584s)]] | |
5233 | [[mpq_rational][[*1] (0.0038067s)][[*1] (0.00643413s)][[*1] (0.0120606s)][[*1] (0.0294843s)]] | |
5234 | ] | |
5235 | ||
5236 | Test code was compiled with Microsoft Visual Studio 2010 with all optimisations | |
5237 | turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit | |
5238 | Windows Vista machine. | |
5239 | ||
5240 | [endsect] | |
5241 | ||
5242 | [endsect] | |
5243 | ||
5244 | [section:map Roadmap] | |
5245 | ||
5246 | [section:hist History] | |
5247 | ||
5248 | [h4 Multiprecision-2.3.0 (Boost-1.63)] | |
5249 | ||
5250 | * Added support for all the C99 math functions. | |
5251 | * Extended generic-interconversions to handle narrowing cases as well, changed convert_to member function and hence explicit | |
5252 | conversion operators to use the same conversion code as the explicit constructors. | |
5253 | * Fix IO stream parsing error, see [@https://svn.boost.org/trac/boost/ticket/12488 #12488]. | |
5254 | * Make default constructed floating point types all zero for consistency, see [@https://svn.boost.org/trac/boost/ticket/12500 #12500]. | |
5255 | * Fix conversion of cpp_bin_float to float/double/long double when the exponent value would overflow an int, see [@https://svn.boost.org/trac/boost/ticket/12512 #12512]. | |
5256 | * Fix cpp_bin_float subtractions that yield signed-zeros, see [@https://svn.boost.org/trac/boost/ticket/12524 #12524]. | |
5257 | * Fix ceil/trunc/round applied to cpp_bin_float and yielding a signed zero, see [@https://svn.boost.org/trac/boost/ticket/12525 #12525]. | |
5258 | ||
5259 | [h4 Multiprecision-2.2.8 (Boost-1.62)] | |
5260 | ||
5261 | * Added support for hashing via `Boost.Hash` or `std::hash`. | |
5262 | * Fixed some arithmetic operations in cpp_bin_float and cpp_dec_float that should generate a NaN, see [@https://svn.boost.org/trac/boost/ticket/12157 #12157]. | |
5263 | * Prevent inadvertant instantiation of variable-precision `mpfr_float_backend` with fixed allocation. | |
5264 | * Fixed division over/underflow in cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12167 #12167]. | |
5265 | * Added support for signed-zeros throughout the library, including support for `signbit` and `copysign`, mpfr, float128, and cpp_bin_float types | |
5266 | should now respect signed-zeros correctly. | |
5267 | * Fixed bug in conversion of cpp_bin_float infinities to double etc, see [@https://svn.boost.org/trac/boost/ticket/12196 #12196]. | |
5268 | * Fix add and subtract of cpp_bin_float when the exponents would overflow., see [@https://svn.boost.org/trac/boost/ticket/12198 #12198]. | |
5269 | * Improve variable-precision support in mpfr and mpf backends, allow these types to be used with Boost.Math. | |
5270 | * Fixed bug in subtraction of signed infinities in cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12209 #12209]. | |
5271 | * Fix result of sqrt(infinity) in cpp_bin_float (result should be infinity), see [@https://svn.boost.org/trac/boost/ticket/12227 #12227]. | |
5272 | * Added workaround in gmp.hpp for recent MPIR releases which are not quite source-compatible with GMP on Windows x64. | |
5273 | * Allow `cpp_int` code to be used with /RTCc with MSVC. | |
5274 | * Fix conversion of `cpp_int` to signed integer when the result is INT_MIN, see [@https://svn.boost.org/trac/boost/ticket/12343 #12343]. | |
5275 | * Update uBlas support to match latest uBlas code. | |
5276 | * Fix some errors present when building on big-endian machines (not all `cpp_int` constructors are available on non-little-endian machines). | |
5277 | * Fix fencepost error in rational to float conversion routines, see [@https://svn.boost.org/trac/boost/ticket/12327 #12327]. | |
5278 | * Fix some Oracle C++ compiler compatibility issues. | |
5279 | * Add modf support to complete C90 compatibility. | |
5280 | * Fix self assignment bug in expression template code for expressions such as `a = a * a * a`, see [@https://svn.boost.org/trac/boost/ticket/12408 #12408]. | |
5281 | * Fixed some compiler errors that occur when converting from `cpp_int` to `cpp_bin_float`. | |
5282 | ||
5283 | [h4 Multiprecision-2.2.7 (Boost-1.61)] | |
5284 | ||
5285 | * Fixed bug in stream input for integer types, see [@https://svn.boost.org/trac/boost/ticket/11857 #11857]. | |
5286 | * Fixed some ambiguous conversions involving expression templates see [@https://svn.boost.org/trac/boost/ticket/11922 #11922]. | |
5287 | * Add expression template aware min/max overloads see [@https://svn.boost.org/trac/boost/ticket/11149 #11149]. | |
5288 | * Fix bug in right shifting negative small integers in cpp_int see [@https://svn.boost.org/trac/boost/ticket/11999 #11999]. | |
5289 | * Use memmove for bitshifts in cpp_int when possible see [@https://svn.boost.org/trac/boost/ticket/9233 #9233]. | |
5290 | * Use memcpy for data import into cpp_int where possible, see [@https://svn.boost.org/trac/boost/ticket/9235 #9235]. | |
5291 | * Changed `cpp_bin_float.convert_to<double>()` to a function template rather than proceding via `long double` to avoid | |
5292 | double-rounding bug, see [@https://svn.boost.org/trac/boost/ticket/12039 #12039]. | |
5293 | * Fixed conversions from NaN's and Infinities, see [@https://svn.boost.org/trac/boost/ticket/12112 #12112]. | |
5294 | * Enabled better support for Clang on Windows. | |
5295 | * Fixed handling of NaN's and Infinities in basic arithmetic for cpp_dec_float and cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12090 #12090]. | |
5296 | * Fixed fencepost error in cpp_bin_float subtraction. | |
5297 | * Fixed double-rounding in conversion to float routines for cpp_bin_float, see [@https://svn.boost.org/trac/boost/ticket/12039 #12039]. | |
5298 | * Make float128 denorm aware, see [@https://svn.boost.org/trac/boost/ticket/12075 #12075]. | |
5299 | * Allow the library and tests to be used without exception handling support, see [@https://svn.boost.org/trac/boost/ticket/12070 #12070]. | |
5300 | * Fixed buggy comparison operator overloads for boost::rational. | |
5301 | * Added some workarounds for Oracle C++. | |
5302 | * Fixed some missing typecasts for cases where cpp_int's limb_type is wider than unsigned. | |
5303 | ||
5304 | ||
5305 | [h4 Multiprecision-2.2.6 (Boost-1.60)] | |
5306 | ||
5307 | * Fixed result of Miller Rabin primality test for value 2, see [@https://svn.boost.org/trac/boost/ticket/11495 #11495]. | |
5308 | * Improved initialization of cpp_int from very large strings of hex or octal digits, see [@https://svn.boost.org/trac/boost/ticket/11590 #11590]. | |
5309 | * Fixed fmod behaviour for negative divisors, see [@https://svn.boost.org/trac/boost/ticket/11641 #11641]. | |
5310 | * Fixed infinite division loop in cpp_int special case, see [@https://svn.boost.org/trac/boost/ticket/11648 #11648]. | |
5311 | * Patched missing return statement in [@https://svn.boost.org/trac/boost/ticket/11762 #11762]. | |
5312 | * Fixed mixed mode arithmetic compiler error in [@https://svn.boost.org/trac/boost/ticket/11764 #11764]. | |
5313 | * Fixed over-aggressive use of noexcept in [@https://svn.boost.org/trac/boost/ticket/11826 #11826]. | |
5314 | ||
5315 | ||
5316 | [h4 Multiprecision-2.2.5 (Boost-1.59)] | |
5317 | ||
5318 | * Depricated boost/multiprecision/random.hpp as it's no longer needed, updated random examples to match. | |
5319 | * Fixed a bug in cpp_int's right shift operator when shifting negative values - semantics now gives the | |
5320 | same values as shifting 2's compliment integers, though not the same bit pattern. | |
5321 | * Fixed support for GCC-4.6.4 in C++0x mode by disabling conditional noexcept suppoprt for that compiler | |
5322 | see [@https://svn.boost.org/trac/boost/ticket/11402 #11402]. | |
5323 | * Suppressed numerous compiler warnings. | |
5324 | ||
5325 | [h4 Multiprecision-2.2.4 (Boost-1.58)] | |
5326 | ||
5327 | * Changed `frexp` to always be non-expression template generating, see: [@https://svn.boost.org/trac/boost/ticket/10993 10993]. | |
5328 | * Improved support of cpp_dec_float on Cygwin and other platforms with missing long double support, see [@https://svn.boost.org/trac/boost/ticket/10924 10924]. | |
5329 | * Improved noexcept support and added some more tests, see [@https://svn.boost.org/trac/boost/ticket/10990 10990]. | |
5330 | * Various workarounds applied for Intel-15.0 and Solaris-12.4 compilers. | |
5331 | ||
5332 | [h4 Multiprecision-2.2.3 (Boost-1.57)] | |
5333 | ||
5334 | * Changed rational to float conversions to exactly round to nearest, see [@https://svn.boost.org/trac/boost/ticket/10085 10085]. | |
5335 | * Added improved generic float to rational conversions. | |
5336 | * Fixed rare bug in exponent function for __cpp_bin_float. | |
5337 | * Fixed various minor documentation issues. | |
5338 | ||
5339 | [h4 Multiprecision-2.2.2 (Boost-1.56)] | |
5340 | ||
5341 | * Change floating-point to rational conversions to be implicit, see [@https://svn.boost.org/trac/boost/ticket/10082 10082]. | |
5342 | * Fix definition of checked_cpp_rational typedef. | |
5343 | ||
5344 | [h4 Multiprecision-2.2.1] | |
5345 | ||
5346 | * Fix bug in assignment from string in cpp_int, see [@https://svn.boost.org/trac/boost/ticket/9936 9936]. | |
5347 | ||
5348 | [h4 Multiprecision-2.2.0] | |
5349 | ||
5350 | * Moved to Boost.Multiprecision specific version number - we have one breaking change in Boost-1.54 | |
5351 | which makes this major version 2, plus two releases with new features since then. | |
5352 | * Added new __cpp_bin_float backend for binary floating-point. | |
5353 | * Added MSVC-specific #include for compiler intrinsics, see [@https://svn.boost.org/trac/boost/ticket/9336 9336]. | |
5354 | * Fixed various typos in docs, see [@https://svn.boost.org/trac/boost/ticket/9432 9432]. | |
5355 | * Fixed __gmp_rational to allow move-copy from an already copied-from object, see [@https://svn.boost.org/trac/boost/ticket/9497 9497]. | |
5356 | * Added list of values for numeric_limits. | |
5357 | ||
5358 | [h4 Boost-1.55] | |
5359 | ||
5360 | * Added support for Boost.Serialization. | |
5361 | * Suppressed some GCC warnings. See [@https://svn.boost.org/trac/boost/ticket/8872 8872]. | |
5362 | * Fixed bug in pow for large integer arguments. See [@https://svn.boost.org/trac/boost/ticket/8809 8809]. | |
5363 | * Fixed bug in pow for calculation of 0[super N]. See [@https://svn.boost.org/trac/boost/ticket/8798 8798]. | |
5364 | * Fixed bug in fixed precision cpp_int IO code that causes conversion to string to fail when the | |
5365 | bit count is very small (less than CHAR_BIT). See [@https://svn.boost.org/trac/boost/ticket/8745 8745]. | |
5366 | * Fixed bug in cpp_int that causes left shift to fail when a fixed precision type would overflow. | |
5367 | See [@https://svn.boost.org/trac/boost/ticket/8741 8741]. | |
5368 | * Fixed some cosmetic warnings from cpp_int. See [@https://svn.boost.org/trac/boost/ticket/8748 8748]. | |
5369 | * Fixed calls to functions which are required to be macros in C99. See [@https://svn.boost.org/trac/boost/ticket/8732 8732]. | |
5370 | * Fixed bug that causes construction from INT_MIN, LONG_MIN etc to fail in cpp_int. See [@https://svn.boost.org/trac/boost/ticket/8711 8711]. | |
5371 | ||
5372 | [h4 1.54] | |
5373 | ||
5374 | * [*Breaking change] renamed `rational_adapter` to `rational_adaptor`. | |
5375 | * Add support for [mpfi]. | |
5376 | * Add logged_adaptor. | |
5377 | * Add support for 128-bit floats via GCC's `__float128` or Intel's `_Quad` data types. | |
5378 | * Add support for user-defined literals in cpp_int, improve `constexpr` support. | |
5379 | * Fixed bug in integer division of `cpp_int` that results in incorrect sign of `cpp_int` when both arguments are small enough | |
5380 | to fit in a `double_limb_type`. See [@https://svn.boost.org/trac/boost/ticket/8126 8126]. | |
5381 | * Fixed bug in subtraction of a single limb in `cpp_int` that results in incorrect value when the result should have a 0 | |
5382 | in the last limb: [@https://svn.boost.org/trac/boost/ticket/8133 8133]. | |
5383 | * Fixed bug in `cpp_int` where division of 0 by something doesn't get zero in the result: [@https://svn.boost.org/trac/boost/ticket/8160 8160]. | |
5384 | * Fixed bug in some transcendental functions that caused incorrect return values when variables are reused, for example with | |
5385 | `a = pow(a, b)`. See [@https://svn.boost.org/trac/boost/ticket/8326 8326]. | |
5386 | * Fixed some assignment operations in the mpfr and gmp backends to be safe if the target has been moved from: [@https://svn.boost.org/trac/boost/ticket/8326 8667]. | |
5387 | * Fixed bug in `cpp_int` that gives incorrect answer for 0%N for large N: [@https://svn.boost.org/trac/boost/ticket/8670 8670]. | |
5388 | * Fixed set_precision in mpfr backend so it doesn't trample over an existing value: [@https://svn.boost.org/trac/boost/ticket/8692 8692]. | |
5389 | ||
5390 | [h4 1.53] | |
5391 | ||
5392 | * First Release. | |
5393 | * Fix bug in [@https://svn.boost.org/trac/boost/ticket/7878 cpp_int division]. | |
5394 | * Fix issue [@https://svn.boost.org/trac/boost/ticket/7806 #7806]. | |
5395 | ||
5396 | [h4 Post review changes] | |
5397 | ||
5398 | * Non-expression template operators further optimised with rvalue reference support. | |
5399 | * Many functions made `constexp`. | |
5400 | * Differentiate between explicit and implicit conversions in the number constructor. | |
5401 | * Removed "mp_" prefix from types. | |
5402 | * Allowed mixed precision arithmetic. | |
5403 | * Changed ExpressionTemplates parameter to class `number` to use enumerated values rather than true/false. | |
5404 | * Changed ExpressionTemplate parameter default value to use a traits class so that the default value depends on the backend used. | |
5405 | * Added support for fused-multiply-add/subtract with GMP support. | |
5406 | * Tweaked expression template unpacking to use fewer temporaries when the LHS also appears in the RHS. | |
5407 | * Refactored `cpp_int_backend` based on review comments with new template parameter structure. | |
5408 | * Added additional template parameter to `mpfr_float_backend` to allow stack-based allocation. | |
5409 | * Added section on mixed precision arithmetic, and added support for operations yielding a higher precision result | |
5410 | than either of the arguments. | |
5411 | * Added overloads of integer-specific functions for built in integer types. | |
5412 | ||
5413 | [h4 Pre-review history] | |
5414 | ||
5415 | *2011-2012, John Maddock adds an expression template enabled front end to Christopher's code, | |
5416 | and adds support for other backends. | |
5417 | * 2011, Christopher Kormanyos publishes the decimal floating-point code under the Boost | |
5418 | Software Licence. The code is published as: [@http://doi.acm.org/10.1145/1916461.1916469 | |
5419 | "Algorithm 910: A Portable C++ Multiple-Precision | |
5420 | System for Special-Function Calculations"], in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, | |
5421 | 2011. | |
5422 | * 2002-2011, Christopher Kormanyos develops the all C++ decimal arithmetic floating-point | |
5423 | code. | |
5424 | ||
5425 | [endsect] | |
5426 | ||
5427 | [section:todo TODO] | |
5428 | ||
5429 | ||
5430 | ||
5431 | More a list of what ['could] be done, rather than what ['should] be done (which may be a much smaller list!). | |
5432 | ||
5433 | * Add back-end support for libdecNumber. | |
5434 | * Add an adaptor back-end for complex number types. | |
5435 | * Add better multiplication routines (Karatsuba, FFT etc) to cpp_int_backend. | |
5436 | * Add assembly level routines to cpp_int_backend. | |
5437 | * Can ring types (exact floating-point types) be supported? The answer should be yes, but someone needs to write it, | |
5438 | the hard part is IO and binary-decimal conversion. | |
5439 | * Should there be a choice of rounding mode (probably MPFR specific)? | |
5440 | * We can reuse temporaries in multiple subtrees (temporary caching). | |
5441 | * cpp_dec_float should round to nearest. | |
5442 | * A 2's complement fixed precision int that uses exactly N bits and no more. | |
5443 | ||
5444 | Things requested in review: | |
5445 | ||
5446 | * The performances of mp_number<a_trivial_adaptor<float>, false>respect to | |
5447 | float and mp_number<a_trivial_adaptor<int>, false> and int should be | |
5448 | given to show the cost of using the generic interface (Mostly done, just need to update docs to the latest results). | |
5449 | * Should we provide min/max overloads for expression templates? (Not done - we can't overload functions declared in the std namespace :-( ). | |
5450 | * The rounding applied when converting must be documented (Done). | |
5451 | * Document why we don't abstract out addition/multiplication algorithms etc. (done - FAQ) | |
5452 | * Document why we don't use proto (compile times) (Done). | |
5453 | * We can reuse temporaries in multiple subtrees (temporary caching) Moved to TODO list. | |
5454 | * Emphasise in the docs that ET's may reorder operations (done 2012/10/31). | |
5455 | * Document what happens to small fixed precision cpp_int's (done 2012/10/31). | |
5456 | * The use of bool in template parameters could be improved by the use of | |
5457 | an enum class which will be more explicit. E.g `enum class expression_template {disabled, enabled}; | |
5458 | enum class sign {unsigned, signed};` (Partly done 2012/09/15, done 2012/10/31). | |
5459 | * Each back-end should document the requirements it satisfies (not currently scheduled for inclusion: it's | |
5460 | deliberately an implementation detail, and "optional" requirements are optimisations which can't be detected | |
5461 | by the user). Not done: this is an implementation detail, the exact list of requirements satisfied is purely | |
5462 | an optimization, not something the user can detect. | |
5463 | * A backend for an overflow aware integers (done 2012/10/31). | |
5464 | * IIUC convert_to is used to emulate in c++98 compilers C++11 explicit | |
5465 | conversions. Could the explicit conversion operator be added on | |
5466 | compilers supporting it? (Done 2012/09/15). | |
5467 | * The front-end should make the differences between implicit and explicit | |
5468 | construction (Done 2012/09/15). | |
5469 | * The tutorial should add more examples concerning implicit or explicit | |
5470 | conversions. (Done 2012/09/15). | |
5471 | * The documentation must explain how move semantics helps in this domain | |
5472 | and what the backend needs to do to profit from this optimization. (Done 2012/09/15). | |
5473 | * The documentation should contain Throws specification on the mp_number | |
5474 | and backend requirements operations. (Done 2012/09/15). | |
5475 | * The library interface should use the noexcept (BOOST_NOEXCEPT, ...) | |
5476 | facilities (Done 2012/09/15). | |
5477 | * It is unfortunate that the generic mp_number front end can not make use | |
5478 | constexpr as not all the backends can ensure this (done - we can go quite a way). | |
5479 | * literals: The library doesn't provide some kind of literals. I think that the | |
5480 | mp_number class should provide a way to create literals if the backend | |
5481 | is able to. (Done 2012/09/15). | |
5482 | * The ExpresionTemplate parameter could be defaulted to a traits class for more sensible defaults (done 2012/09/20). | |
5483 | * In a = exp1 op exp2 where a occurs inside one of exp1 or exp2 then we can optimise and eliminate one more temporary (done 2012/09/20). | |
5484 | ||
5485 | ||
5486 | ||
5487 | [h4 Pre-Review Comments] | |
5488 | ||
5489 | * Make fixed precision orthogonal to Allocator type in cpp_int. Possible solution - add an additional MaxBits | |
5490 | template argument that defaults to 0 (meaning keep going till no more space/memory). Done. | |
5491 | * Can ring types (exact floating-point types) be supported? The answer should be yes, but someone needs to write it (Moved to TODO list). | |
5492 | * Should there be a choice of rounding mode (probably MPFR specific)? Moved to TODO list. | |
5493 | * Make the exponent type for cpp_dec_float a template parameter, maybe include support for big-integer exponents. | |
5494 | Open question - what should be the default - int32_t or int64_t? (done 2012/09/06) | |
5495 | * Document the size requirements of fixed precision ints (done 2012/09/15). | |
5496 | * Document std lib function accuracy (done 2012/09/15). | |
5497 | * Be a bit clearer on the effects of sign-magnitude representation of cpp_int - min == -max etc - done. | |
5498 | * Document cpp_dec_float precision, rounding, and exponent size (done 2012/09/06). | |
5499 | * Can we be clearer in the docs that mixed arithmetic doesn't work (no longer applicable as of 2012/09/06)? | |
5500 | * Document round functions behaviour better (they behave as in C++11) (added note 2012/09/06). | |
5501 | * Document limits on size of cpp_dec_float (done 2012/09/06). | |
5502 | * Add support for fused multiply add (and subtract). GMP mpz_t could use this (done 2012/09/20). | |
5503 | ||
5504 | [endsect] | |
5505 | ||
5506 | [section:faq FAQ] | |
5507 | ||
5508 | [variablelist | |
5509 | [[Why do I get compiler errors when passing a `number` to a template function?] | |
5510 | [Most likely you are actually passing an expression template type to the function and | |
5511 | template-argument-deduction deduces the "wrong" type. Try casting the arguments | |
5512 | involving expressions to the actual number type, or as a last resort turning off | |
5513 | expression template support in the number type you are using.]] | |
5514 | [[When is expression template support a performance gain?] | |
5515 | [As a general rule, expression template support adds a small runtime overhead | |
5516 | creating and unpacking the expression templates, but greatly reduces the number of | |
5517 | temporaries created. So it's most effective in improving performance when the cost | |
5518 | of creating a temporary is high: for example when creating a temporary involves a memory | |
5519 | allocation. It is least effective (and may even be a dis-optimisation) when temporaries | |
5520 | are cheap: for example if the number type is basically a thin wrapper around a native | |
5521 | arithmetic type. In addition, since the library makes extensive use of thin inline wrapper | |
5522 | functions, turning on compiler optimization is essential to achieving high performance.]] | |
5523 | [[Do expression templates reorder operations?] | |
5524 | [Yes they do, sometimes quite radically so, if this is a concern then they should be turned | |
5525 | off for the number type you are using.]] | |
5526 | [[I can't construct my number type from ['some other type], but the docs indicate that the conversion should be allowed, what's up?] | |
5527 | [Some conversions are ['explicit], that includes construction from a string, or constructing from any type | |
5528 | that may result in loss of precision (for example constructing an integer type from a float).]] | |
5529 | [[Why do I get an exception thrown (or the program crash due to an uncaught exception) when using the bitwise operators on a checked `cpp_int`?] | |
5530 | [Bitwise operations on negative values (or indeed any signed integer type) are unspecified by the standard. As a result | |
5531 | any attempt to carry out a bitwise operation on a negative checked-integer will result in a `std::range_error` being thrown.]] | |
5532 | [[Why do I get compiler errors when trying to use the complement operator?] | |
5533 | [Use of the complement operator on signed types is problematic as the result is unspecified by the standard, and is further | |
5534 | complicated by the fact that most extended precision integer types use a sign-magnitude representation rather than the 2's | |
5535 | complement one favored by most native integer types. As a result the complement operator is deliberately disabled for | |
5536 | checked `cpp_int`'s. Unchecked `cpp_int`'s give the same valued result as a 2's complement type would, but not the same bit-pattern.]] | |
5537 | [[Why can't I negate an unsigned type?] | |
5538 | [The unary negation operator is deliberately disabled for unsigned integer types as its use would almost always be a programming error.]] | |
5539 | [[Why doesn't the library use proto?] | |
5540 | [A very early version of the library did use proto, but compile times became too slow | |
5541 | for the library to be usable. Since the library only required a tiny fraction of what | |
5542 | proto has to offer anyway, a lightweight expression template mechanism was used instead. | |
5543 | Compile times are still too slow...]] | |
5544 | [[Why not abstract out addition/multiplication algorithms?] | |
5545 | [This was deemed not to be practical: these algorithms are intimately | |
5546 | tied to the actual data representation used.]] | |
5547 | ] | |
5548 | ||
5549 | [endsect] | |
5550 | ||
5551 | [section:ack Acknowledgements] | |
5552 | ||
5553 | This library would not have happened without: | |
5554 | ||
5555 | * Christopher Kormanyos' C++ decimal number code. | |
5556 | * Paul Bristow for patiently testing, and commenting on the library. | |
5557 | * All the folks at GMP, MPFR and libtommath, for providing the "guts" that makes this library work. | |
5558 | * [@http://www-cs-faculty.stanford.edu/~uno/taocp.html "The Art Of Computer Programming"], | |
5559 | Donald E. Knuth, Volume 2: Seminumerical Algorithms, Third Edition | |
5560 | (Reading, Massachusetts: Addison-Wesley, 1997), xiv+762pp. ISBN 0-201-89684-2 | |
5561 | ||
5562 | [endsect] | |
5563 | ||
5564 | [endsect] | |
5565 | ||
5566 | [section:indexes Indexes] | |
5567 | ||
5568 | ''' | |
5569 | <index type="function_name"> | |
5570 | <title>Function Index</title> | |
5571 | </index> | |
5572 | ||
5573 | <index type="class_name"> | |
5574 | <title>Class Index</title> | |
5575 | </index> | |
5576 | ||
5577 | <index type="typedef_name"> | |
5578 | <title>Typedef Index</title> | |
5579 | </index> | |
5580 | ||
5581 | <index/> | |
5582 | ''' | |
5583 | ||
5584 | [endsect] | |
5585 | ||
5586 | ||
5587 | ||
5588 |