diff --git a/config/Jamfile.v2 b/config/Jamfile.v2 new file mode 100644 index 00000000..91f9cbb3 --- /dev/null +++ b/config/Jamfile.v2 @@ -0,0 +1,22 @@ +# copyright John Maddock 2008 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + +import modules ; +import path ; + +local gmp_path = [ modules.peek : GMP_PATH ] ; +local mpfr_path = [ modules.peek : MPFR_PATH ] ; +local tommath_path = [ modules.peek : TOMMATH_PATH ] ; + +obj has_gmp : has_gmp.cpp : + $(gmp_path) $(gmp_path)/mpfr $(gmp_path)/gmpfrxx ; +obj has_mpfr : has_mpfr.cpp : + $(mpfr_path) $(gmp_path)/mpfr $(gmp_path)/gmpfrxx $(gmp_path) ; +obj has_tommath : has_tommath.cpp : + $(tommath_path) ; + +explicit has_gmp ; +explicit has_mpfr ; +explicit has_tommath ; diff --git a/config/has_gmp.cpp b/config/has_gmp.cpp new file mode 100644 index 00000000..582f0027 --- /dev/null +++ b/config/has_gmp.cpp @@ -0,0 +1,7 @@ +// Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + diff --git a/config/has_mpfr.cpp b/config/has_mpfr.cpp new file mode 100644 index 00000000..49d12a0b --- /dev/null +++ b/config/has_mpfr.cpp @@ -0,0 +1,7 @@ +// Copyright John Maddock 2008. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + diff --git a/config/has_tommath.cpp b/config/has_tommath.cpp new file mode 100644 index 00000000..8d230043 --- /dev/null +++ b/config/has_tommath.cpp @@ -0,0 +1,7 @@ +// Copyright John Maddock 2011. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 00000000..c8568858 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,79 @@ + +# Copyright John Maddock 2011. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using quickbook ; +using auto-index ; + +path-constant images_location : html ; +path-constant here : . ; + +xml big_number : multiprecision.qbk ; +boostbook standalone + : + big_number + : + # Path for links to Boost: + #boost.root=http://www.boost.org/doc/libs/release + + # Some general style settings: + table.footnote.number.format=1 + footnote.number.format=1 + html.stylesheet=http://www.boost.org/doc/libs/release/doc/src/boostbook.css + + # HTML options first: + # Use graphics not text for navigation: + navig.graphics=1 + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=10 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=10 + # How far down sections get TOC's + toc.section.depth=10 + # Max depth in each TOC: + toc.max.depth=4 + # How far down we go with TOC's + #generate.section.toc.level=10 + # Index on type: + index.on.type=1 + + # PDF Options: + # TOC Generation: this is needed for FOP-0.9 and later: + fop1.extensions=0 + pdf:xep.extensions=1 + # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! + pdf:fop.extensions=0 + pdf:fop1.extensions=0 + # No indent on body text: + pdf:body.start.indent=0pt + # Margin size: + pdf:page.margin.inner=0.5in + # Margin size: + pdf:page.margin.outer=0.5in + # Paper type = A4 + pdf:paper.type=A4 + # Yes, we want graphics for admonishments: + admon.graphics=1 + # Set this one for PDF generation *only*: + # default pnd graphics are awful in PDF form, + # better use SVG's instead: + pdf:admon.graphics.extension=".svg" + pdf:use.role.for.mediaobject=1 + pdf:preferred.mediaobject.role=print + pdf:img.src.path=$(images_location)/ + pdf:draft.mode="no" + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/math/doc/sf_and_dist/html + # Index generation: + on + $(here)/index.idx + $(here)/../../.. + on + html:on + enable_index + pdf:index.on.type=1 + ; + +install pdf-install : standalone : . PDF ; + + diff --git a/doc/floating_point_eg1.mml b/doc/floating_point_eg1.mml new file mode 100644 index 00000000..f98264f1 --- /dev/null +++ b/doc/floating_point_eg1.mml @@ -0,0 +1,154 @@ + +]> + +floating_point_eg1 + + + + + + + + 1 + + + + + + + + f + + + + x + + + + + + + + + m + 1 + + + + O + + + d + + x + 2 + + + + + + + + f + + + + x + + + + + + + + + 4 + 3 + + + m + 1 + + + + 1 + 3 + + + m + 2 + + + + O + + + d + + x + 4 + + + + + + + + f + + + + x + + + + + + + + + 3 + 2 + + + m + 1 + + + + 3 + 5 + + + m + 2 + + + + + 1 + 10 + + + m + 3 + + + + O + + + d + + x + 6 + + + + + + + + + + + + diff --git a/doc/floating_point_eg1.png b/doc/floating_point_eg1.png new file mode 100644 index 00000000..b250bda4 Binary files /dev/null and b/doc/floating_point_eg1.png differ diff --git a/doc/floating_point_eg1.svg b/doc/floating_point_eg1.svg new file mode 100644 index 00000000..87f82ede --- /dev/null +++ b/doc/floating_point_eg1.svg @@ -0,0 +1,2 @@ + +(1)f′(x)≈m1+O(dx2)f′(x)≈43m1−13m2+O(dx4)f′(x)≈32m1−35m2+110m3+O(dx6) \ No newline at end of file diff --git a/doc/floating_point_eg2.mml b/doc/floating_point_eg2.mml new file mode 100644 index 00000000..9a87f93c --- /dev/null +++ b/doc/floating_point_eg2.mml @@ -0,0 +1,152 @@ + +]> + +floating_point_eg2 + + + + + + + + 2 + + + + + + + + + m + 1 + + + + = + + + + + f + + + x + + + d + x + + + + f + + + x + + d + x + + + + + 2 + d + x + + + + + + + + m + 2 + + + + = + + + + + f + + + x + + + 2 + d + x + + + + f + + + x + + 2 + d + x + + + + + 4 + d + x + + + + + + + + m + 3 + + + + = + + + + + f + + + x + + + 3 + d + x + + + + f + + + x + + 3 + d + x + + + + + 6 + d + x + + + + + + + + + + diff --git a/doc/floating_point_eg2.png b/doc/floating_point_eg2.png new file mode 100644 index 00000000..cb18e4ac Binary files /dev/null and b/doc/floating_point_eg2.png differ diff --git a/doc/floating_point_eg2.svg b/doc/floating_point_eg2.svg new file mode 100644 index 00000000..8b2a9ee0 --- /dev/null +++ b/doc/floating_point_eg2.svg @@ -0,0 +1,2 @@ + +(2)m1=f(x+dx)−f(x−dx)2dxm2=f(x+2dx)−f(x−2dx)4dxm3=f(x+3dx)−f(x−3dx)6dx \ No newline at end of file diff --git a/doc/floating_point_eg3.mml b/doc/floating_point_eg3.mml new file mode 100644 index 00000000..cdf690d2 --- /dev/null +++ b/doc/floating_point_eg3.mml @@ -0,0 +1,53 @@ + +]> + +floating_point_eg3 + + + + + + + + 3 + + + + + + d + + d + x + + + sin + x + + | + + x + = + + π + 3 + + + + = + cos + + π + 3 + + = + + 1 + 2 + + + + + diff --git a/doc/floating_point_eg3.png b/doc/floating_point_eg3.png new file mode 100644 index 00000000..2293fd40 Binary files /dev/null and b/doc/floating_point_eg3.png differ diff --git a/doc/floating_point_eg3.svg b/doc/floating_point_eg3.svg new file mode 100644 index 00000000..0ff51462 --- /dev/null +++ b/doc/floating_point_eg3.svg @@ -0,0 +1,2 @@ + +(3)ddxsinx|x=Ï€3=cosÏ€3=12 \ No newline at end of file diff --git a/doc/generate.sh b/doc/generate.sh new file mode 100755 index 00000000..27d1d5ef --- /dev/null +++ b/doc/generate.sh @@ -0,0 +1,33 @@ +# Copyright John Maddock 2008. +# Use, modification and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Generates SVG and PNG files from the MML masters. +# +# Paths to tools come first, change these to match your system: +# +math2svg='m:\download\open\SVGMath-0.3.1\math2svg.py' +python=/cygdrive/c/Python26/python.exe +inkscape=/cygdrive/c/progra~1/Inkscape/inkscape +# Image DPI: +dpi=120 + +for mmlfile in $*; do + svgfile=$(basename $mmlfile .mml).svg + pngfile=$(basename $svgfile .svg).png + tempfile=temp.mml + # strip html wrappers put in by MathCast: + cat $mmlfile | tr -d "\r\n" | sed -e 's/.*\(]*>.*<\/math>\).*/\1/' > $tempfile + + echo Generating $svgfile + $python $math2svg $tempfile > $svgfile + echo Generating $pngfile + $inkscape -d $dpi -e $(cygpath -a -w $pngfile) $(cygpath -a -w $svgfile) + rm $tempfile +done + + + + + diff --git a/doc/html/boost_multiprecision/indexes.html b/doc/html/boost_multiprecision/indexes.html new file mode 100644 index 00000000..8a9d13ce --- /dev/null +++ b/doc/html/boost_multiprecision/indexes.html @@ -0,0 +1,40 @@ + + + +Indexes + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/indexes/s01.html b/doc/html/boost_multiprecision/indexes/s01.html new file mode 100644 index 00000000..39761a20 --- /dev/null +++ b/doc/html/boost_multiprecision/indexes/s01.html @@ -0,0 +1,515 @@ + + + +Function Index + + + + + + + + +
+PrevUpHomeNext +
+
+

+Function Index

+

A B C D E F I L M P R S T Z

+
+
+A +
+
+
+B +
+
+
+C +
+
+
+D +
+
+
+E +
+
+
+F +
+
+
+I +
+
+
+L +
+
+
+M +
+
+
+P +
+
+
+R +
+
+
+S +
+
+
+T +
+
+
+Z +
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/indexes/s02.html b/doc/html/boost_multiprecision/indexes/s02.html new file mode 100644 index 00000000..92823c08 --- /dev/null +++ b/doc/html/boost_multiprecision/indexes/s02.html @@ -0,0 +1,125 @@ + + + +Class Index + + + + + + + + +
+PrevUpHomeNext +
+
+

+Class Index

+

C E G I M N T

+
+
+C +
+
+
+E +
+
  • +

    expression_template_default

    + +
+
+G +
+
+
+I +
+
+
+M +
+
+
+N +
+
+
+T +
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/indexes/s03.html b/doc/html/boost_multiprecision/indexes/s03.html new file mode 100644 index 00000000..be2ca667 --- /dev/null +++ b/doc/html/boost_multiprecision/indexes/s03.html @@ -0,0 +1,260 @@ + + + +Typedef Index + + + + + + + + +
+PrevUpHomeNext +
+
+

+Typedef Index

+

C I L M S T U

+
+
+C +
+
+
+I +
+
+
+L +
+
+
+M +
+
+
+S +
+
+
+T +
+
+
+U +
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/indexes/s04.html b/doc/html/boost_multiprecision/indexes/s04.html new file mode 100644 index 00000000..aefd9766 --- /dev/null +++ b/doc/html/boost_multiprecision/indexes/s04.html @@ -0,0 +1,1040 @@ + + + +Index + + + + + + + +
+PrevUpHome +
+
+

+Index

+

A B C D E F G I L M N O P R S T U Z

+
+
+A +
+
+
+B +
+
+
+C +
+
+
+D +
+
+
+E +
+
+
+F +
+
+
+G +
+
+
+I +
+
+
+L +
+
+
+M +
+
+
+N +
+
+
+O +
+
+
+P +
+
+
+R +
+
+
+S +
+
+
+T +
+
+
+U +
+
+
+Z +
+
+
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/doc/html/boost_multiprecision/intro.html b/doc/html/boost_multiprecision/intro.html new file mode 100644 index 00000000..5cc6c307 --- /dev/null +++ b/doc/html/boost_multiprecision/intro.html @@ -0,0 +1,681 @@ + + + +Introduction + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ The Multiprecision Library provides User-defined integer, + rational and floating-point C++ types which try to emulate as closely as practicable + the C++ built-in types, but provide for more range and precision. Depending + upon the number type, precision may be arbitrarily large (limited only by available + memory), fixed at compile time values, for example 50 decimal digits, or a + variable controlled at run-time by member functions. The types are expression-template-enabled + for better performance than naive user-defined types. +

+

+ The Multiprecision library comes in two distinct parts: +

+
    +
  • + An expression-template-enabled front-end number + that handles all the operator overloading, expression evaluation optimization, + and code reduction. +
  • +
  • + A selection of back-ends that implement the actual arithmetic operations, + and need conform only to the reduced interface requirements of the front-end. +
  • +
+

+ Separation of front-end and back-end allows use of highly refined, but restricted + license libraries where possible, but provides Boost license alternatives for + users who must have a portable unconstrained license. Which is to say some + back-ends rely on 3rd party libraries, but a header-only Boost license version + is always available (if somewhat slower). +

+

+ Should you just wish to cut to the chase and use a fully Boost-licensed number + type, then skip to cpp_int + for multiprecision integers, cpp_dec_float + for multiprecision floating point types and cpp_rational + for rational types. +

+

+ The library is often used via one of the predefined typedefs: for example if + you wanted an arbitrary + precision integer type using GMP + as the underlying implementation then you could use: +

+
#include <boost/multiprecision/gmp.hpp>  // Defines the wrappers around the GMP library's types
+
+boost::multiprecision::mpz_int myint;    // Arbitrary precision integer type.
+
+

+ Alternatively, you can compose your own multiprecision type, by combining + number with one of the predefined + back-end types. For example, suppose you wanted a 300 decimal digit floating-point + type based on the MPFR library. In + this case, there's no predefined typedef with that level of precision, so instead + we compose our own: +

+
#include <boost/multiprecision/mpfr.hpp>  // Defines the Backend type that wraps MPFR
+
+namespace mp = boost::multiprecision;     // Reduce the typing a bit later...
+
+typedef mp::number<mp::mpfr_float_backend<300> >  my_float;
+
+my_float a, b, c; // These variables have 300 decimal digits precision
+
+

+ We can repeat the above example, but with the expression templates disabled + (for faster compile times, but slower runtimes) by passing a second template + argument to number: +

+
#include <boost/multiprecision/mpfr.hpp>  // Defines the Backend type that wraps MPFR
+
+namespace mp = boost::multiprecision;     // Reduce the typing a bit later...
+
+typedef mp::number<mp::mpfr_float_backend<300>, et_off>  my_float;
+
+my_float a, b, c; // These variables have 300 decimal digits precision
+
+

+ We can also mix arithmetic operations between different types, provided there + is an unambiguous implicit conversion from one type to the other: +

+
#include <boost/multiprecision/cpp_int.hpp>
+
+namespace mp = boost::multiprecision;     // Reduce the typing a bit later...
+
+mp::int128_t a(3), b(4);
+mp::int512_t c(50), d;
+
+d = c * a;   // OK, result of mixed arithmetic is an int512_t
+
+

+ Conversions are also allowed: +

+
d = a; // OK, widening conversion.
+d = a * b;  // OK, can convert from an expression template too.
+
+

+ However conversions that are inherently lossy are either declared explicit + or else forbidden altogether: +

+
d = 3.14;  // Error implicit conversion from float not allowed.
+d = static_cast<mp::int512_t>(3.14);  // OK explicit construction is allowed
+
+

+ Mixed arithmetic will fail if the conversion is either ambiguous or explicit: +

+
number<cpp_int_backend<>, et_off> a(2);
+number<cpp_int_backend<>, et_on>  b(3);
+
+b = a * b; // Error, implicit conversion could go either way.
+b = a * 3.14; // Error, no operator overload if the conversion would be explicit.
+
+
+ + Move + Semantics +
+

+ On compilers that support rvalue-references, class number + is move-enabled if the underlying backend is. +

+

+ In addition the non-expression template operator overloads (see below) are + move aware and have overloads that look something like: +

+
template <class B>
+number<B, et_off> operator + (number&& a, const number& b)
+{
+    return std::move(a += b);
+}
+
+

+ These operator overloads ensure that many expressions can be evaluated without + actually generating any temporaries. However, there are still many simple expressions + such as: +

+
a = b * c;
+
+

+ Which don't noticeably benefit from move support. Therefore, optimal performance + comes from having both move-support, and expression templates enabled. +

+

+ Note that while "moved-from" objects are left in a sane state, they + have an unspecified value, and the only permitted operations on them are destruction + or the assignment of a new value. Any other operation should be considered + a programming error and all of our backends will trigger an assertion if any + other operation is attempted. This behavior allows for optimal performance + on move-construction (i.e. no allocation required, we just take ownership of + the existing object's internal state), while maintaining usability in the standard + library containers. +

+
+ + Expression + Templates +
+

+ Class number is expression-template-enabled: + that means that rather than having a multiplication operator that looks like + this: +

+
template <class Backend>
+number<Backend> operator * (const number<Backend>& a, const number<Backend>& b)
+{
+   number<Backend> result(a);
+   result *= b;
+   return result;
+}
+
+

+ Instead the operator looks more like this: +

+
template <class Backend>
+unmentionable-type operator * (const number<Backend>& a, const number<Backend>& b);
+
+

+ Where the "unmentionable" return type is an implementation detail + that, rather than containing the result of the multiplication, contains instructions + on how to compute the result. In effect it's just a pair of references to the + arguments of the function, plus some compile-time information that stores what + the operation is. +

+

+ The great advantage of this method is the elimination of temporaries: + for example the "naive" implementation of operator* above, requires one temporary for computing + the result, and at least another one to return it. It's true that sometimes + this overhead can be reduced by using move-semantics, but it can't be eliminated + completely. For example, lets suppose we're evaluating a polynomial via Horner's + method, something like this: +

+
T a[7] = { /* some values */ };
+//....
+y = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0];
+
+

+ If type T is a number, then this expression is evaluated + without creating a single temporary value. In contrast, + if we were using the mpfr_class + C++ wrapper for MPFR - then this expression + would result in no less than 11 temporaries (this is true even though mpfr_class does + use expression templates to reduce the number of temporaries somewhat). Had + we used an even simpler wrapper around MPFR + like mpreal things + would have been even worse and no less that 24 temporaries are created for + this simple expression (note - we actually measure the number of memory allocations + performed rather than the number of temporaries directly, note also that the + mpf_class + wrapper that will be supplied with GMP-5.1 reduces the number of temporaries + to pretty much zero). Note that if we compile with expression templates disabled + and rvalue-reference support on, then actually still have no wasted memory + allocations as even though temporaries are created, their contents are moved + rather than copied. [1] +

+
+ + + + + +
[Important]Important
+

+ Expression templates can radically reorder the operations in an expression, + for example: +

+

+ a = (b * c) * a; +

+

+ Will get transformed into: +

+

+ a *= c; a *= b; +

+

+ If this is likely to be an issue for a particular application, then they + should be disabled. +

+
+

+ This library also extends expression template support to standard library functions + like abs or sin + with number arguments. This + means that an expression such as: +

+
y = abs(x);
+
+

+ can be evaluated without a single temporary being calculated. Even expressions + like: +

+
y = sin(x);
+
+

+ get this treatment, so that variable 'y' is used as "working storage" + within the implementation of sin, + thus reducing the number of temporaries used by one. Of course, should you + write: +

+
x = sin(x);
+
+

+ Then we clearly can't use x + as working storage during the calculation, so then a temporary variable is + created in this case. +

+

+ Given the comments above, you might be forgiven for thinking that expression-templates + are some kind of universal-panacea: sadly though, all tricks like this have + their downsides. For one thing, expression template libraries like this one, + tend to be slower to compile than their simpler cousins, they're also harder + to debug (should you actually want to step through our code!), and rely on + compiler optimizations being turned on to give really good performance. Also, + since the return type from expressions involving numbers + is an "unmentionable implementation detail", you have to be careful + to cast the result of an expression to the actual number type when passing + an expression to a template function. For example, given: +

+
template <class T>
+void my_proc(const T&);
+
+

+ Then calling: +

+
my_proc(a+b);
+
+

+ Will very likely result in obscure error messages inside the body of my_proc - since we've passed it an expression + template type, and not a number type. Instead we probably need: +

+
my_proc(my_number_type(a+b));
+
+

+ Having said that, these situations don't occur that often - or indeed not at + all for non-template functions. In addition, all the functions in the Boost.Math + library will automatically convert expression-template arguments to the underlying + number type without you having to do anything, so: +

+
mpfr_float_100 a(20), delta(0.125);
+boost::math::gamma_p(a, a + delta);
+
+

+ Will work just fine, with the a + delta expression + template argument getting converted to an mpfr_float_100 + internally by the Boost.Math library. +

+

+ One other potential pitfall that's only possible in C++11: you should never + store an expression template using: +

+
auto my_expression = a + b - c;
+
+

+ unless you're absolutely sure that the lifetimes of a, + b and c + will outlive that of my_expression. +

+

+ And finally... the performance improvements from an expression template library + like this are often not as dramatic as the reduction in number of temporaries + would suggest. For example if we compare this library with mpfr_class + and mpreal, with + all three using the underlying MPFR + library at 50 decimal digits precision then we see the following typical results + for polynomial execution: +

+
+

Table 1.1. Evaluation of Order 6 Polynomial.

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Library +

+
+

+ Relative Time +

+
+

+ Relative number of memory allocations +

+
+

+ number +

+
+

+ 1.0 (0.00957s) +

+
+

+ 1.0 (2996 total) +

+
+

+ mpfr_class +

+
+

+ 1.1 (0.0102s) +

+
+

+ 4.3 (12976 total) +

+
+

+ mpreal +

+
+

+ 1.6 (0.0151s) +

+
+

+ 9.3 (27947 total) +

+
+
+

+ As you can see, the execution time increases a lot more slowly than the number + of memory allocations. There are a number of reasons for this: +

+
    +
  • + The cost of extended-precision multiplication and division is so great, + that the times taken for these tend to swamp everything else. +
  • +
  • + The cost of an in-place multiplication (using operator*=) tends to be more than an out-of-place + operator* + (typically operator *= + has to create a temporary workspace to carry out the multiplication, where + as operator* + can use the target variable as workspace). Since the expression templates + carry out their magic by converting out-of-place operators to in-place + ones, we necessarily take this hit. Even so the transformation is more + efficient than creating the extra temporary variable, just not by as much + as one would hope. +
  • +
+

+ Finally, note that number takes + a second template argument, which, when set to et_off + disables all the expression template machinery. The result is much faster to + compile, but slower at runtime. +

+

+ We'll conclude this section by providing some more performance comparisons + between these three libraries, again, all are using MPFR + to carry out the underlying arithmetic, and all are operating at the same precision + (50 decimal digits): +

+
+

Table 1.2. Evaluation of Boost.Math's Bessel function test data

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Library +

+
+

+ Relative Time +

+
+

+ Relative Number of Memory Allocations +

+
+

+ mpfr_float_50 +

+
+

+ 1.0 (5.78s) +

+
+

+ 1.0 (1611963) +

+
+

+ number<mpfr_float_backend<50>, et_off>
(but with + rvalue reference support) +

+
+

+ 1.1 (6.29s) +

+
+

+ 2.64 (4260868) +

+
+

+ mpfr_class +

+
+

+ 1.1 (6.28s) +

+
+

+ 2.45 (3948316) +

+
+

+ mpreal +

+
+

+ 1.65 (9.54s) +

+
+

+ 8.21 (13226029) +

+
+
+
+

Table 1.3. Evaluation of Boost.Math's Non-Central T distribution test data

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Library +

+
+

+ Relative Time +

+
+

+ Relative Number of Memory Allocations +

+
+

+ number +

+
+

+ 1.0 (263s) +

+
+

+ 1.0 (127710873) +

+
+

+ number<mpfr_float_backend<50>, et_off>
(but with + rvalue reference support) +

+
+

+ 1.0 (260s) +

+
+

+ 1.2 (156797871) +

+
+

+ mpfr_class +

+
+

+ 1.1 (287s) +

+
+

+ 2.1 (268336640) +

+
+

+ mpreal +

+
+

+ 1.5 (389s) +

+
+

+ 3.6 (466960653) +

+
+
+

+ The above results were generated on Win32 compiling with Visual C++ 2010, all + optimizations on (/Ox), with MPFR 3.0 and MPIR 2.3.0. +

+
+

+

[1] + The actual number generated will depend on the compiler, how well it optimises + the code, and whether it supports rvalue references. The number of 11 temporaries + was generated with Visual C++ 10 +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/map.html b/doc/html/boost_multiprecision/map.html new file mode 100644 index 00000000..9521a6be --- /dev/null +++ b/doc/html/boost_multiprecision/map.html @@ -0,0 +1,40 @@ + + + +Roadmap + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/map/ack.html b/doc/html/boost_multiprecision/map/ack.html new file mode 100644 index 00000000..0dc685f5 --- /dev/null +++ b/doc/html/boost_multiprecision/map/ack.html @@ -0,0 +1,55 @@ + + + +Acknowledgements + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ This library would not have happened without: +

+
    +
  • + Christopher Kormanyos' C++ decimal number code. +
  • +
  • + Paul Bristow for patiently testing, and commenting on the library. +
  • +
  • + All the folks at GMP, MPFR and libtommath, for providing the "guts" + that makes this library work. +
  • +
  • + "The + Art Of Computer Programming", Donald E. Knuth, Volume 2: + Seminumerical Algorithms, Third Edition (Reading, Massachusetts: Addison-Wesley, + 1997), xiv+762pp. ISBN 0-201-89684-2 +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/map/faq.html b/doc/html/boost_multiprecision/map/faq.html new file mode 100644 index 00000000..5df05580 --- /dev/null +++ b/doc/html/boost_multiprecision/map/faq.html @@ -0,0 +1,111 @@ + + + +FAQ + + + + + + + + +
+PrevUpHomeNext +
+
+

+FAQ +

+
+

+
+
Why do I get compiler errors when passing a number + to a template function?
+

+ Most likely you are actually passing an expression template type to + the function and template-argument-deduction deduces the "wrong" + type. Try casting the arguments involving expressions to the actual + number type, or as a last resort turning off expression template support + in the number type you are using. +

+
When is expression template support a performance gain?
+

+ As a general rule, expression template support adds a small runtime + overhead creating and unpacking the expression templates, but greatly + reduces the number of temporaries created. So it's most effective in + improving performance when the cost of creating a temporary is high: + for example when creating a temporary involves a memory allocation. + It is least effective (and may even be a dis-optimisation) when temporaries + are cheap: for example if the number type is basically a thin wrapper + around a native arithmetic type. In addition, since the library makes + extensive use of thin inline wrapper functions, turning on compiler + optimization is essential to achieving high performance. +

+
Do expression templates reorder operations?
+

+ Yes they do, sometimes quite radically so, if this is a concern then + they should be turned off for the number type you are using. +

+
I can't construct my number type from some other type, + but the docs indicate that the conversion should be allowed, what's up?
+

+ Some conversions are explicit, that includes construction + from a string, or constructing from any type that may result in loss + of precision (for example constructing an integer type from a float). +

+
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?
+

+ Bitwise operations on negative values (or indeed any signed integer + type) are unspecified by the standard. As a result any attempt to carry + out a bitwise operation on a negative checked-integer will result in + a std::range_error being thrown. +

+
Why do I get compiler errors when trying to use the complement operator?
+

+ Use of the complement operator on signed types is problematic as the + result is unspecified by the standard, and is further complicated by + the fact that most extended precision integer types use a sign-magnitude + representation rather than the 2's complement one favored by most native + integer types. As a result the complement operator is deliberately + disabled for 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. +

+
Why can't I negate an unsigned type?
+

+ The unary negation operator is deliberately disabled for unsigned integer + types as its use would almost always be a programming error. +

+
Why doesn't the library use proto?
+

+ A very early version of the library did use proto, but compile times + became too slow for the library to be usable. Since the library only + required a tiny fraction of what proto has to offer anyway, a lightweight + expression template mechanism was used instead. Compile times are still + too slow... +

+
Why not abstract out addition/multiplication algorithms?
+

+ This was deamed not to be practical: these algorithms are intimately + tied to the actual data representation used. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/map/hist.html b/doc/html/boost_multiprecision/map/hist.html new file mode 100644 index 00000000..bb5e3493 --- /dev/null +++ b/doc/html/boost_multiprecision/map/hist.html @@ -0,0 +1,109 @@ + + + +History + + + + + + + + +
+PrevUpHomeNext +
+
+ +
+ + Post + review changes +
+
    +
  • + Non-expression template operators further optimised with rvalue reference + support. +
  • +
  • + Many functions made constexp. +
  • +
  • + Differentiate between explicit and implicit conversions in the number + constructor. +
  • +
  • + Removed "mp_" prefix from types. +
  • +
  • + Allowed mixed precision arithmetic. +
  • +
  • + Changed ExpressionTemplates parameter to class number + to use enumerated values rather than true/false. +
  • +
  • + Changed ExpressionTemplate parameter default value to use a traits class + so that the default value depends on the backend used. +
  • +
  • + Added support for fused-multiply-add/subtract with GMP support. +
  • +
  • + Tweaked expression template unpacking to use fewer temporaries when the + LHS also appears in the RHS. +
  • +
  • + Refactored cpp_int_backend + based on review comments with new template parameter structure. +
  • +
  • + Added additional template parameter to mpfr_float_backend + to allow stack-based allocation. +
  • +
  • + Added section on mixed precision arithmetic, and added support for operations + yielding a higher precision result than either of the arguments. +
  • +
  • + Added overloads of integer-specific functions for built in integer types. +
  • +
+
+ + Pre-review + history +
+
    +
  • + 2011-2012, John Maddock adds an expression template enabled front end + to Christopher's code, and adds support for other backends. +
  • +
  • + 2011, Christopher Kormanyos publishes the decimal floating point code + under the Boost Software Licence. The code is published as: "Algorithm + 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", + in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. +
  • +
  • + 2002-2011, Christopher Kormanyos develops the all C++ decimal arithmetic + floating point code. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/map/todo.html b/doc/html/boost_multiprecision/map/todo.html new file mode 100644 index 00000000..f8aa94a5 --- /dev/null +++ b/doc/html/boost_multiprecision/map/todo.html @@ -0,0 +1,226 @@ + + + +TODO + + + + + + + + +
+PrevUpHomeNext +
+
+

+TODO +

+

+ More a list of what could be done, rather than what + should be done (which may be a much smaller list!). +

+
    +
  • + Add back-end support for libdecNumber. +
  • +
  • + Add an adapter back-end for complex number types. +
  • +
  • + Add a back-end for MPFR interval arithmetic. +
  • +
  • + Add better multiplication routines (Karatsuba, FFT etc) to cpp_int_backend. +
  • +
  • + Add assembly level routines to cpp_int_backend. +
  • +
  • + Add an all C++ binary floating point type. +
  • +
  • + Can ring types (exact floating point types) be supported? The answer + should be yes, but someone needs to write it, the hard part is IO and + binary-decimal convertion. +
  • +
  • + Should there be a choice of rounding mode (probably MPFR specific)? +
  • +
  • + We can reuse temporaries in multiple subtrees (temporary caching). +
  • +
  • + cpp_dec_float should round to nearest. +
  • +
  • + A 2's complement fixed precision int that uses exactly N bits and no + more. +
  • +
+

+ Things requested in review: +

+
    +
  • + The performances of mp_number<a_trivial_adaptor<float>, false>respect + to float and mp_number<a_trivial_adaptor<int>, false> and + int should be given to show the cost of using the generic interface (Mostly + done, just need to update docs to the latest results). +
  • +
  • + Should we provide min/max overloads for expression templates? (Not done + - we can't overload functions declared in the std namespace :-( ). +
  • +
  • + The rounding applied when converting must be documented (Done). +
  • +
  • + Document why we don't abstract out addition/multiplication algorithms + etc. (done - FAQ) +
  • +
  • + Document why we don't use proto (compile times) (Done). +
  • +
  • + We can reuse temporaries in multiple subtrees (temporary caching) Moved + to TODO list. +
  • +
  • + Emphasise in the docs that ET's may reorder operations (done 2012/10/31). +
  • +
  • + Document what happens to small fixed precision cpp_int's (done 2012/10/31). +
  • +
  • + The use of bool in template parameters could be improved by the use of + an enum class which will be more explicit. E.g enum + class expression_template + {disabled, enabled}; enum class sign + {unsigned, signed}; (Partly done 2012/09/15, done 2012/10/31). +
  • +
  • + Each back-end should document the requirements it satisfies (not currently + scheduled for inclusion: it's deliberately an implementation detail, + and "optional" requirements are optimisations which can't be + detected by the user). Not done: this is an implementation detail, the + exact list of requirements satisfied is purely an optimimization, not + something the user can detect. +
  • +
  • + A backend for an overflow aware integers (done 2012/10/31). +
  • +
  • + IIUC convert_to is used to emulate in c++98 compilers C++11 explicit + conversions. Could the explicit conversion operator be added on compilers + supporting it? (Done 2012/09/15). +
  • +
  • + The front-end should make the differences between implicit and explicit + construction (Done 2012/09/15). +
  • +
  • + The tutorial should add more examples concerning implicit or explicit + conversions. (Done 2012/09/15). +
  • +
  • + The documentation must explain how move semantics helps in this domain + and what the backend needs to do to profit from this optimization. (Done + 2012/09/15). +
  • +
  • + The documentation should contain Throws specification on the mp_number + and backend requirements operations. (Done 2012/09/15). +
  • +
  • + The library interface should use the noexcept (BOOST_NOEXCEPT, ...) facilities + (Done 2012/09/15). +
  • +
  • + It is unfortunate that the generic mp_number front end can not make use + contexpr as not all the backends can ensure this (done - we can go quite + a way). +
  • +
  • + literals: The library doesn't provide some kind of literals. I think + that the mp_number class should provide a way to create literals if the + backend is able to. (Done 2012/09/15). +
  • +
  • + The ExpresionTemplate parameter could be defaulted to a traits class + for more sensible defaults (done 2012/09/20). +
  • +
  • + 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). +
  • +
+
+ + Pre-Review + Comments +
+
    +
  • + Make fixed precision orthogonal to Allocator type in cpp_int. Possible + solution - add an additional MaxBits template argument that defaults + to 0 (meaning keep going till no more space/memory). Done. +
  • +
  • + Can ring types (exact floating point types) be supported? The answer + should be yes, but someone needs to write it (Moved to TODO list). +
  • +
  • + Should there be a choice of rounding mode (probably MPFR specific)? Moved + to TODO list. +
  • +
  • + Make the exponent type for cpp_dec_float a templare parameter, maybe + include support for big-integer exponents. Open question - what should + be the default - int32_t or int64_t? (done 2012/09/06) +
  • +
  • + Document the size requirements of fixed precision ints (done 2012/09/15). +
  • +
  • + Document std lib function accuracy (done 2012/09/15). +
  • +
  • + Be a bit clearer on the effects of sign-magnitude representation of cpp_int + - min == -max etc - done. +
  • +
  • + Document cpp_dec_float precision, rounding, and exponent size (done 2012/09/06). +
  • +
  • + Can we be clearer in the docs that mixed arithmetic doesn't work (no + longer applicable as of 2012/09/06)? +
  • +
  • + Document round functions behaviour better (they behave as in C++11) (added + note 2012/09/06). +
  • +
  • + Document limits on size of cpp_dec_float (done 2012/09/06). +
  • +
  • + Add support for fused multiply add (and subtract). GMP mpz_t could use + this (done 2012/09/20). +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf.html b/doc/html/boost_multiprecision/perf.html new file mode 100644 index 00000000..53ca5c0b --- /dev/null +++ b/doc/html/boost_multiprecision/perf.html @@ -0,0 +1,48 @@ + + + +Performance Comparison + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/float_performance.html b/doc/html/boost_multiprecision/perf/float_performance.html new file mode 100644 index 00000000..04026041 --- /dev/null +++ b/doc/html/boost_multiprecision/perf/float_performance.html @@ -0,0 +1,2070 @@ + + + +Float Algorithm Perfomance + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Note that these tests are carefully designed to test performance of the underlying + algorithms and not memory allocation or variable copying. As usual, performance + results should be taken with a healthy dose of scepticism, and real-world + performance may vary widely depending upon the specifics of the program. + In each table relative times are given first, with the best performer given + a score of 1. Total actual times are given in brackets, measured in seconds + for 500000 operations. +

+

+ Test code was compiled with Microsoft Visual Studio 2010 with all optimisations + turned on (/Ox), and used MPIR-2.3.0 and MPFR-3.0.0. + The tests were run on 32-bit Windows Vista machine. +

+
+

Table 1.10. Operator +

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.0575156s) +

+
+

+ 1 (0.0740086s) +

+
+

+ 1 (0.219073s) +

+
+

+ gmp_float +

+
+

+ 2.45065 (0.14095s) +

+
+

+ 2.01398 (0.149052s) +

+
+

+ 1.09608 (0.240122s) +

+
+

+ mpfr_float +

+
+

+ 2.6001 (0.149546s) +

+
+

+ 2.12079 (0.156957s) +

+
+

+ 1.09078 (0.23896s) +

+
+
+
+

Table 1.11. Operator +(int)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1.46115 (0.0855392s) +

+
+

+ 2.60353 (0.114398s) +

+
+

+ 3.62562 (0.264905s) +

+
+

+ gmp_float +

+
+

+ 1 (0.0585424s) +

+
+

+ 1 (0.0439398s) +

+
+

+ 1 (0.0730648s) +

+
+

+ mpfr_float +

+
+

+ 2.40441 (0.14076s) +

+
+

+ 3.2877 (0.144461s) +

+
+

+ 2.40379 (0.175632s) +

+
+
+
+

Table 1.12. Operator +(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.118146s) +

+
+

+ 1 (0.144714s) +

+
+

+ 1 (0.315639s) +

+
+

+ gmp_float +

+
+

+ 4.5555 (0.538213s) +

+
+

+ 3.83096 (0.554395s) +

+
+

+ 1.95079 (0.615745s) +

+
+

+ mpfr_float +

+
+

+ 5.74477 (0.678719s) +

+
+

+ 4.85295 (0.702291s) +

+
+

+ 2.70354 (0.853342s) +

+
+
+
+

Table 1.13. Operator +=(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.101188s) +

+
+

+ 1 (0.122394s) +

+
+

+ 1 (0.251975s) +

+
+

+ gmp_float +

+
+

+ 5.199 (0.526079s) +

+
+

+ 4.39327 (0.537712s) +

+
+

+ 2.42151 (0.610159s) +

+
+

+ mpfr_float +

+
+

+ 6.08318 (0.615547s) +

+
+

+ 5.18525 (0.634645s) +

+
+

+ 3.1022 (0.781677s) +

+
+
+
+

Table 1.14. Operator -

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.0895163s) +

+
+

+ 1 (0.129248s) +

+
+

+ 1.5088 (0.374512s) +

+
+

+ gmp_float +

+
+

+ 1.72566 (0.154474s) +

+
+

+ 1.22567 (0.158415s) +

+
+

+ 1 (0.248219s) +

+
+

+ mpfr_float +

+
+

+ 1.83764 (0.164499s) +

+
+

+ 1.34284 (0.173559s) +

+
+

+ 1.00226 (0.248781s) +

+
+
+
+

Table 1.15. Operator -(int)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.105285s) +

+
+

+ 1 (0.142741s) +

+
+

+ 1 (0.278718s) +

+
+

+ gmp_float +

+
+

+ 2.34437 (0.246828s) +

+
+

+ 1.28814 (0.183871s) +

+
+

+ 1.00731 (0.280754s) +

+
+

+ mpfr_float +

+
+

+ 2.8032 (0.295136s) +

+
+

+ 2.09178 (0.298582s) +

+
+

+ 1.25213 (0.34899s) +

+
+
+
+

Table 1.16. Operator -(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.13719s) +

+
+

+ 1 (0.184428s) +

+
+

+ 1 (0.344212s) +

+
+

+ gmp_float +

+
+

+ 4.0804 (0.559791s) +

+
+

+ 3.06776 (0.565781s) +

+
+

+ 2.07736 (0.715053s) +

+
+

+ mpfr_float +

+
+

+ 5.10114 (0.699828s) +

+
+

+ 3.88684 (0.716843s) +

+
+

+ 2.50074 (0.860784s) +

+
+
+
+

Table 1.17. Operator -=(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.100984s) +

+
+

+ 1 (0.123148s) +

+
+

+ 1 (0.246181s) +

+
+

+ gmp_float +

+
+

+ 5.68353 (0.573944s) +

+
+

+ 4.68636 (0.577116s) +

+
+

+ 2.6958 (0.663655s) +

+
+

+ mpfr_float +

+
+

+ 6.19738 (0.625834s) +

+
+

+ 5.18544 (0.638577s) +

+
+

+ 3.18738 (0.784673s) +

+
+
+
+

Table 1.18. Operator *

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1.03667 (0.284251s) +

+
+

+ 1.30576 (0.536527s) +

+
+

+ 1.44686 (4.81057s) +

+
+

+ gmp_float +

+
+

+ 1 (0.274196s) +

+
+

+ 1 (0.410891s) +

+
+

+ 1 (3.32484s) +

+
+

+ mpfr_float +

+
+

+ 1.24537 (0.341477s) +

+
+

+ 1.15785 (0.475749s) +

+
+

+ 1.1796 (3.92199s) +

+
+
+
+

Table 1.19. Operator *(int)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 3.97453 (0.240262s) +

+
+

+ 9.91222 (0.463473s) +

+
+

+ 50.7926 (4.36527s) +

+
+

+ gmp_float +

+
+

+ 1 (0.0604505s) +

+
+

+ 1 (0.0467577s) +

+
+

+ 1 (0.0859431s) +

+
+

+ mpfr_float +

+
+

+ 2.56974 (0.155342s) +

+
+

+ 3.56312 (0.166603s) +

+
+

+ 3.22964 (0.277565s) +

+
+
+
+

Table 1.20. Operator *(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.331877s) +

+
+

+ 1.01058 (0.586122s) +

+
+

+ 6.688 (4.7931s) +

+
+

+ gmp_float +

+
+

+ 1.72433 (0.572266s) +

+
+

+ 1 (0.579987s) +

+
+

+ 1 (0.716672s) +

+
+

+ mpfr_float +

+
+

+ 2.5553 (0.848047s) +

+
+

+ 1.74987 (1.0149s) +

+
+

+ 1.80403 (1.2929s) +

+
+
+
+

Table 1.21. Operator *=(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.321397s) +

+
+

+ 1.00772 (0.574887s) +

+
+

+ 6.65946 (4.7468s) +

+
+

+ gmp_float +

+
+

+ 1.77419 (0.570218s) +

+
+

+ 1 (0.570482s) +

+
+

+ 1 (0.712791s) +

+
+

+ mpfr_float +

+
+

+ 2.62172 (0.842611s) +

+
+

+ 1.77691 (1.01369s) +

+
+

+ 1.77511 (1.26528s) +

+
+
+
+

Table 1.22. Operator /

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 2.96096 (4.00777s) +

+
+

+ 4.53244 (7.86435s) +

+
+

+ 6.11936 (51.5509s) +

+
+

+ gmp_float +

+
+

+ 1 (1.35354s) +

+
+

+ 1 (1.73512s) +

+
+

+ 1 (8.42422s) +

+
+

+ mpfr_float +

+
+

+ 1.30002 (1.75963s) +

+
+

+ 1.39045 (2.41261s) +

+
+

+ 1.66762 (14.0484s) +

+
+
+
+

Table 1.23. Operator /(int)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 8.60726 (1.8181s) +

+
+

+ 15.4122 (3.67479s) +

+
+

+ 34.5119 (24.729s) +

+
+

+ gmp_float +

+
+

+ 1.24394 (0.262756s) +

+
+

+ 1 (0.238433s) +

+
+

+ 1 (0.716536s) +

+
+

+ mpfr_float +

+
+

+ 1 (0.211229s) +

+
+

+ 1.12178 (0.26747s) +

+
+

+ 1.02237 (0.732562s) +

+
+
+
+

Table 1.24. Operator /(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 2.10976 (1.97569s) +

+
+

+ 3.73601 (3.9133s) +

+
+

+ 11.3085 (25.4533s) +

+
+

+ gmp_float +

+
+

+ 1 (0.936452s) +

+
+

+ 1 (1.04746s) +

+
+

+ 1 (2.25081s) +

+
+

+ mpfr_float +

+
+

+ 1.3423 (1.257s) +

+
+

+ 1.51575 (1.58768s) +

+
+

+ 3.31513 (7.46175s) +

+
+
+
+

Table 1.25. Operator /=(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 2.17401 (1.96883s) +

+
+

+ 3.79591 (3.8965s) +

+
+

+ 11.2328 (25.2606s) +

+
+

+ gmp_float +

+
+

+ 1 (0.905621s) +

+
+

+ 1 (1.0265s) +

+
+

+ 1 (2.24882s) +

+
+

+ mpfr_float +

+
+

+ 1.37953 (1.24933s) +

+
+

+ 1.53073 (1.57129s) +

+
+

+ 3.30546 (7.43339s) +

+
+
+
+

Table 1.26. Operator construct

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.00929804s) +

+
+

+ 1 (0.0268321s) +

+
+

+ 1 (0.0310685s) +

+
+

+ gmp_float +

+
+

+ 30.8781 (0.287106s) +

+
+

+ 7.59969 (0.203916s) +

+
+

+ 6.51873 (0.202527s) +

+
+

+ mpfr_float +

+
+

+ 23.5296 (0.218779s) +

+
+

+ 8.11058 (0.217624s) +

+
+

+ 7.16325 (0.222552s) +

+
+
+
+

Table 1.27. Operator construct(unsigned)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.0603971s) +

+
+

+ 1 (0.0735485s) +

+
+

+ 1 (0.116464s) +

+
+

+ gmp_float +

+
+

+ 3.91573 (0.236498s) +

+
+

+ 2.88171 (0.211945s) +

+
+

+ 1.81075 (0.210887s) +

+
+

+ mpfr_float +

+
+

+ 4.90052 (0.295977s) +

+
+

+ 4.01118 (0.295017s) +

+
+

+ 2.62005 (0.305141s) +

+
+
+
+

Table 1.28. Operator construct(unsigned long long)

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 1 (0.0610288s) +

+
+

+ 1 (0.0759005s) +

+
+

+ 1 (0.118511s) +

+
+

+ gmp_float +

+
+

+ 8.26247 (0.504249s) +

+
+

+ 6.69042 (0.507806s) +

+
+

+ 4.32819 (0.51294s) +

+
+

+ mpfr_float +

+
+

+ 10.1593 (0.620013s) +

+
+

+ 8.45884 (0.64203s) +

+
+

+ 5.51472 (0.653557s) +

+
+
+
+

Table 1.29. Operator str

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 50 Bits +

+
+

+ 100 Bits +

+
+

+ 500 Bits +

+
+

+ cpp_dec_float +

+
+

+ 2.95848 (0.0223061s) +

+
+

+ 3.33461 (0.033471s) +

+
+

+ 3.0159 (0.132732s) +

+
+

+ gmp_float +

+
+

+ 1 (0.00753971s) +

+
+

+ 1 (0.0100374s) +

+
+

+ 1 (0.0440106s) +

+
+

+ mpfr_float +

+
+

+ 1.25424 (0.00945658s) +

+
+

+ 1.24943 (0.012541s) +

+
+

+ 1.09428 (0.0481601s) +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/int_real_world.html b/doc/html/boost_multiprecision/perf/int_real_world.html new file mode 100644 index 00000000..c1672066 --- /dev/null +++ b/doc/html/boost_multiprecision/perf/int_real_world.html @@ -0,0 +1,372 @@ + + + +Integer Real World Tests + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Test code was compiled with Microsoft Visual Studio 2010 with all optimisations + turned on (/Ox), and used MPIR-2.3.0 and libtommath-0.42.0. + The tests were run on 32-bit Windows Vista machine. +

+

+ The first set of tests + measure the times taken to execute the multiprecision part of the Voronoi-diagram + builder from Boost.Polygon. The tests mainly create a large number of temporaries + "just in case" multiprecision arithmetic is required, for comparison, + also included in the tests is Boost.Polygon's own partial-multiprecision + integer type which was custom written for this specific task: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Integer Type +

+
+

+ Relative Performance (Actual time in parenthesis) +

+
+

+ polygon::detail::extended_int +

+
+

+ 1(0.138831s) +

+
+

+ int256_t +

+
+

+ 1.19247(0.165551s) +

+
+

+ int512_t +

+
+

+ 1.23301(0.17118s) +

+
+

+ int1024_t +

+
+

+ 1.21463(0.168628s) +

+
+

+ checked_int256_t +

+
+

+ 1.31711(0.182855s) +

+
+

+ checked_int512_t +

+
+

+ 1.57413(0.218538s) +

+
+

+ checked_int1024_t +

+
+

+ 1.36992(0.190187s) +

+
+

+ cpp_int +

+
+

+ 1.63244(0.226632s) +

+
+

+ mpz_int +

+
+

+ 5.42511(0.753172s) +

+
+

+ tom_int +

+
+

+ 29.0793(4.03709s) +

+
+

+ Note how for this use case, any dynamic allocation is a performance killer. +

+

+ The next tests + measure the time taken to generate 1000 128-bit random numbers and test for + primality using the Miller Rabin test. This is primarily a test of modular-exponentiation + since that is the rate limiting step: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Integer Type +

+
+

+ Relative Performance (Actual time in parenthesis) +

+
+

+ cpp_int +

+
+

+ 5.25827(0.379597s) +

+
+

+ cpp_int (no Expression templates) +

+
+

+ 5.15675(0.372268s) +

+
+

+ cpp_int (128-bit cache) +

+
+

+ 5.10882(0.368808s) +

+
+

+ cpp_int (256-bit cache) +

+
+

+ 5.50623(0.397497s) +

+
+

+ cpp_int (512-bit cache) +

+
+

+ 4.82257(0.348144s) +

+
+

+ cpp_int (1024-bit cache) +

+
+

+ 5.00053(0.360991s) +

+
+

+ int1024_t +

+
+

+ 4.37589(0.315897s) +

+
+

+ checked_int1024_t +

+
+

+ 4.52396(0.326587s) +

+
+

+ mpz_int +

+
+

+ 1(0.0721905s) +

+
+

+ mpz_int (no Expression templates) +

+
+

+ 1.0248(0.0739806s) +

+
+

+ tom_int +

+
+

+ 2.60673(0.188181s) +

+
+

+ tom_int (no Expression templates) +

+
+

+ 2.64997(0.191303s) +

+
+

+ It's interesting to note that expression templates have little effect here + - perhaps because the actual expressions involved are relatively trivial + in this case - so the time taken for multiplication and division tends to + dominate. Also note how increasing the internal cache size used by cpp_int is quite effective in this case + in cutting out memory allocations altogether - cutting about a third off + the total runtime. Finally the much quicker times from GMP and tommath are + down to their much better modular-exponentiation algorithms (GMP's is about + 5x faster). That's an issue which needs to be addressed in a future release + for cpp_int. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/integer_performance.html b/doc/html/boost_multiprecision/perf/integer_performance.html new file mode 100644 index 00000000..1eea8f84 --- /dev/null +++ b/doc/html/boost_multiprecision/perf/integer_performance.html @@ -0,0 +1,4673 @@ + + + +Integer Algorithm Perfomance + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Note that these tests are carefully designed to test performance of the underlying + algorithms and not memory allocation or variable copying. As usual, performance + results should be taken with a healthy dose of scepticism, and real-world + performance may vary widely depending upon the specifics of the program. + In each table relative times are given first, with the best performer given + a score of 1. Total actual times are given in brackets, measured in seconds + for 500000 operations. +

+

+ Test code was compiled with Microsoft Visual Studio 2010 with all optimisations + turned on (/Ox), and used MPIR-2.3.0 and MPFR-3.0.0. + The tests were run on 32-bit Windows Vista machine. +

+

+ Linux x86_64 results are broadly similar, except that libtommath performs + much better there. +

+
+

Table 1.30. Operator +

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.22306 (0.0279933s) +

+
+

+ 1.15878 (0.038341s) +

+
+

+ 1.24006 (0.0562258s) +

+
+

+ 1.32055 (0.0925091s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.56093 (0.0357264s) +

+
+

+ 1.71757 (0.05683s) +

+
+

+ 1.66497 (0.0754916s) +

+
+

+ 1.70376 (0.119354s) +

+
+

+ gmp_int +

+
+

+ 1.98788 (0.0454986s) +

+
+

+ 1.37882 (0.0456216s) +

+
+

+ 1.14898 (0.0520959s) +

+
+

+ 1 (0.0700532s) +

+
+

+ tommath_int +

+
+

+ 1 (0.022888s) +

+
+

+ 1 (0.0330875s) +

+
+

+ 1 (0.0453411s) +

+
+

+ 1.07021 (0.074972s) +

+
+
+
+

Table 1.31. Operator +(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0162581s) +

+
+

+ 1 (0.0196602s) +

+
+

+ 1 (0.0305476s) +

+
+

+ 1 (0.0421105s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.3852 (0.0225207s) +

+
+

+ 1.84835 (0.036339s) +

+
+

+ 1.6111 (0.0492153s) +

+
+

+ 1.63014 (0.068646s) +

+
+

+ gmp_int +

+
+

+ 1.95525 (0.0317886s) +

+
+

+ 2.2217 (0.0436791s) +

+
+

+ 2.21508 (0.0676653s) +

+
+

+ 2.58759 (0.108965s) +

+
+

+ tommath_int +

+
+

+ 13.603 (0.221158s) +

+
+

+ 11.5797 (0.227659s) +

+
+

+ 7.86674 (0.24031s) +

+
+

+ 6.36923 (0.268212s) +

+
+
+
+

Table 1.32. Operator +(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0269712s) +

+
+

+ 1 (0.0296213s) +

+
+

+ 1 (0.0380242s) +

+
+

+ 1 (0.045841s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.38342 (0.0373126s) +

+
+

+ 1.51165 (0.0447769s) +

+
+

+ 1.54533 (0.05876s) +

+
+

+ 1.3971 (0.0640443s) +

+
+

+ gmp_int +

+
+

+ 26.7163 (0.72057s) +

+
+

+ 24.0631 (0.712781s) +

+
+

+ 19.6009 (0.745307s) +

+
+

+ 17.6547 (0.809308s) +

+
+

+ tommath_int +

+
+

+ 19.7493 (0.532664s) +

+
+

+ 18.2944 (0.541905s) +

+
+

+ 14.9127 (0.567043s) +

+
+

+ 12.9059 (0.591619s) +

+
+
+
+

Table 1.33. Operator +=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.16166 (0.020334s) +

+
+

+ 1.15312 (0.0204789s) +

+
+

+ 1.21086 (0.0216179s) +

+
+

+ 1.28088 (0.0229569s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0175043s) +

+
+

+ 1 (0.0177595s) +

+
+

+ 1 (0.0178534s) +

+
+

+ 1 (0.0179228s) +

+
+

+ gmp_int +

+
+

+ 39.0852 (0.684159s) +

+
+

+ 38.7246 (0.68773s) +

+
+

+ 38.2555 (0.68299s) +

+
+

+ 37.6736 (0.675217s) +

+
+

+ tommath_int +

+
+

+ 30.5872 (0.535408s) +

+
+

+ 29.371 (0.521614s) +

+
+

+ 30.3387 (0.541648s) +

+
+

+ 31.8346 (0.570565s) +

+
+
+
+

Table 1.34. Operator -

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.12975 (0.0308979s) +

+
+

+ 1 (0.0392305s) +

+
+

+ 1.05392 (0.0543957s) +

+
+

+ 1.18166 (0.0860767s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.36853 (0.0374283s) +

+
+

+ 1.45987 (0.0572717s) +

+
+

+ 1.44606 (0.0746349s) +

+
+

+ 1.55935 (0.11359s) +

+
+

+ gmp_int +

+
+

+ 1.53173 (0.0418917s) +

+
+

+ 1.17956 (0.0462749s) +

+
+

+ 1.13609 (0.0586365s) +

+
+

+ 1 (0.0728442s) +

+
+

+ tommath_int +

+
+

+ 1 (0.0273493s) +

+
+

+ 1.07293 (0.0420917s) +

+
+

+ 1 (0.0516126s) +

+
+

+ 1.0985 (0.0800191s) +

+
+
+
+

Table 1.35. Operator -(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0146171s) +

+
+

+ 1 (0.0172176s) +

+
+

+ 1 (0.023655s) +

+
+

+ 1 (0.0313105s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.49086 (0.021792s) +

+
+

+ 1.94917 (0.03356s) +

+
+

+ 1.89657 (0.0448632s) +

+
+

+ 1.82658 (0.057191s) +

+
+

+ gmp_int +

+
+

+ 2.16301 (0.0316169s) +

+
+

+ 2.55059 (0.0439151s) +

+
+

+ 2.67983 (0.0633913s) +

+
+

+ 3.27949 (0.102682s) +

+
+

+ tommath_int +

+
+

+ 14.0691 (0.20565s) +

+
+

+ 12.527 (0.215684s) +

+
+

+ 9.43355 (0.22315s) +

+
+

+ 7.64671 (0.239422s) +

+
+
+
+

Table 1.36. Operator -(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0265242s) +

+
+

+ 1 (0.0295275s) +

+
+

+ 1 (0.0377737s) +

+
+

+ 1 (0.0450106s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.2627 (0.033492s) +

+
+

+ 1.47472 (0.0435449s) +

+
+

+ 1.47468 (0.055704s) +

+
+

+ 1.40667 (0.0633151s) +

+
+

+ gmp_int +

+
+

+ 26.0595 (0.691208s) +

+
+

+ 23.3957 (0.690817s) +

+
+

+ 18.9344 (0.715223s) +

+
+

+ 16.9593 (0.763349s) +

+
+

+ tommath_int +

+
+

+ 19.26 (0.510855s) +

+
+

+ 17.6236 (0.52038s) +

+
+

+ 13.9134 (0.52556s) +

+
+

+ 12.2359 (0.550746s) +

+
+
+
+

Table 1.37. Operator -=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.28589 (0.0210146s) +

+
+

+ 1.3505 (0.0222463s) +

+
+

+ 1.34427 (0.0237863s) +

+
+

+ 1.22787 (0.0230902s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0163425s) +

+
+

+ 1 (0.0164727s) +

+
+

+ 1 (0.0176946s) +

+
+

+ 1 (0.0188051s) +

+
+

+ gmp_int +

+
+

+ 41.0201 (0.670371s) +

+
+

+ 41.4726 (0.683165s) +

+
+

+ 37.9503 (0.671514s) +

+
+

+ 35.6021 (0.669502s) +

+
+

+ tommath_int +

+
+

+ 32.6952 (0.534322s) +

+
+

+ 31.4882 (0.518695s) +

+
+

+ 29.3988 (0.5202s) +

+
+

+ 29.1175 (0.547558s) +

+
+
+
+

Table 1.38. Operator *

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.13172 (0.0766099s) +

+
+

+ 1.59509 (0.20993s) +

+
+

+ 1.40998 (0.70643s) +

+
+

+ 1.70758 (2.66895s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.067693s) +

+
+

+ 1.27132 (0.167319s) +

+
+

+ 1 (0.50102s) +

+
+

+ 1 (1.563s) +

+
+

+ gmp_int +

+
+

+ 1.01718 (0.0688559s) +

+
+

+ 1 (0.13161s) +

+
+

+ 1.13221 (0.567258s) +

+
+

+ 1.02292 (1.59883s) +

+
+

+ tommath_int +

+
+

+ 1.6793 (0.113677s) +

+
+

+ 2.66959 (0.351345s) +

+
+

+ 2.01091 (1.00751s) +

+
+

+ 2.05812 (3.21684s) +

+
+
+
+

Table 1.39. Operator *(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0228822s) +

+
+

+ 1.19988 (0.0332404s) +

+
+

+ 1.13882 (0.0416226s) +

+
+

+ 1.2711 (0.0665655s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.33157 (0.0304692s) +

+
+

+ 1.6546 (0.0458376s) +

+
+

+ 1.72684 (0.063114s) +

+
+

+ 1.83178 (0.0959269s) +

+
+

+ gmp_int +

+
+

+ 1.00858 (0.0230786s) +

+
+

+ 1 (0.0277032s) +

+
+

+ 1 (0.0365488s) +

+
+

+ 1 (0.0523682s) +

+
+

+ tommath_int +

+
+

+ 10.8491 (0.248252s) +

+
+

+ 9.88511 (0.273849s) +

+
+

+ 8.95509 (0.327298s) +

+
+

+ 8.04172 (0.421131s) +

+
+
+
+

Table 1.40. Operator *(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0574926s) +

+
+

+ 1 (0.0876613s) +

+
+

+ 1 (0.146194s) +

+
+

+ 1 (0.258556s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.12247 (0.0645337s) +

+
+

+ 1.24471 (0.109113s) +

+
+

+ 1.19748 (0.175065s) +

+
+

+ 1.17442 (0.303653s) +

+
+

+ gmp_int +

+
+

+ 12.271 (0.705488s) +

+
+

+ 8.23054 (0.7215s) +

+
+

+ 5.28668 (0.772883s) +

+
+

+ 3.09816 (0.801047s) +

+
+

+ tommath_int +

+
+

+ 10.2751 (0.590743s) +

+
+

+ 7.36707 (0.645807s) +

+
+

+ 4.88979 (0.71486s) +

+
+

+ 3.43724 (0.888719s) +

+
+
+
+

Table 1.41. Operator *=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 114.922 (7.57662s) +

+
+

+ 70.5882 (7.61458s) +

+
+

+ 44.3157 (7.67791s) +

+
+

+ 26.2881 (7.81595s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0659286s) +

+
+

+ 1 (0.107873s) +

+
+

+ 1 (0.173255s) +

+
+

+ 1 (0.297319s) +

+
+

+ gmp_int +

+
+

+ 47.9828 (3.16344s) +

+
+

+ 29.4972 (3.18196s) +

+
+

+ 18.1719 (3.14838s) +

+
+

+ 10.6941 (3.17956s) +

+
+

+ tommath_int +

+
+

+ 284.199 (18.7368s) +

+
+

+ 173.129 (18.676s) +

+
+

+ 109.052 (18.8938s) +

+
+

+ 64.5866 (19.2028s) +

+
+
+
+

Table 1.42. Operator /

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 2.71618 (0.616086s) +

+
+

+ 2.09988 (0.737246s) +

+
+

+ 1.65898 (0.94343s) +

+
+

+ 1.49441 (1.44418s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.226821s) +

+
+

+ 1 (0.35109s) +

+
+

+ 1 (0.56868s) +

+
+

+ 1 (0.966385s) +

+
+

+ gmp_int +

+
+

+ 3.82134 (0.866761s) +

+
+

+ 2.75998 (0.969001s) +

+
+

+ 1.93226 (1.09884s) +

+
+

+ 1.34132 (1.29623s) +

+
+

+ tommath_int +

+
+

+ 13.2978 (3.01622s) +

+
+

+ 11.3314 (3.97833s) +

+
+

+ 9.94138 (5.65347s) +

+
+

+ 13.3423 (12.8938s) +

+
+
+
+

Table 1.43. Operator /(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 4.15094 (0.23911s) +

+
+

+ 3.57962 (0.356615s) +

+
+

+ 3.11624 (0.578256s) +

+
+

+ 2.82967 (1.00414s) +

+
+

+ cpp_int(fixed) +

+
+

+ 2.42806 (0.139865s) +

+
+

+ 2.54164 (0.253208s) +

+
+

+ 2.43025 (0.450962s) +

+
+

+ 2.37209 (0.841768s) +

+
+

+ gmp_int +

+
+

+ 1 (0.0576038s) +

+
+

+ 1 (0.0996238s) +

+
+

+ 1 (0.185562s) +

+
+

+ 1 (0.354863s) +

+
+

+ tommath_int +

+
+

+ 36.3133 (2.09179s) +

+
+

+ 28.2731 (2.81668s) +

+
+

+ 21.8589 (4.05618s) +

+
+

+ 25.8061 (9.15762s) +

+
+
+
+

Table 1.44. Operator /(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.53953 (0.716927s) +

+
+

+ 1.40156 (1.65075s) +

+
+

+ 2.59584 (3.57744s) +

+
+

+ 4.58524 (8.3789s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.465679s) +

+
+

+ 1.09556 (1.29034s) +

+
+

+ 2.2858 (3.15016s) +

+
+

+ 4.40115 (8.0425s) +

+
+

+ gmp_int +

+
+

+ 2.25405 (1.04967s) +

+
+

+ 1 (1.17779s) +

+
+

+ 1 (1.37814s) +

+
+

+ 1 (1.82736s) +

+
+

+ tommath_int +

+
+

+ 5.03884 (2.34648s) +

+
+

+ 2.63459 (3.103s) +

+
+

+ 3.67287 (5.06174s) +

+
+

+ 6.77479 (12.38s) +

+
+
+
+

Table 1.45. Operator /=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.78744 (0.0586752s) +

+
+

+ 1.74065 (0.0616578s) +

+
+

+ 1.66814 (0.0740436s) +

+
+

+ 1.36231 (0.126362s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0328264s) +

+
+

+ 1 (0.0354222s) +

+
+

+ 1 (0.0443871s) +

+
+

+ 1 (0.0927553s) +

+
+

+ gmp_int +

+
+

+ 21.2392 (0.697207s) +

+
+

+ 19.3517 (0.68548s) +

+
+

+ 15.2936 (0.678837s) +

+
+

+ 7.37138 (0.683734s) +

+
+

+ tommath_int +

+
+

+ 32.8142 (1.07717s) +

+
+

+ 30.5556 (1.08235s) +

+
+

+ 24.7236 (1.09741s) +

+
+

+ 12.4072 (1.15084s) +

+
+
+
+

Table 1.46. Operator %

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.86833 (0.37472s) +

+
+

+ 1.43076 (0.491332s) +

+
+

+ 1.30757 (0.708055s) +

+
+

+ 1.2528 (1.15842s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.200565s) +

+
+

+ 1 (0.343407s) +

+
+

+ 1 (0.541503s) +

+
+

+ 1 (0.924662s) +

+
+

+ gmp_int +

+
+

+ 3.22603 (0.647027s) +

+
+

+ 2.08249 (0.715143s) +

+
+

+ 1.5148 (0.82027s) +

+
+

+ 1.09519 (1.01268s) +

+
+

+ tommath_int +

+
+

+ 15.4642 (3.10158s) +

+
+

+ 11.5534 (3.9675s) +

+
+

+ 10.5164 (5.69467s) +

+
+

+ 13.8962 (12.8493s) +

+
+
+
+

Table 1.47. Operator %(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.80079 (0.106617s) +

+
+

+ 1.96413 (0.207216s) +

+
+

+ 2.09096 (0.395682s) +

+
+

+ 2.14767 (0.776873s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.73532 (0.10274s) +

+
+

+ 1.92036 (0.202599s) +

+
+

+ 2.02172 (0.382579s) +

+
+

+ 2.07328 (0.749963s) +

+
+

+ gmp_int +

+
+

+ 1 (0.0592053s) +

+
+

+ 1 (0.1055s) +

+
+

+ 1 (0.189234s) +

+
+

+ 1 (0.361727s) +

+
+

+ tommath_int +

+
+

+ 35.6993 (2.11359s) +

+
+

+ 25.3086 (2.67007s) +

+
+

+ 21.2701 (4.02504s) +

+
+

+ 25.8662 (9.3565s) +

+
+
+
+

Table 1.48. Operator construct

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.17135 (0.00274853s) +

+
+

+ 1 (0.00275161s) +

+
+

+ 1 (0.00275161s) +

+
+

+ 1 (0.00344359s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.00234646s) +

+
+

+ 1.54518 (0.00425173s) +

+
+

+ 2.2494 (0.00618947s) +

+
+

+ 1.73247 (0.00596591s) +

+
+

+ gmp_int +

+
+

+ 85.6802 (0.201045s) +

+
+

+ 72.6635 (0.199941s) +

+
+

+ 78.1286 (0.214979s) +

+
+

+ 58.3553 (0.200952s) +

+
+

+ tommath_int +

+
+

+ 87.9831 (0.206449s) +

+
+

+ 74.8522 (0.205964s) +

+
+

+ 74.8918 (0.206073s) +

+
+

+ 63.4572 (0.218521s) +

+
+
+
+

Table 1.49. Operator construct(unsigned)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.43934 (0.00268554s) +

+
+

+ 1 (0.00286887s) +

+
+

+ 1 (0.00283465s) +

+
+

+ 1 (0.00290638s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.00186581s) +

+
+

+ 1.7597 (0.00504834s) +

+
+

+ 2.07419 (0.00587959s) +

+
+

+ 1.89871 (0.00551837s) +

+
+

+ gmp_int +

+
+

+ 125.861 (0.234832s) +

+
+

+ 72.7068 (0.208586s) +

+
+

+ 75.5147 (0.214058s) +

+
+

+ 71.2679 (0.207131s) +

+
+

+ tommath_int +

+
+

+ 240.568 (0.448854s) +

+
+

+ 155.552 (0.446257s) +

+
+

+ 157.598 (0.446734s) +

+
+

+ 160.728 (0.467137s) +

+
+
+
+

Table 1.50. Operator construct(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 2.3528 (0.00771495s) +

+
+

+ 1.61678 (0.00717424s) +

+
+

+ 1.12087 (0.00715985s) +

+
+

+ 1.2104 (0.0078878s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.00327905s) +

+
+

+ 1 (0.00443737s) +

+
+

+ 1 (0.00638775s) +

+
+

+ 1 (0.00651668s) +

+
+

+ gmp_int +

+
+

+ 222.775 (0.730489s) +

+
+

+ 165.447 (0.734148s) +

+
+

+ 114.708 (0.732725s) +

+
+

+ 112.162 (0.730926s) +

+
+

+ tommath_int +

+
+

+ 215.962 (0.70815s) +

+
+

+ 157.945 (0.700858s) +

+
+

+ 109.582 (0.699985s) +

+
+

+ 111.909 (0.729275s) +

+
+
+
+

Table 1.51. Operator str

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.46938 (0.00196575s) +

+
+

+ 1.37205 (0.00331355s) +

+
+

+ 1.5689 (0.00862952s) +

+
+

+ 1.57176 (0.0237239s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.00133781s) +

+
+

+ 1 (0.00241504s) +

+
+

+ 1 (0.00550035s) +

+
+

+ 1.20619 (0.0182059s) +

+
+

+ gmp_int +

+
+

+ 1.65482 (0.00221383s) +

+
+

+ 1.38972 (0.00335622s) +

+
+

+ 1.13845 (0.0062619s) +

+
+

+ 1 (0.0150938s) +

+
+

+ tommath_int +

+
+

+ 13.9845 (0.0187087s) +

+
+

+ 18.3179 (0.0442384s) +

+
+

+ 23.3489 (0.128427s) +

+
+

+ 25.3273 (0.382285s) +

+
+
+
+

Table 1.52. Operator gcd

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 2.03241 (5.06795s) +

+
+

+ 1.89904 (11.3002s) +

+
+

+ 1.99735 (27.4027s) +

+
+

+ 2.20708 (73.7574s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.67874 (4.18605s) +

+
+

+ 1.70044 (10.1184s) +

+
+

+ 1.96475 (26.9554s) +

+
+

+ 2.28347 (76.31s) +

+
+

+ gmp_int +

+
+

+ 1 (2.49357s) +

+
+

+ 1 (5.95047s) +

+
+

+ 1 (13.7195s) +

+
+

+ 1 (33.4185s) +

+
+

+ tommath_int +

+
+

+ 5.01832 (12.5135s) +

+
+

+ 4.41659 (26.2808s) +

+
+

+ 4.08042 (55.9814s) +

+
+

+ 3.97901 (132.972s) +

+
+
+
+

Table 1.53. Operator &

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.00344 (0.0315529s) +

+
+

+ 1 (0.0426295s) +

+
+

+ 1 (0.0543214s) +

+
+

+ 1.06624 (0.0835064s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0314446s) +

+
+

+ 1.0808 (0.046074s) +

+
+

+ 1.06116 (0.0576436s) +

+
+

+ 1 (0.0783186s) +

+
+

+ gmp_int +

+
+

+ 1.78372 (0.0560885s) +

+
+

+ 1.58661 (0.0676363s) +

+
+

+ 1.5738 (0.0854908s) +

+
+

+ 1.83409 (0.143644s) +

+
+

+ tommath_int +

+
+

+ 4.08054 (0.128311s) +

+
+

+ 3.50852 (0.149567s) +

+
+

+ 2.88826 (0.156894s) +

+
+

+ 4.45879 (0.349206s) +

+
+
+
+

Table 1.54. Operator &(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0367605s) +

+
+

+ 1 (0.0485394s) +

+
+

+ 1 (0.0650023s) +

+
+

+ 1 (0.099751s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.00324 (0.0368795s) +

+
+

+ 1.06734 (0.0518081s) +

+
+

+ 1.05192 (0.0683771s) +

+
+

+ 1.05296 (0.105034s) +

+
+

+ gmp_int +

+
+

+ 4.00058 (0.147063s) +

+
+

+ 3.02928 (0.147039s) +

+
+

+ 2.22221 (0.144449s) +

+
+

+ 1.45749 (0.145386s) +

+
+

+ tommath_int +

+
+

+ 8.83732 (0.324864s) +

+
+

+ 6.95191 (0.337442s) +

+
+

+ 5.42556 (0.352674s) +

+
+

+ 6.10829 (0.609309s) +

+
+
+
+

Table 1.55. Operator |

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0312723s) +

+
+

+ 1 (0.0428385s) +

+
+

+ 1 (0.0528083s) +

+
+

+ 1 (0.0827344s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.0311 (0.0322449s) +

+
+

+ 1.20267 (0.0515207s) +

+
+

+ 1.27028 (0.0670814s) +

+
+

+ 1.19432 (0.0988112s) +

+
+

+ gmp_int +

+
+

+ 1.55273 (0.0485576s) +

+
+

+ 1.4656 (0.0627839s) +

+
+

+ 1.66721 (0.0880424s) +

+
+

+ 1.67004 (0.13817s) +

+
+

+ tommath_int +

+
+

+ 4.15311 (0.129877s) +

+
+

+ 3.39008 (0.145226s) +

+
+

+ 2.88739 (0.152478s) +

+
+

+ 4.20575 (0.34796s) +

+
+
+
+

Table 1.56. Operator |(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1.01685 (0.030066s) +

+
+

+ 1 (0.0360965s) +

+
+

+ 1 (0.0402109s) +

+
+

+ 1 (0.0527074s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1 (0.0295677s) +

+
+

+ 1.50234 (0.0542292s) +

+
+

+ 1.52609 (0.0613656s) +

+
+

+ 1.37526 (0.0724863s) +

+
+

+ gmp_int +

+
+

+ 4.84414 (0.14323s) +

+
+

+ 3.99297 (0.144132s) +

+
+

+ 3.85375 (0.154963s) +

+
+

+ 2.91129 (0.153447s) +

+
+

+ tommath_int +

+
+

+ 10.8218 (0.319975s) +

+
+

+ 9.05203 (0.326747s) +

+
+

+ 8.32597 (0.334795s) +

+
+

+ 10.948 (0.577039s) +

+
+
+
+

Table 1.57. Operator ^

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0311003s) +

+
+

+ 1 (0.0430909s) +

+
+

+ 1 (0.0530915s) +

+
+

+ 1 (0.0842599s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.04721 (0.0325686s) +

+
+

+ 1.18557 (0.0510874s) +

+
+

+ 1.25714 (0.0667433s) +

+
+

+ 1.14462 (0.0964459s) +

+
+

+ gmp_int +

+
+

+ 1.59277 (0.0495356s) +

+
+

+ 1.47967 (0.0637601s) +

+
+

+ 1.73243 (0.0919772s) +

+
+

+ 1.68499 (0.141977s) +

+
+

+ tommath_int +

+
+

+ 4.17425 (0.12982s) +

+
+

+ 3.41013 (0.146946s) +

+
+

+ 2.8988 (0.153902s) +

+
+

+ 4.17074 (0.351426s) +

+
+
+
+

Table 1.58. Operator ^(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0290428s) +

+
+

+ 1 (0.0360261s) +

+
+

+ 1 (0.0409722s) +

+
+

+ 1 (0.0541785s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.01484 (0.0294736s) +

+
+

+ 1.4898 (0.0536716s) +

+
+

+ 1.34782 (0.0552234s) +

+
+

+ 1.35054 (0.0731703s) +

+
+

+ gmp_int +

+
+

+ 4.94574 (0.143638s) +

+
+

+ 4.05569 (0.146111s) +

+
+

+ 3.65257 (0.149654s) +

+
+

+ 2.89039 (0.156597s) +

+
+

+ tommath_int +

+
+

+ 10.8939 (0.316389s) +

+
+

+ 9.21322 (0.331916s) +

+
+

+ 8.17995 (0.335151s) +

+
+

+ 10.6902 (0.579178s) +

+
+
+
+

Table 1.59. Operator <<

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0253777s) +

+
+

+ 1.04239 (0.034484s) +

+
+

+ 1 (0.0420979s) +

+
+

+ 1 (0.0623485s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.05039 (0.0266563s) +

+
+

+ 1.40679 (0.0465388s) +

+
+

+ 1.34077 (0.0564434s) +

+
+

+ 1.20319 (0.0750171s) +

+
+

+ gmp_int +

+
+

+ 1.0359 (0.0262888s) +

+
+

+ 1 (0.0330815s) +

+
+

+ 1.1625 (0.0489388s) +

+
+

+ 1.16511 (0.0726428s) +

+
+

+ tommath_int +

+
+

+ 1.65904 (0.0421025s) +

+
+

+ 2.11201 (0.0698686s) +

+
+

+ 2.36727 (0.0996572s) +

+
+

+ 2.701 (0.168403s) +

+
+
+
+

Table 1.60. Operator >>

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_int +

+
+

+ 1 (0.0221035s) +

+
+

+ 1.0337 (0.0313761s) +

+
+

+ 1.03419 (0.0355718s) +

+
+

+ 1.20366 (0.0453508s) +

+
+

+ cpp_int(fixed) +

+
+

+ 1.1036 (0.0243933s) +

+
+

+ 1.12323 (0.0340936s) +

+
+

+ 1.40181 (0.0482162s) +

+
+

+ 1.69985 (0.0640463s) +

+
+

+ gmp_int +

+
+

+ 1.30456 (0.0288354s) +

+
+

+ 1 (0.0303532s) +

+
+

+ 1 (0.0343958s) +

+
+

+ 1 (0.0376776s) +

+
+

+ tommath_int +

+
+

+ 10.5766 (0.233779s) +

+
+

+ 9.0959 (0.27609s) +

+
+

+ 8.6249 (0.29666s) +

+
+

+ 13.6818 (0.515498s) +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/overhead.html b/doc/html/boost_multiprecision/perf/overhead.html new file mode 100644 index 00000000..4e4b91df --- /dev/null +++ b/doc/html/boost_multiprecision/perf/overhead.html @@ -0,0 +1,186 @@ + + + +The Overhead in the Number Class Wrapper + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Using a simple backend + class that wraps any built in arithmetic type we can measure the + overhead involved in wrapping a type inside the number + frontend, and the effect that turning on expression templates has. The following + table compares the performance between double + and a double wrapped inside + class number: +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Type +

+
+

+ Bessel Function Evaluation +

+
+

+ Non-Central T Evaluation +

+
+

+ double +

+
+

+ 1.0 (0.016s) +

+
+

+ 1.0 (0.46s) +

+
+

+ number<arithmetic_backend<double>, + et_off> +

+
+

+ 1.2 (0.019s) +

+
+

+ 1.0(0.46s) +

+
+

+ number<arithmetic_backend<double>, + et_on> +

+
+

+ 1.2 (0.019s) +

+
+

+ 1.7 (0.79s) +

+
+

+ As you can see whether there is an overhead, and how large it is depends + on the actual situation, but the overhead is in any cases small. Expression + templates generally add a greater overhead the more complex the expression + becomes due to the logic of figuring out how to best unpack and evaluate + the expression, but of course this is also the situation where you save more + temporaries. For a "trivial" backend like this, saving temporaries + has no benefit, but for larger types it becomes a bigger win. +

+

+ The following table compares arithmetic using either long + long or number<arithmetic_backend<long long> > for the voronoi-diagram + builder test: +

+
++++ + + + + + + + + + + + + + + +
+

+ Type +

+
+

+ Relative time +

+
+

+ long long +

+
+

+ 1.0(0.0823s) +

+
+

+ number<arithmetic_backend<long long>, et_off> +

+
+

+ 1.05 (0.0875s) +

+
+

+ This test involves mainly creating a lot of temporaries and performing a + small amount of arithmetic on them, with very little difference in performance + between the native and "wrapped" types. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/rational_performance.html b/doc/html/boost_multiprecision/perf/rational_performance.html new file mode 100644 index 00000000..d8b7efa5 --- /dev/null +++ b/doc/html/boost_multiprecision/perf/rational_performance.html @@ -0,0 +1,1950 @@ + + + +Rational Type Perfomance + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Note that these tests are carefully designed to test performance of the underlying + algorithms and not memory allocation or variable copying. As usual, performance + results should be taken with a healthy dose of scepticism, and real-world + performance may vary widely depending upon the specifics of the program. + In each table relative times are given first, with the best performer given + a score of 1. Total actual times are given in brackets, measured in seconds + for 500000 operations. +

+

+ Test code was compiled with Microsoft Visual Studio 2010 with all optimisations + turned on (/Ox), and used MPIR-2.3.0 and MPFR-3.0.0. + The tests were run on 32-bit Windows Vista machine. +

+
+

Table 1.61. Operator +

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 5.89417 (18.4116s) +

+
+

+ 6.87256 (47.4698s) +

+
+

+ 6.65008 (107.715s) +

+
+

+ 6.53801 (256.244s) +

+
+

+ mpq_rational +

+
+

+ 1 (3.1237s) +

+
+

+ 1 (6.90715s) +

+
+

+ 1 (16.1975s) +

+
+

+ 1 (39.1929s) +

+
+
+
+

Table 1.62. Operator +(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 3.62367 (2.46488s) +

+
+

+ 4.18291 (2.94603s) +

+
+

+ 4.726 (3.74866s) +

+
+

+ 6.1388 (5.56817s) +

+
+

+ mpq_rational +

+
+

+ 1 (0.680215s) +

+
+

+ 1 (0.704303s) +

+
+

+ 1 (0.7932s) +

+
+

+ 1 (0.907046s) +

+
+
+
+

Table 1.63. Operator +(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.1527 (2.6378s) +

+
+

+ 1.31751 (3.09863s) +

+
+

+ 1.58996 (4.00714s) +

+
+

+ 2.15642 (5.75702s) +

+
+

+ mpq_rational +

+
+

+ 1 (2.28837s) +

+
+

+ 1 (2.35189s) +

+
+

+ 1 (2.52028s) +

+
+

+ 1 (2.66971s) +

+
+
+
+

Table 1.64. Operator +=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.18436 (2.7059s) +

+
+

+ 1.32279 (3.11099s) +

+
+

+ 1.61398 (4.05389s) +

+
+

+ 2.20048 (5.84623s) +

+
+

+ mpq_rational +

+
+

+ 1 (2.2847s) +

+
+

+ 1 (2.35183s) +

+
+

+ 1 (2.51174s) +

+
+

+ 1 (2.6568s) +

+
+
+
+

Table 1.65. Operator -

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 5.81893 (18.3457s) +

+
+

+ 6.82209 (47.1928s) +

+
+

+ 6.64143 (107.498s) +

+
+

+ 6.51362 (255.137s) +

+
+

+ mpq_rational +

+
+

+ 1 (3.15277s) +

+
+

+ 1 (6.91765s) +

+
+

+ 1 (16.1859s) +

+
+

+ 1 (39.1698s) +

+
+
+
+

Table 1.66. Operator -(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 3.72441 (2.48756s) +

+
+

+ 4.27663 (2.98713s) +

+
+

+ 4.62109 (3.72114s) +

+
+

+ 6.17605 (5.56503s) +

+
+

+ mpq_rational +

+
+

+ 1 (0.667908s) +

+
+

+ 1 (0.698479s) +

+
+

+ 1 (0.805252s) +

+
+

+ 1 (0.901066s) +

+
+
+
+

Table 1.67. Operator -(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.15627 (2.63239s) +

+
+

+ 1.32096 (3.12092s) +

+
+

+ 1.61044 (4.00106s) +

+
+

+ 2.19378 (5.7644s) +

+
+

+ mpq_rational +

+
+

+ 1 (2.27663s) +

+
+

+ 1 (2.36262s) +

+
+

+ 1 (2.48445s) +

+
+

+ 1 (2.62761s) +

+
+
+
+

Table 1.68. Operator -=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.1984 (2.73444s) +

+
+

+ 1.34141 (3.15698s) +

+
+

+ 1.64159 (4.06997s) +

+
+

+ 2.23017 (5.88108s) +

+
+

+ mpq_rational +

+
+

+ 1 (2.28174s) +

+
+

+ 1 (2.35348s) +

+
+

+ 1 (2.47929s) +

+
+

+ 1 (2.63706s) +

+
+
+
+

Table 1.69. Operator *

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 5.4306 (32.5882s) +

+
+

+ 6.91805 (89.9436s) +

+
+

+ 6.94556 (207.307s) +

+
+

+ 6.88704 (492.151s) +

+
+

+ mpq_rational +

+
+

+ 1 (6.00084s) +

+
+

+ 1 (13.0013s) +

+
+

+ 1 (29.8475s) +

+
+

+ 1 (71.4604s) +

+
+
+
+

Table 1.70. Operator *(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 2.12892 (2.51376s) +

+
+

+ 2.47245 (3.07841s) +

+
+

+ 2.86832 (3.93619s) +

+
+

+ 3.94086 (6.02565s) +

+
+

+ mpq_rational +

+
+

+ 1 (1.18077s) +

+
+

+ 1 (1.24508s) +

+
+

+ 1 (1.3723s) +

+
+

+ 1 (1.52902s) +

+
+
+
+

Table 1.71. Operator *(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.32254 (5.43565s) +

+
+

+ 1.56078 (6.73163s) +

+
+

+ 1.97701 (9.32522s) +

+
+

+ 2.85404 (15.1573s) +

+
+

+ mpq_rational +

+
+

+ 1 (4.11002s) +

+
+

+ 1 (4.313s) +

+
+

+ 1 (4.71682s) +

+
+

+ 1 (5.31082s) +

+
+
+
+

Table 1.72. Operator *=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 6.29806 (58.1188s) +

+
+

+ 6.30556 (59.5076s) +

+
+

+ 6.3385 (62.1007s) +

+
+

+ 6.55345 (67.6905s) +

+
+

+ mpq_rational +

+
+

+ 1 (9.22804s) +

+
+

+ 1 (9.43733s) +

+
+

+ 1 (9.79739s) +

+
+

+ 1 (10.329s) +

+
+
+
+

Table 1.73. Operator /

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 4.4269 (66.8031s) +

+
+

+ 6.40103 (173.527s) +

+
+

+ 6.32347 (348.193s) +

+
+

+ 6.61148 (824.063s) +

+
+

+ mpq_rational +

+
+

+ 1 (15.0903s) +

+
+

+ 1 (27.1093s) +

+
+

+ 1 (55.0637s) +

+
+

+ 1 (124.641s) +

+
+
+
+

Table 1.74. Operator /(int)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.78772 (2.50984s) +

+
+

+ 2.10623 (3.10606s) +

+
+

+ 2.46986 (3.99358s) +

+
+

+ 3.37428 (5.96678s) +

+
+

+ mpq_rational +

+
+

+ 1 (1.40393s) +

+
+

+ 1 (1.4747s) +

+
+

+ 1 (1.61693s) +

+
+

+ 1 (1.76831s) +

+
+
+
+

Table 1.75. Operator /(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1.29695 (5.45454s) +

+
+

+ 1.55248 (6.85353s) +

+
+

+ 1.93237 (9.28765s) +

+
+

+ 2.75211 (14.8541s) +

+
+

+ mpq_rational +

+
+

+ 1 (4.20568s) +

+
+

+ 1 (4.41458s) +

+
+

+ 1 (4.80635s) +

+
+

+ 1 (5.39734s) +

+
+
+
+

Table 1.76. Operator /=(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 6.19401 (58.4278s) +

+
+

+ 6.20135 (59.643s) +

+
+

+ 6.21327 (62.0338s) +

+
+

+ 6.40576 (67.6778s) +

+
+

+ mpq_rational +

+
+

+ 1 (9.43295s) +

+
+

+ 1 (9.61774s) +

+
+

+ 1 (9.98407s) +

+
+

+ 1 (10.5652s) +

+
+
+
+

Table 1.77. Operator construct

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1 (0.00978288s) +

+
+

+ 1 (0.0100574s) +

+
+

+ 1 (0.0101393s) +

+
+

+ 1 (0.0101847s) +

+
+

+ mpq_rational +

+
+

+ 39.1516 (0.383015s) +

+
+

+ 38.3523 (0.385725s) +

+
+

+ 37.5812 (0.381048s) +

+
+

+ 37.6007 (0.382953s) +

+
+
+
+

Table 1.78. Operator construct(unsigned)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1 (0.0548151s) +

+
+

+ 1 (0.0557542s) +

+
+

+ 1 (0.055825s) +

+
+

+ 1 (0.0552808s) +

+
+

+ mpq_rational +

+
+

+ 7.21073 (0.395257s) +

+
+

+ 7.1016 (0.395944s) +

+
+

+ 7.02046 (0.391917s) +

+
+

+ 7.16881 (0.396297s) +

+
+
+
+

Table 1.79. Operator construct(unsigned long long)

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 1 (0.0605156s) +

+
+

+ 1 (0.0616657s) +

+
+

+ 1 (0.0592056s) +

+
+

+ 1 (0.0603081s) +

+
+

+ mpq_rational +

+
+

+ 35.1604 (2.12775s) +

+
+

+ 34.7575 (2.14335s) +

+
+

+ 35.7232 (2.11502s) +

+
+

+ 35.0437 (2.11342s) +

+
+
+
+

Table 1.80. Operator str

+
+++++++ + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ 128 Bits +

+
+

+ 256 Bits +

+
+

+ 512 Bits +

+
+

+ 1024 Bits +

+
+

+ cpp_rational +

+
+

+ 5.48898 (0.0208949s) +

+
+

+ 8.49668 (0.0546688s) +

+
+

+ 10.107 (0.121897s) +

+
+

+ 10.5339 (0.310584s) +

+
+

+ mpq_rational +

+
+

+ 1 (0.0038067s) +

+
+

+ 1 (0.00643413s) +

+
+

+ 1 (0.0120606s) +

+
+

+ 1 (0.0294843s) +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/perf/realworld.html b/doc/html/boost_multiprecision/perf/realworld.html new file mode 100644 index 00000000..6df14e07 --- /dev/null +++ b/doc/html/boost_multiprecision/perf/realworld.html @@ -0,0 +1,276 @@ + + + +Floating Point Real World Tests + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ These tests test the total time taken to execute all of Boost.Math's test + cases for these functions. In each case the best performing library gets + a relative score of 1, with the total execution time given in brackets. The + first three libraries listed are the various floating point types provided + by this library, while for comparison, two popular C++ front-ends to MPFR ( mpfr_class + and mpreal) are + also shown. +

+

+ Test code was compiled with Microsoft Visual Studio 2010 with all optimisations + turned on (/Ox), and used MPIR-2.3.0 and MPFR-3.0.0. + The tests were run on 32-bit Windows Vista machine. +

+
+

Table 1.8. Bessel Function Performance

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Library +

+
+

+ 50 Decimal Digits +

+
+

+ 100 Decimal Digits +

+
+

+ mpfr_float +

+
+

+ 1.2 (5.78s) +

+
+

+ 1.2 (9.56s) +

+
+

+ static_mpfr_float +

+
+

+ 1.1 (5.47s) +

+
+

+ 1.1 (9.09s) +

+
+

+ mpf_float +

+
+

+ 1.0 (4.82s) +

+
+

+ 1.0(8.07s) +

+
+

+ cpp_dec_float +

+
+

+ 1.8 (8.54s) +

+
+

+ 2.6 (20.66s) +

+
+

+ mpfr_class +

+
+

+ 1.3 (6.28s) +

+
+

+ 1.2(10.06s) +

+
+

+ mpreal +

+
+

+ 2.0 (9.54s) +

+
+

+ 1.7 (14.08s) +

+
+
+
+

Table 1.9. Non-Central T Distribution Performance

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Library +

+
+

+ 50 Decimal Digits +

+
+

+ mpfr_float +

+
+

+ 1.3 (263.27s) +

+
+

+ static_mpfr_float +

+
+

+ 1.2 (232.88s) +

+
+

+ mpf_float +

+
+

+ 1.0 (195.73s) +

+
+

+ cpp_dec_float +

+
+

+ 1.9 (366.38s) +

+
+

+ mpfr_class +

+
+

+ 1.5 (286.94s) +

+
+

+ mpreal +

+
+

+ 2.0 (388.70s) +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref.html b/doc/html/boost_multiprecision/ref.html new file mode 100644 index 00000000..c3d58d48 --- /dev/null +++ b/doc/html/boost_multiprecision/ref.html @@ -0,0 +1,47 @@ + + + +Reference + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/backendconc.html b/doc/html/boost_multiprecision/ref/backendconc.html new file mode 100644 index 00000000..2f6d4b91 --- /dev/null +++ b/doc/html/boost_multiprecision/ref/backendconc.html @@ -0,0 +1,3848 @@ + + + +Backend Requirements + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ The requirements on the Backend + template argument to number + are split up into sections: compulsory and optional. +

+

+ Compulsory requirements have no default implementation in the library, therefore + if the feature they implement is to be supported at all, then they must be + implemented by the backend. +

+

+ Optional requirements have default implementations that are called if the + backend doesn't provide it's own. Typically the backend will implement these + to improve performance. +

+

+ In the following tables, type B is the Backend + template argument to number, + b and b2 + are a variables of type B, cb, + cb2 and cb3 + are constant variables of type const + B, rb + is a variable of type B&&, + a and a2 + are variables of Arithmetic type, s + is a variable of type const char*, ui is a variable of type unsigned, bb + is a variable of type bool, + pa is a variable of type + pointer-to-arithmetic-type, exp + is a variable of type B::exp_type, pexp + is a variable of type B::exp_type*, + i is a variable of type + int, pi + pointer to a variable of type int, + B2 is another type that meets these requirements, b2 is a variable of type + B2. +

+
+

Table 1.4. Compulsory Requirements on the Backend type.

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Return Type +

+
+

+ Comments +

+
+

+ Throws +

+
+

+ B::signed_types +

+
+

+ mpl::list<type-list> +

+
+

+ A list of signed integral types that can be assigned to type B. + The types shall be listed in order of size, smallest first, and + shall terminate in the type that is std::intmax_t. +

+
+

+   +

+
+

+ B::unsigned_types +

+
+

+ mpl::list<type-list> +

+
+

+ A list of unsigned integral types that can be assigned to type + B. The types shall be listed in order of size, smallest first, + and shall terminate in the type that is std::uintmax_t. +

+
+

+   +

+
+

+ B::float_types +

+
+

+ mpl::list<type-list> +

+
+

+ A list of floating-point types that can be assigned to type B.The + types shall be listed in order of size, smallest first, and shall + terminate in type long double. +

+
+

+   +

+
+

+ B::exponent_type +

+
+

+ A signed integral type. +

+
+

+ The type of the exponent of type B. This type is required only + for floating point types. +

+
+

+   +

+
+

+ B() +

+
+ +

+ Default constructor. +

+
+

+   +

+
+

+ B(cb) +

+
+ +

+ Copy Constructor. +

+
+

+   +

+
+

+ b = + b +

+
+

+ B& +

+
+

+ Assignment operator. +

+
+

+   +

+
+

+ b = + a +

+
+

+ B& +

+
+

+ Assignment from an Arithmetic type. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. +

+
+

+   +

+
+

+ b = + s +

+
+

+ B& +

+
+

+ Assignment from a string. +

+
+

+ Throws a std::runtime_error if the string could + not be interpretted as a valid number. +

+
+

+ b.swap(b) +

+
+

+ void +

+
+

+ Swaps the contents of its arguments. +

+
+

+ noexcept +

+
+

+ cb.str(ui, + bb) +

+
+

+ std::string +

+
+

+ Returns the string representation of b + with ui digits + and in scientific format if bb + is true. If ui is zero, then returns as many + digits as are required to reconstruct the original value. +

+
+

+   +

+
+

+ b.negate() +

+
+

+ void +

+
+

+ Negates b. +

+
+

+   +

+
+

+ 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 if cb == cb2. +

+
+

+ noexcept +

+
+

+ 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 if cb == a. + The type of a shall + be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. +

+
+

+   +

+
+

+ eval_add(b, + cb) +

+
+

+ void +

+
+

+ Adds cb to b. +

+
+

+   +

+
+

+ eval_subtract(b, + cb) +

+
+

+ void +

+
+

+ Subtracts cb from + b. +

+
+

+   +

+
+

+ eval_multiply(b, + cb) +

+
+

+ void +

+
+

+ Multiplies b by + cb. +

+
+

+   +

+
+

+ eval_divide(b, + cb) +

+
+

+ void +

+
+

+ Divides b by cb. +

+
+

+ std::overflow_error if cb has the + value zero, and std::numeric_limits<number<B> >::has_infinity == + false +

+
+

+ eval_modulus(b, + cb) +

+
+

+ void +

+
+

+ Computes b %= + cb, only required when + B is an integer + type. +

+
+

+ std::overflow_error if cb has the + value zero. +

+
+

+ eval_bitwise_and(b, cb) +

+
+

+ void +

+
+

+ Computes b &= + cb, only required when + B is an integer + type. +

+
+

+   +

+
+

+ eval_bitwise_or(b, cb) +

+
+

+ void +

+
+

+ Computes b |= + cb, only required when + B is an integer + type. +

+
+

+   +

+
+

+ eval_bitwise_xor(b, cb) +

+
+

+ void +

+
+

+ Computes b ^= + cb, only required when + B is an integer + type. +

+
+

+   +

+
+

+ 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. +

+
+

+   +

+
+

+ eval_left_shift(b, ui) +

+
+

+ void +

+
+

+ Computes b <<= + ui, only required when + B is an integer + type. +

+
+

+   +

+
+

+ eval_right_shift(b, ui) +

+
+

+ void +

+
+

+ Computes b >>= + ui, only required when + B is an integer + type. +

+
+

+   +

+
+

+ eval_convert_to(pa, cb) +

+
+

+ void +

+
+

+ Converts cb to + the type of *pa + and store the result in *pa. Type B + shall support conversion to at least types std::intmax_t, + std::uintmax_t and long + long. Conversion to other + arithmetic types can then be synthesised using other operations. + Conversions to other types are entirely optional. +

+
+

+   +

+
+

+ eval_frexp(b, + cb, + pexp) +

+
+

+ void +

+
+

+ Stores values in b + and *pexp + such that the value of cb + is b * 2*pexp, only required when B + is a floating-point type. +

+
+

+   +

+
+

+ eval_ldexp(b, + cb, + exp) +

+
+

+ void +

+
+

+ Stores a value in b + that is cb * 2exp, only required when B + is a floating-point type. +

+
+

+   +

+
+

+ eval_frexp(b, + cb, + pi) +

+
+

+ void +

+
+

+ Stores values in b + and *pi + such that the value of cb + is b * 2*pi, only required when B + is a floating-point type. +

+
+

+ std::runtime_error if the exponent + of cb is too large to be stored in an int. +

+
+

+ eval_ldexp(b, + cb, + i) +

+
+

+ void +

+
+

+ Stores a value in b + that is cb * 2i, only required when B + is a floating-point type. +

+
+

+   +

+
+

+ eval_floor(b, + cb) +

+
+

+ void +

+
+

+ Stores the floor of cb + in b, only required + when B is a floating-point + type. +

+
+

+   +

+
+

+ eval_ceil(b, + cb) +

+
+

+ void +

+
+

+ Stores the ceiling of cb + in b, only required + when B is a floating-point + type. +

+
+

+   +

+
+

+ eval_sqrt(b, + cb) +

+
+

+ void +

+
+

+ Stores the square root of cb + in b, only required + when B is a floating-point + type. +

+
+

+   +

+
+

+ 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. + Defaults to number_kind_floating_point. +

+
+

+   +

+
+
+
+

Table 1.5. Optional Requirements on the Backend Type

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Expression +

+
+

+ Returns +

+
+

+ Comments +

+
+

+ Throws +

+
+

+ Construct and assign: +

+
   
+

+ B(rb) +

+
+

+ B +

+
+

+ Move constructor. Afterwards variable rb + shall be in sane state, albeit with unspecified value. Only destruction + and assignment to the moved-from variable rb + need be supported after the operation. +

+
+

+ noexcept +

+
+

+ b = + rb +

+
+

+ B& +

+
+

+ Move-assign. Afterwards variable rb + shall be in sane state, albeit with unspecified value. Only destruction + and assignment to the moved-from variable rb + need be supported after the operation. +

+
+

+ noexcept +

+
+

+ B(a) +

+
+

+ B +

+
+

+ Direct construction from an arithmetic type. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + this operation is simulated using default-construction followed + by assignment. +

+
+

+   +

+
+

+ B(b2) +

+
+

+ B +

+
+

+ Copy constructor from a different back-end type. When not provided, + a generic interconversion routine is used. This constructor may + be explicit if the + corresponding frontend constructor should also be explicit. +

+
+

+   +

+
+

+ b = + b2 +

+
+

+ b& +

+
+

+ Assignment operator from a different back-end type. When not provided, + a generic interconversion routine is used. +

+
+

+   +

+
+

+ assign_components(b, a, a) +

+
+

+ void +

+
+

+ Assigns to b the + two components in the following arguments. Only applies to rational + and complex number types. When not provided, arithmetic operations + are used to synthesise the result from the two values. +

+
+

+   +

+
+

+ assign_components(b, b2, b2) +

+
+

+ void +

+
+

+ Assigns to b the + two components in the following arguments. Only applies to rational + and complex number types. When not provided, arithmetic operations + are used to synthesise the result from the two values. +

+
+

+   +

+
+

+ Comparisons: +

+
   
+

+ eval_eq(cb, + cb2) +

+
+

+ bool +

+
+

+ Returns true if cb and cb2 + are equal in value. When not provided, the default implementation + returns cb.compare(cb2) + == 0. +

+
+

+ noexcept +

+
+

+ eval_eq(cb, + a) +

+
+

+ bool +

+
+

+ Returns true if cb and a + are equal in value. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided, + return the equivalent of eval_eq(cb, B(a)). +

+
+

+   +

+
+

+ eval_eq(a, + cb) +

+
+

+ bool +

+
+

+ Returns true if cb and a + are equal in value. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version returns eval_eq(cb, a). +

+
+

+   +

+
+

+ eval_lt(cb, + cb2) +

+
+

+ bool +

+
+

+ Returns true if cb is less than cb2 in value. When not provided, + the default implementation returns cb.compare(cb2) < + 0. +

+
+

+ noexcept +

+
+

+ eval_lt(cb, + a) +

+
+

+ bool +

+
+

+ Returns true if cb is less than a in value. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default implementation returns eval_lt(cb, B(a)). +

+
+

+   +

+
+

+ eval_lt(a, + cb) +

+
+

+ bool +

+
+

+ Returns true if a is less than cb in value. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default implementation returns eval_gt(cb, a). +

+
+

+   +

+
+

+ eval_gt(cb, + cb2) +

+
+

+ bool +

+
+

+ Returns true if cb is greater than cb2 in value. When not provided, + the default implementation returns cb.compare(cb2) > + 0. +

+
+

+ noexcept +

+
+

+ eval_gt(cb, + a) +

+
+

+ bool +

+
+

+ Returns true if cb is greater than a in value. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default implementation returns eval_gt(cb, B(a)). +

+
+

+   +

+
+

+ eval_gt(a, + cb) +

+
+

+ bool +

+
+

+ Returns true if a is greater than cb in value. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default implementation returns eval_lt(cb, a). +

+
+

+   +

+
+

+ eval_is_zero(cb) +

+
+

+ bool +

+
+

+ Returns true if cb is zero, otherwise false. The default version of this + function returns cb.compare(ui_type(0)) == + 0, where ui_type + is ui_type is + typename mpl::front<typename + B::unsigned_types>::type. +

+
+

+   +

+
+

+ 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. The default version of this function returns cb.compare(ui_type(0)), + where ui_type is + ui_type is typename mpl::front<typename + B::unsigned_types>::type. +

+
+

+   +

+
+

+ Basic arithmetic: +

+
   
+

+ eval_add(b, + a) +

+
+

+ void +

+
+

+ Adds a to b. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default version calls eval_add(b, B(a)) +

+
+

+   +

+
+

+ eval_add(b, + cb, + cb2) +

+
+

+ void +

+
+

+ Add cb to cb2 and stores the result in + b. When not provided, + does the equivalent of b + = cb; eval_add(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, B::unsigned_types + or B::float_types. When not provided, + does the equivalent of eval_add(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_add(b, cb, a). +

+
+

+   +

+
+

+ eval_subtract(b, + a) +

+
+

+ void +

+
+

+ Subtracts a from + b. The type of + a shall be listed + in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_subtract(b, B(a)) +

+
+

+   +

+
+

+ eval_subtract(b, + cb, + cb2) +

+
+

+ void +

+
+

+ Subtracts cb2 from + cb and stores the + result in b. When + not provided, does the equivalent of b + = cb; eval_subtract(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_subtract(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_subtract(b, cb, a); b.negate();. +

+
+

+   +

+
+

+ eval_multiply(b, + a) +

+
+

+ void +

+
+

+ Multiplies b by + a. The type of + a shall be listed + in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_multiply(b, B(a)) +

+
+

+   +

+
+

+ eval_multiply(b, + cb, + cb2) +

+
+

+ void +

+
+

+ Multiplies cb by + cb2 and stores + the result in b. + When not provided, does the equivalent of b + = cb; eval_multiply(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_multiply(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_multiply(b, cb, a). +

+
+

+   +

+
+

+ eval_multiply_add(b, cb, cb2) +

+
+

+ void +

+
+

+ Multiplies cb by + cb2 and adds the + result to b. When + not provided does the equivalent of creating a temporary B t + and eval_multiply(t, cb, cb2) followed by eval_add(b, t). +

+
+

+   +

+
+

+ eval_multiply_add(b, cb, a) +

+
+

+ void +

+
+

+ Multiplies a by + cb and adds the + result to b. The + type of a shall + be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided + does the equivalent of creating a temporary B + t and eval_multiply(t, cb, a) followed by eval_add(b, t). +

+
+

+   +

+
+

+ eval_multiply_add(b, a, cb) +

+
+

+ void +

+
+

+ Multiplies a by + cb and adds the + result to b. The + type of a shall + be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided + does the equivalent of eval_multiply_add(b, cb, a). +

+
+

+   +

+
+

+ eval_multiply_subtract(b, cb, cb2) +

+
+

+ void +

+
+

+ Multiplies cb by + cb2 and subtracts + the result from b. + When not provided does the equivalent of creating a temporary + B t + and eval_multiply(t, cb, cb2) followed by eval_subtract(b, t). +

+
+

+   +

+
+

+ eval_multiply_subtract(b, cb, a) +

+
+

+ void +

+
+

+ Multiplies a by + cb and subtracts + the result from b. + The type of a shall + be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided + does the equivalent of creating a temporary B + t and eval_multiply(t, cb, a) followed by eval_subtract(b, t). +

+
+

+   +

+
+

+ eval_multiply_subtract(b, a, cb) +

+
+

+ void +

+
+

+ Multiplies a by + cb and subtracts + the result from b. + The type of a shall + be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. When not provided + does the equivalent of eval_multiply_subtract(b, cb, a). +

+
+

+   +

+
+

+ eval_multiply_add(b, cb, cb2, cb3) +

+
+

+ void +

+
+

+ Multiplies cb by + cb2 and adds the + result to cb3 storing + the result in b. + When not provided does the equivalent of eval_multiply(b, cb, cb2) followed by eval_add(b, cb3). For brevity, only a version showing + all arguments of type B + is shown here, but you can replace up to any 2 of cb, cb2 + and cb3 with any + type type listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. +

+
+

+   +

+
+

+ eval_multiply_subtract(b, cb, cb2, cb3) +

+
+

+ void +

+
+

+ Multiplies cb by + cb2 and subtracts + from the result cb3 + storing the result in b. + When not provided does the equivalent of eval_multiply(b, cb, cb2) followed by eval_subtract(b, cb3). For brevity, only a version showing + all arguments of type B + is shown here, but you can replace up to any 2 of cb, cb2 + and cb3 with any + type type listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. +

+
+

+   +

+
+

+ eval_divide(b, + a) +

+
+

+ void +

+
+

+ Divides b by a. The type of a shall be listed in one of the + type lists B::signed_types, B::unsigned_types + or B::float_types. When not provided, + the default version calls eval_divide(b, B(a)) +

+
+

+ std::overflow_error if a has the value zero, and std::numeric_limits<number<B> + >::has_infinity + == false +

+
+

+ eval_divide(b, + cb, + cb2) +

+
+

+ void +

+
+

+ Divides cb by + cb2 and stores + the result in b. + When not provided, does the equivalent of b + = cb; eval_divide(b, cb2). +

+
+

+ std::overflow_error if cb2 has the value zero, and + std::numeric_limits<number<B> + >::has_infinity + == false +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_divide(b, cb, B(a)). +

+
+

+ std::overflow_error if a has the value zero, and std::numeric_limits<number<B> + >::has_infinity + == false +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_divide(b, B(a), cb). +

+
+

+ std::overflow_error if cb has the + value zero, and std::numeric_limits<number<B> >::has_infinity == + false +

+
+

+ eval_increment(b) +

+
+

+ void +

+
+

+ Increments the value of b + by one. When not provided, does the equivalent of eval_add(b, + static_cast<ui_type>(1u)). + Where ui_type is + typename mpl::front<typename + B::unsigned_types>::type. +

+
+

+   +

+
+

+ eval_decrement(b) +

+
+

+ void +

+
+

+ Decrements the value of b + by one. When not provided, does the equivalent of eval_subtract(b, + static_cast<ui_type>(1u)). + Where ui_type is + typename mpl::front<typename + B::unsigned_types>::type. +

+
+

+   +

+
+

+ Integer specific operations: +

+
   
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_modulus(b, B(a)) +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ eval_modulus(b, + cb, + cb2) +

+
+

+ void +

+
+

+ Computes cb % + cb2 and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_modulus(b, cb2). +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_modulus(b, cb, B(a)). +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_modulus(b, B(a), cb). +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_bitwise_and(b, B(a)) +

+
+

+   +

+
+

+ eval_bitwise_and(b, cb, cb2) +

+
+

+ void +

+
+

+ Computes cb & + cb2 and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_bitwise_and(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_and(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_and(b, cb, a). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_bitwise_or(b, B(a)) +

+
+

+   +

+
+

+ eval_bitwise_or(b, cb, cb2) +

+
+

+ void +

+
+

+ Computes cb | + cb2 and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_bitwise_or(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_or(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_or(b, cb, a). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + the default version calls eval_bitwise_xor(b, B(a)) +

+
+

+   +

+
+

+ eval_bitwise_xor(b, cb, cb2) +

+
+

+ void +

+
+

+ Computes cb ^ + cb2 and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_bitwise_xor(b, cb2). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_xor(b, cb, B(a)). +

+
+

+   +

+
+

+ 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 B::signed_types, + B::unsigned_types or B::float_types. When not provided, + does the equivalent of eval_bitwise_xor(b, cb, a). +

+
+

+   +

+
+

+ eval_left_shift(b, cb, ui) +

+
+

+ void +

+
+

+ Computes cb << + ui and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_left_shift(b, a);. +

+
+

+   +

+
+

+ eval_right_shift(b, cb, ui) +

+
+

+ void +

+
+

+ Computes cb >> + ui and stores the result + in b, only required + when B is an integer + type. When not provided, does the equivalent of b + = cb; eval_right_shift(b, a);. +

+
+

+   +

+
+

+ 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. The default version of this function is synthesised from + other operations above. +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ eval_integer_modulus(cb, ui) +

+
+

+ unsigned +

+
+

+ Returns the result of cb + % ui. + Only required when B + is an integer type. The default version of this function is synthesised + from other operations above. +

+
+

+ std::overflow_error if a has the value zero. +

+
+

+ eval_lsb(cb) +

+
+

+ unsigned +

+
+

+ Returns the index of the least significant bit that is set. Only + required when B + is an integer type. The default version of this function is synthesised + from other operations above. +

+
+

+   +

+
+

+ eval_bit_test(cb, + ui) +

+
+

+ bool +

+
+

+ Returns true if cb + has bit ui set. + Only required when B + is an integer type. The default version of this function is synthesised + from other operations above. +

+
+

+   +

+
+

+ eval_bit_set(b, + ui) +

+
+

+ void +

+
+

+ Sets the bit at index ui + in b. Only required + when B is an integer + type. The default version of this function is synthesised from + other operations above. +

+
+

+   +

+
+

+ eval_bit_unset(b, ui) +

+
+

+ void +

+
+

+ Unsets the bit at index ui + in b. Only required + when B is an integer + type. The default version of this function is synthesised from + other operations above. +

+
+

+   +

+
+

+ eval_bit_flip(b, + ui) +

+
+

+ void +

+
+

+ Flips the bit at index ui + in b. Only required + when B is an integer + type. The default version of this function is synthesised from + other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function is synthesised from + other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function is synthesised from + other operations above. +

+
+

+   +

+
+

+ 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. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. The default version + of this function calls eval_gcd(b, cb, B(a)). +

+
+

+   +

+
+

+ 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. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. The default version + of this function calls eval_lcm(b, cb, B(a)). +

+
+

+   +

+
+

+ 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. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. The default version + of this function calls eval_gcd(b, cb, a). +

+
+

+   +

+
+

+ 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. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types or B::float_types. The default version + of this function calls eval_lcm(b, cb, a). +

+
+

+   +

+
+

+ eval_powm(b, + cb, + cb2, + cb3) +

+
+

+ void +

+
+

+ Sets b to the result + of (cb^cb2)%cb3. The default version of this + function is synthesised from other operations above. +

+
+

+   +

+
+

+ eval_powm(b, + cb, + cb2, + a) +

+
+

+ void +

+
+

+ Sets b to the result + of (cb^cb2)%a. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types. The default version + of this function is synthesised from other operations above. +

+
+

+   +

+
+

+ eval_powm(b, + cb, + a, + cb2) +

+
+

+ void +

+
+

+ Sets b to the result + of (cb^a)%cb2. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types. The default version + of this function is synthesised from other operations above. +

+
+

+   +

+
+

+ eval_powm(b, + cb, + a, + a2) +

+
+

+ void +

+
+

+ Sets b to the result + of (cb^a)%a2. The type of a + shall be listed in one of the type lists B::signed_types, + B::unsigned_types. The default version + of this function is synthesised from other operations above. +

+
+

+   +

+
+

+ Sign manipulation: +

+
   
+

+ eval_abs(b, + cb) +

+
+

+ void +

+
+

+ Set b to the absolute + value of cb. The + default version of this functions assigns cb + to b, and then + calls b.negate() + if eval_get_sign(cb) < + 0. +

+
+

+   +

+
+

+ eval_fabs(b, + cb) +

+
+

+ void +

+
+

+ Set b to the absolute + value of cb. The + default version of this functions assigns cb + to b, and then + calls b.negate() + if eval_get_sign(cb) < + 0. +

+
+

+   +

+
+

+ Floating point functions: +

+
   
+

+ eval_fpclassify(cb) +

+
+

+ int +

+
+

+ Returns one of the same values returned by std::fpclassify. + Only required when B + is an floating-point type. The default version of this function + will only test for zero cb. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+

+ 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. The default version of this function + is synthesised from other operations above. +

+
+

+   +

+
+
+

+ When the tables above place no throws requirements on + an operation, then it is up to each type modelling this concept to decide + when or whether throwing an exception is desirable. However, thrown exceptions + should always either be the type, or inherit from the type std::runtime_error. + For example, a floating point type might choose to throw std::overflow_error + whenever the result of an operation would be infinite, and std::underflow_error + whenever it would round to zero. +

+
+ + + + + +
[Note]Note

+ The non-member functions are all named with an "eval_" prefix + to avoid conflicts with template classes of the same name - in point of + fact this naming convention shouldn't be necessary, but rather works around + some compiler bugs. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/cpp_dec_ref.html b/doc/html/boost_multiprecision/ref/cpp_dec_ref.html new file mode 100644 index 00000000..76a9f702 --- /dev/null +++ b/doc/html/boost_multiprecision/ref/cpp_dec_ref.html @@ -0,0 +1,64 @@ + + + +cpp_dec_float + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+template <unsigned Digits10>
+class cpp_dec_float;
+
+typedef number<cpp_dec_float<50> > cpp_dec_float_50;
+typedef number<cpp_dec_float<100> > cpp_dec_float_100;
+
+}} // namespaces
+
+

+ Class template cpp_dec_float + fulfills all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The class takes a single template parameter - Digits10 + - which is the number of decimal digits precision the type should support. + Note that this type does not ever perform any dynamic memory allocation, + as a result the Digits10 + template argument should not be set too high or the class's size will grow + unreasonably large. +

+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_floating_point>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/cpp_int_ref.html b/doc/html/boost_multiprecision/ref/cpp_int_ref.html new file mode 100644 index 00000000..36391a56 --- /dev/null +++ b/doc/html/boost_multiprecision/ref/cpp_int_ref.html @@ -0,0 +1,148 @@ + + + +cpp_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+typedef unspecified-type limb_type;
+
+enum cpp_integer_type    { signed_magnitude, unsigned_magnitude };
+enum cpp_int_check_type  { checked, unchecked };
+
+template <unsigned MinDigits = 0,
+          unsigned MaxDits = 0,
+          cpp_integer_type SignType = signed_magnitude,
+          cpp_int_check_type Checked = unchecked,
+          class Allocator = std::allocator<limb_type> >
+class cpp_int_backend;
+//
+// Expression templates default to et_off if there is no allocator:
+//
+template <unsigned MinDigits, unsigned MaxDigits, cpp_integer_type SignType, cpp_int_check_type Checked>
+struct expression_template_default<cpp_int_backend<MinDigits, MaxDigits, SignType, Checked, void> >
+{ static const expression_template_option value = et_off; };
+
+typedef number<cpp_int_backend<> >              cpp_int;    // arbitrary precision integer
+typedef rational_adapter<cpp_int_backend<> >    cpp_rational_backend;
+typedef number<cpp_rational_backend>            cpp_rational; // arbitrary precision rational number
+
+// Fixed precision unsigned types:
+typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >   uint128_t;
+typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >   uint256_t;
+typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >   uint512_t;
+typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
+
+// Fixed precision signed types:
+typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >     int128_t;
+typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >     int256_t;
+typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >     int512_t;
+typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >   int1024_t;
+
+// Over again, but with checking enabled this time:
+typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> >                 checked_cpp_int;
+typedef rational_adapter<cpp_int_backend<0, 0, signed_magnitude, checked> >       checked_cpp_rational_backend;
+typedef number<cpp_rational_backend>                                              checked_cpp_rational;
+
+// Checked fixed precision unsigned types:
+typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >     checked_uint128_t;
+typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >     checked_uint256_t;
+typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >     checked_uint512_t;
+typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> >   checked_uint1024_t;
+
+// Fixed precision signed types:
+typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >       checked_int128_t;
+typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >       checked_int256_t;
+typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >       checked_int512_t;
+typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >     checked_int1024_t;
+
+}} // namespaces
+
+

+ Class template cpp_int_backend + fulfills all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The template arguments are: +

+
+

+
+
MinBits
+

+ Determines the number of Bits to store directly within the object before + resorting to dynamic memory allocation. When zero, this field is determined + automatically based on how many bits can be stored in union with the + dynamic storage header: setting a larger value may improve performance + as larger integer values will be stored internally before memory allocation + is required. +

+
MaxBits
+

+ Determines the maximum number of bits to be stored in the type: resulting + in a fixed precision type. When this value is the same as MinBits, + then the Allocator parameter is ignored, as no dynamic memory allocation + will ever be performed: in this situation the Allocator parameter should + be set to type void. Note + that this parameter should not be used simply to prevent large memory + allocations, not only is that role better performed by the allocator, + but fixed precision integers have a tendency to allocate all of MaxBits + of storage more often than one would expect. +

+
SignType
+

+ Determines whether the resulting type is signed or not. Note that for + arbitrary + precision types this parameter must be signed_magnitude. + For fixed precision types then this type may be either signed_magnitude or unsigned_magnitude. +

+
Checked
+

+ This parameter has two values: checked + or unchecked. See the + tutorial + for more information. +

+
Allocator
+

+ The allocator to use for dynamic memory allocation, or type void if MaxBits == MinBits. +

+
+
+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_integer>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/gmp_int_ref.html b/doc/html/boost_multiprecision/ref/gmp_int_ref.html new file mode 100644 index 00000000..d7eefd2d --- /dev/null +++ b/doc/html/boost_multiprecision/ref/gmp_int_ref.html @@ -0,0 +1,54 @@ + + + +gmp_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+class gmp_int;
+
+typedef number<gmp_int >         mpz_int;
+
+}} // namespaces
+
+

+ Class template gmp_int fulfills + all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_integer>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/headers.html b/doc/html/boost_multiprecision/ref/headers.html new file mode 100644 index 00000000..4e55c754 --- /dev/null +++ b/doc/html/boost_multiprecision/ref/headers.html @@ -0,0 +1,415 @@ + + + +Header File Structure + + + + + + + + +
+PrevUpHomeNext +
+
+ +
+

Table 1.6. Top level headers

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Header +

+
+

+ Contains +

+
+

+ cpp_int.hpp +

+
+

+ The cpp_int backend + type. +

+
+

+ gmp.hpp +

+
+

+ Defines all GMP related + backends. +

+
+

+ miller_rabin.hpp +

+
+

+ Miller Rabin primality testing code. +

+
+

+ number.hpp +

+
+

+ Defines the number + backend, is included by all the backend headers. +

+
+

+ mpfr.hpp +

+
+

+ Defines the mpfr_float_backend backend. +

+
+

+ random.hpp +

+
+

+ Defines code to interoperate with Boost.Random. +

+
+

+ rational_adapter.hpp +

+
+

+ Defines the rational_adapter + backend. +

+
+

+ cpp_dec_float.hpp +

+
+

+ Defines the cpp_dec_float + backend. +

+
+

+ tommath.hpp +

+
+

+ Defines the tommath_int + backend. +

+
+

+ concepts/number_archetypes.hpp +

+
+

+ Defines a backend concept architypes for testing use. +

+
+
+
+

Table 1.7. Implementation Headers]

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Header +

+
+

+ Contains +

+
+

+ cpp_int/add.hpp +

+
+

+ Add and subtract operators for cpp_int_backend. +

+
+

+ cpp_int/bitwise.hpp +

+
+

+ Bitwise operators for cpp_int_backend. +

+
+

+ cpp_int/checked.hpp +

+
+

+ Helper functions for checked arithmetic for cpp_int_backend. +

+
+

+ cpp_int/comparison.hpp +

+
+

+ Comparison operators for cpp_int_backend. +

+
+

+ cpp_int/cpp_int_config.hpp +

+
+

+ Basic setup and configuration for cpp_int_backend. +

+
+

+ cpp_int/divide.hpp +

+
+

+ Division and modulus operators for cpp_int_backend. +

+
+

+ cpp_int/limits.hpp +

+
+

+ numeric_limits + support for cpp_int_backend. +

+
+

+ cpp_int/misc.hpp +

+
+

+ Miscellaneous operators for cpp_int_backend. +

+
+

+ cpp_int/multiply.hpp +

+
+

+ Multiply operators for cpp_int_backend. +

+
+

+ detail/big_lanczos.hpp +

+
+

+ Lanczos support for Boost.Math integration. +

+
+

+ detail/default_ops.hpp +

+
+

+ Default versions of the optional backend non-member functions. +

+
+

+ detail/generic_interconvert.hpp +

+
+

+ Generic interconversion routines. +

+
+

+ detail/number_base.hpp +

+
+

+ All the expression template code, metaprogramming, and operator + overloads for number. +

+
+

+ detail/no_et_ops.hpp +

+
+

+ The non-expression template operators. +

+
+

+ defail/functions/constants.hpp +

+
+

+ Defines constants used by the floating point functions. +

+
+

+ detail/functions/pow.hpp +

+
+

+ Defines default versions of the power and exponential related floating + point functions. +

+
+

+ detail/functions/trig.hpp +

+
+

+ Defines default versions of the trigonometric related floating + point functions. +

+
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/internals.html b/doc/html/boost_multiprecision/ref/internals.html new file mode 100644 index 00000000..8a6e979a --- /dev/null +++ b/doc/html/boost_multiprecision/ref/internals.html @@ -0,0 +1,105 @@ + + + +Internal Support Code + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ There are some traits classes which authors of new backends should be aware + of: +

+
namespace boost{ namespace multiprecision{ namespace detail{
+
+template<typename From, typename To>
+struct is_explicitly_convertible;
+
+}}}
+
+

+ Inherits from boost::integral_constant<bool,true> if type From + has an explicit conversion from To. +

+

+ For compilers that support C++11 SFINAE-expressions this trait should "just + work". Otherwise it inherits from boost::is_convertible<From, To>::type, and will need to be specialised for + Backends that have constructors marked as explicit. +

+
template <class From, class To>
+struct is_lossy_conversion
+{
+   static const bool value = see below;
+};
+
+

+ Member value is true if the + conversion from From to + To would result in a loss + of precision, and false otherwise. +

+

+ The default version of this trait simply checks whether the kind + of conversion (for example from a floating point to an integer type) is inherently + lossy. Note that if either of the types From + or To are of an unknown number + category (because number_category + is not specialised for that type) then this trait will be true. +

+
template<typename From, typename To>
+struct is_restricted_conversion
+{
+   static const bool value = see below;
+};
+
+

+ Member value is true if From + is only explicitly convertible to To + and not implicitly convertible, or if is_lossy_conversion<From, To>::value is true. + Otherwise false. +

+

+ Note that while this trait is the ultimate arbiter of which constructors + are marked as explicit in class + number, authors of backend + types should generally specialise one of the traits above, rather than this + one directly. +

+
template <class T>
+is_signed_number;
+template <class T>
+is_unsigned_number;
+
+

+ These two traits inherit from either mpl::true_ + or mpl::false_, by default types are assumed to + be signed unless is_unsigned_number + is specialized for that type. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/mpf_ref.html b/doc/html/boost_multiprecision/ref/mpf_ref.html new file mode 100644 index 00000000..7bb0616a --- /dev/null +++ b/doc/html/boost_multiprecision/ref/mpf_ref.html @@ -0,0 +1,70 @@ + + + +gmp_float + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+template <unsigned Digits10>
+class gmp_float;
+
+typedef number<gmp_float<50> >    mpf_float_50;
+typedef number<gmp_float<100> >   mpf_float_100;
+typedef number<gmp_float<500> >   mpf_float_500;
+typedef number<gmp_float<1000> >  mpf_float_1000;
+typedef number<gmp_float<0> >     mpf_float;
+
+}} // namespaces
+
+

+ Class template gmp_float + fulfills all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The class takes a single template parameter - Digits10 + - which is the number of decimal digits precision the type should support. + When this parameter is zero, then the precision can be set at runtime via + number::default_precision and number::precision. + Note that this type does not in any way change the GMP library's global state + (for example it does not change the default precision of the mpf_t data type), + therefore you can safely mix this type with existing code that uses GMP, + and also mix gmp_floats of + differing precision. +

+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_floating_point>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/mpfr_ref.html b/doc/html/boost_multiprecision/ref/mpfr_ref.html new file mode 100644 index 00000000..45c7dbfe --- /dev/null +++ b/doc/html/boost_multiprecision/ref/mpfr_ref.html @@ -0,0 +1,70 @@ + + + +mpfr_float_backend + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+template <unsigned Digits10>
+class mpfr_float_backend;
+
+typedef number<mpfr_float_backend<50> >    mpfr_float_50;
+typedef number<mpfr_float_backend<100> >   mpfr_float_100;
+typedef number<mpfr_float_backend<500> >   mpfr_float_500;
+typedef number<mpfr_float_backend<1000> >  mpfr_float_1000;
+typedef number<mpfr_float_backend<0> >     mpfr_float;
+
+}} // namespaces
+
+

+ Class template mpfr_float_backend + fulfills all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The class takes a single template parameter - Digits10 + - which is the number of decimal digits precision the type should support. + When this parameter is zero, then the precision can be set at runtime via + number::default_precision and number::precision. + Note that this type does not in any way change the GMP or MPFR library's + global state (for example it does not change the default precision of the + mpfr_t data type), therefore you can safely mix this type with existing code + that uses GMP or MPFR, and also mix mpfr_float_backends + of differing precision. +

+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_floating_point>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/number.html b/doc/html/boost_multiprecision/ref/number.html new file mode 100644 index 00000000..e1c5c399 --- /dev/null +++ b/doc/html/boost_multiprecision/ref/number.html @@ -0,0 +1,1259 @@ + + + +number + + + + + + + + +
+PrevUpHomeNext +
+
+

+number +

+
+ + Synopsis +
+
namespace boost{ namespace multiprecision{
+
+enum expression_template_option { et_on = 1, et_off = 0 };
+
+template <class Backend> struct expression_template_default
+{ static const expression_template_option value = et_on; };
+
+template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
+class number
+{
+   number();
+   number(see-below);
+   number& operator=(see-below);
+   number& assign(see-below);
+
+   // Member operators
+   number& operator+=(const see-below&);
+   number& operator-=(const see-below&);
+   number& operator*=(const see-below&);
+   number& operator/=(const see-below&);
+   number& operator++();
+   number& operator--();
+   number  operator++(int);
+   number  operator--(int);
+
+   number& operator%=(const see-below&);
+   number& operator&=(const see-below&);
+   number& operator|=(const see-below&);
+   number& operator^=(const see-below&);
+   number& operator<<=(const integer-type&);
+   number& operator>>=(const integer-type&);
+
+   // Use in Boolean context:
+   operator convertible-to-bool-type()const;
+   // swap:
+   void swap(number& other);
+   // Sign:
+   bool is_zero()const;
+   int sign()const;
+   // string conversion:
+   std::string str()const;
+   // Generic conversion mechanism
+   template <class T>
+   T convert_to()const;
+   template <class T>
+   explicit operator T ()const;
+   // precision control:
+   static unsigned default_precision();
+   static void default_precision(unsigned digits10);
+   unsigned precision()const;
+   void precision(unsigned digits10);
+   // Comparison:
+   int compare(const number<Backend>& o)const;
+   template <class V>
+   typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type
+      compare(const V& o)const;
+   // Access to the underlying implementation:
+   Backend& backend();
+   const Backend& backend()const;
+};
+
+// Non member operators:
+unmentionable-expression-template-type operator+(const see-below&);
+unmentionable-expression-template-type operator-(const see-below&);
+unmentionable-expression-template-type operator+(const see-below&, const see-below&);
+unmentionable-expression-template-type operator-(const see-below&, const see-below&);
+unmentionable-expression-template-type operator*(const see-below&, const see-below&);
+unmentionable-expression-template-type operator/(const see-below&, const see-below&);
+// Integer only operations:
+unmentionable-expression-template-type operator%(const see-below&, const see-below&);
+unmentionable-expression-template-type operator&(const see-below&, const see-below&);
+unmentionable-expression-template-type operator|(const see-below&, const see-below&);
+unmentionable-expression-template-type operator^(const see-below&, const see-below&);
+unmentionable-expression-template-type operator<<(const see-below&, const integer-type&);
+unmentionable-expression-template-type operator>>(const see-below&, const integer-type&);
+// Comparison operators:
+bool operator==(const see-below&, const see-below&);
+bool operator!=(const see-below&, const see-below&);
+bool operator< (const see-below&, const see-below&);
+bool operator> (const see-below&, const see-below&);
+bool operator<=(const see-below&, const see-below&);
+bool operator>=(const see-below&, const see-below&);
+
+// Swap:
+template <class Backend, expression_template_option ExpressionTemplates>
+void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b);
+
+// iostream support:
+template <class Backend, expression_template_option ExpressionTemplates>
+std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r);
+std::ostream& operator << (std::ostream& os, const unmentionable-expression-template-type& r);
+template <class Backend, expression_template_option ExpressionTemplates>
+std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r);
+
+// Arithmetic with a higher precision result:
+template <class ResultType, class Source1 class Source2>
+ResultType& add(ResultType& result, const Source1& a, const Source2& b);
+template <class ResultType, class Source1 class Source2>
+ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
+template <class ResultType, class Source1 class Source2>
+ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
+
+// Non-member function standard library support:
+unmentionable-expression-template-type    abs    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    fabs   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sqrt   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    floor  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    ceil   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    trunc  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    itrunc (const number-or-expression-template-type&);
+unmentionable-expression-template-type    ltrunc (const number-or-expression-template-type&);
+unmentionable-expression-template-type    lltrunc(const number-or-expression-template-type&);
+unmentionable-expression-template-type    round  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    iround (const number-or-expression-template-type&);
+unmentionable-expression-template-type    lround (const number-or-expression-template-type&);
+unmentionable-expression-template-type    llround(const number-or-expression-template-type&);
+unmentionable-expression-template-type    exp    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    log    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    log10    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    cos    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sin    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    tan    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    acos   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    asin   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    atan   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    cosh   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sinh   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    tanh   (const number-or-expression-template-type&);
+
+unmentionable-expression-template-type    ldexp (const number-or-expression-template-type&, int);
+unmentionable-expression-template-type    frexp (const number-or-expression-template-type&, int*);
+unmentionable-expression-template-type    pow   (const number-or-expression-template-type&, const number-or-expression-template-type&);
+unmentionable-expression-template-type    fmod  (const number-or-expression-template-type&, const number-or-expression-template-type&);
+unmentionable-expression-template-type    atan2 (const number-or-expression-template-type&, const number-or-expression-template-type&);
+
+// Traits support:
+template <class T>
+struct component_type;
+template <class T>
+struct number_category;
+template <class T>
+struct is_number;
+template <class T>
+struct is_number_expression;
+
+// Integer specific functions:
+unmentionable-expression-template-type    pow(const number-or-expression-template-type&, unsigned);
+unmentionable-expression-template-type    powm(const number-or-expression-template-type& b, const number-or-expression-template-type& p, const number-or-expression-template-type& m);
+template <class Backend, expression_template_option ExpressionTemplates>
+void divide_qr(const number-or-expression-template-type& x, const number-or-expression-template-type& y,
+               number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r);
+template <class Integer>
+Integer integer_modulus(const number-or-expression-template-type& x, Integer val);
+unsigned lsb(const number-or-expression-template-type& x);
+template <class Backend, class ExpressionTemplates>
+bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index);
+template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index);
+template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index);
+template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index);
+template <class Engine>
+bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials, Engine& gen);
+bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials);
+
+// Rational number support:
+typename component_type<number-or-expression-template-type>::type numerator  (const number-or-expression-template-type&);
+typename component_type<number-or-expression-template-type>::type denominator(const number-or-expression-template-type&);
+
+}} // namespaces
+
+namespace boost{ namespace math{
+
+// Boost.Math interoperability functions:
+int                                              fpclassify     (const number-or-expression-template-type&, int);
+bool                                             isfinite       (const number-or-expression-template-type&, int);
+bool                                             isnan          (const number-or-expression-template-type&, int);
+bool                                             isinf          (const number-or-expression-template-type&, int);
+bool                                             isnormal       (const number-or-expression-template-type&, int);
+
+}} // namespaces
+
+// numeric_limits support:
+namespace std{
+
+template <class Backend, expression_template_option ExpressionTemplates>
+struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> >
+{
+   /* Usual members here */
+};
+
+}
+
+
+ + Description +
+
enum expression_template_option { et_on = 1, et_off = 0 };
+
+

+ This enumerated type is used to specify whether expression templates are + turned on (et_on) or turned off (et_off). +

+
template <class Backend> struct expression_template_default
+{ static const expression_template_option value = et_on; };
+
+

+ This traits class specifies the default expression template option to be + used with a particular Backend type. It defaults to et_on. +

+
template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
+class number;
+
+

+ Class number has two template + arguments: +

+
+

+
+
Backend
+

+ The actual arithmetic back-end that does all the work. +

+
ExpressionTemplates
+

+ A Boolean value: when et_on, + then expression templates are enabled, otherwise when set to et_off they are disabled. The default + for this parameter is computed via the traits class expression_template_default + whose member value + defaults to et_on unless + the the traits class is specialized for a particular backend. +

+
+
+
number();
+number(see-below);
+number& operator=(see-below);
+number& assign(see-below);
+
+

+ Type number is default constructible, + and both copy constructible and assignable from: +

+
    +
  • + Itself. +
  • +
  • + An expression template which is the result of one of the arithmetic operators. +
  • +
  • + Any builtin arithmetic type, as long as the result would not be lossy + (for example float to integer conversion). +
  • +
  • + Any type that the Backend is implicitly constructible or assignable from. +
  • +
  • + An rvalue reference to another number. + Move-semantics are used for construction if the backend also supports + rvalue reference construction. In the case of assignment, move semantics + are always supported when the argument is an rvalue reference irrespective + of the backend. +
  • +
  • + Any type in the same family, as long as no loss of precision is involved. + For example from int128_t + to int256_t, or cpp_dec_float_50 to cpp_dec_float_100. +
  • +
+

+ Type number is explicitly + constructible from: +

+
    +
  • + Any type mentioned above. +
  • +
  • + A std::string or any type which is convertible + to const char*. +
  • +
  • + Any arithmetic type (including those that would result in lossy conversions). +
  • +
  • + Any type in the same family, including those that result in loss of precision. +
  • +
  • + Any type that the Backend is explicitly constructible from. +
  • +
  • + Any pair of types for which a generic interconversion exists: that is + from integer to integer, integer to rational, integer to float, rational + to rational, rational to float, or float to float. +
  • +
+

+ The assign member function is available for any type for which an explicit + converting constructor exists. It is intended to be used where a temporary + generated from an explicit assignment would be expensive, for example: +

+
mpfr_float_50    f50;
+mpfr_float_100   f100;
+
+f50 = static_cast<mpfr_float_50>(f100);  // explicit cast create a temporary
+f50.assign(f100);                        // explicit call to assign create no temporary
+
+

+ In addition, if the type has multiple components (for example rational or + complex number types), then there is a two argument constructor: +

+
number(arg1, arg2);
+
+

+ Where the two args must either be arithmetic types, or types that are convertible + to the two components of this. +

+
number& operator+=(const see-below&);
+number& operator-=(const see-below&);
+number& operator*=(const see-below&);
+number& operator/=(const see-below&);
+number& operator++();
+number& operator--();
+number  operator++(int);
+number  operator--(int);
+// Integer only operations:
+number& operator%=(const see-below&);
+number& operator&=(const see-below&);
+number& operator|=(const see-below&);
+number& operator^=(const see-below&);
+number& operator<<=(const integer-type&);
+number& operator>>=(const integer-type&);
+
+

+ These operators all take their usual arithmetic meanings. +

+

+ The arguments to these operators is either: +

+
    +
  • + Another number<Backend, + ExpressionTemplates>. +
  • +
  • + An expression template derived from number<Backend>. +
  • +
  • + Any type implicitly convertible to number<Backend, ExpressionTemplates>, including some other instance of + class number. +
  • +
+

+ For the left and right shift operations, the argument must be a builtin integer + type with a positive value (negative values result in a std::runtime_error + being thrown). +

+
operator convertible-to-bool-type()const;
+
+

+ Returns an unmentionable-type that is usable in Boolean + contexts (this allows number + to be used in any Boolean context - if statements, conditional statements, + or as an argument to a logical operator - without type number + being convertible to type bool. +

+

+ This operator also enables the use of number + with any of the following operators: !, + ||, && + and ?:. +

+
void swap(number& other);
+
+

+ Swaps *this + with other. +

+
bool is_zero()const;
+
+

+ Returns true is *this is zero, + otherwise false. +

+
int sign()const;
+
+

+ Returns a value less than zero if *this is negative, a value greater than zero + if *this + is positive, and zero if *this + is zero. +

+
std::string str(unsigned precision, bool scientific = true)const;
+
+

+ Returns the number formatted as a string, with at least precision + digits, and in scientific format if scientific is true. +

+
template <class T>
+T convert_to()const;
+
+template <class T>
+explicit operator T ()const;
+
+

+ Provides a generic conversion mechanism to convert *this to type T. + Type T may be any arithmetic + type. Optionally other types may also be supported by specific Backend types. +

+
static unsigned default_precision();
+static void default_precision(unsigned digits10);
+unsigned precision()const;
+void precision(unsigned digits10);
+
+

+ These functions are only available if the Backend template parameter supports + runtime changes to precision. They get and set the default precision and + the precision of *this + respectively. +

+
int compare(const number<Backend, ExpressionTemplates>& o)const;
+template <class V>
+typename enable_if<is_convertible<V, number<Backend, ExpressionTemplates> >, int>::type
+   compare(const V& other)const;
+
+

+ Returns: +

+
    +
  • + A value less that 0 for *this < other +
  • +
  • + A value greater that 0 for *this > other +
  • +
  • + Zero for *this + == other +
  • +
+
Backend& backend();
+const Backend& backend()const;
+
+

+ Returns the underlying back-end instance used by *this. +

+
+ + Non-member + operators +
+
// Non member operators:
+unmentionable-expression-template-type operator+(const see-below&);
+unmentionable-expression-template-type operator-(const see-below&);
+unmentionable-expression-template-type operator+(const see-below&, const see-below&);
+unmentionable-expression-template-type operator-(const see-below&, const see-below&);
+unmentionable-expression-template-type operator*(const see-below&, const see-below&);
+unmentionable-expression-template-type operator/(const see-below&, const see-below&);
+// Integer only operations:
+unmentionable-expression-template-type operator%(const see-below&, const see-below&);
+unmentionable-expression-template-type operator&(const see-below&, const see-below&);
+unmentionable-expression-template-type operator|(const see-below&, const see-below&);
+unmentionable-expression-template-type operator^(const see-below&, const see-below&);
+unmentionable-expression-template-type operator<<(const see-below&, const integer-type&);
+unmentionable-expression-template-type operator>>(const see-below&, const integer-type&);
+// Comparison operators:
+bool operator==(const see-below&, const see-below&);
+bool operator!=(const see-below&, const see-below&);
+bool operator< (const see-below&, const see-below&);
+bool operator> (const see-below&, const see-below&);
+bool operator<=(const see-below&, const see-below&);
+bool operator>=(const see-below&, const see-below&);
+
+

+ These operators all take their usual arithmetic meanings. +

+

+ The arguments to these functions must contain at least one of the following: +

+
    +
  • + A number. +
  • +
  • + An expression template type derived from number. +
  • +
  • + Any type for which number + has an implicit constructor - for example a builtin arithmetic type. +
  • +
+

+ The return type of these operators is either: +

+
    +
  • + An unmentionable-type expression template type when + ExpressionTemplates is + true. +
  • +
  • + Type number<Backend, + et_off> + when ExpressionTemplates + is false. +
  • +
  • + Type bool if the operator + is a comparison operator. +
  • +
+

+ Finally note that the second argument to the left and right shift operations + must be a builtin integer type, and that the argument must be positive (negative + arguments result in a std::runtime_error + being thrown). +

+
+ + swap +
+
template <class Backend, ExpressionTemplates>
+void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b);
+
+

+ Swaps a and b. +

+
+ + Iostream + Support +
+
template <class Backend, expression_template_option ExpressionTemplates>
+std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r);
+template <class Unspecified...>
+std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r);
+template <class Backend, expression_template_option ExpressionTemplates>
+inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
+
+

+ These operators provided formatted input-output operations on number types, and expression templates + derived from them. +

+

+ It's down to the back-end type to actually implement string conversion. However, + the back-ends provided with this library support all of the iostream formatting + flags, field width and precision settings. +

+
+ + Arithmetic + with a higher precision result +
+
template <class ResultType, class Source1 class Source2>
+ResultType& add(ResultType& result, const Source1& a, const Source2& b);
+
+template <class ResultType, class Source1 class Source2>
+ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
+
+template <class ResultType, class Source1 class Source2>
+ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
+
+

+ These functions apply the named operator to the arguments a + and b and store the result in result, + returning result. In all cases they behave "as + if" arguments a and b were + first promoted to type ResultType + before applying the operator, though particular backends may well avoid that + step by way of an optimization. +

+

+ The type ResultType must + be an instance of class number, + and the types Source1 and + Source2 may be either instances + of class number or native + integer types. The latter is an optimization that allows arithmetic to be + performed on native integer types producing an extended precision result. +

+
+ + Non-member + standard library function support +
+
unmentionable-expression-template-type    abs    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    fabs   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sqrt   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    floor  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    ceil   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    trunc  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    itrunc (const number-or-expression-template-type&);
+unmentionable-expression-template-type    ltrunc (const number-or-expression-template-type&);
+unmentionable-expression-template-type    lltrunc(const number-or-expression-template-type&);
+unmentionable-expression-template-type    round  (const number-or-expression-template-type&);
+unmentionable-expression-template-type    iround (const number-or-expression-template-type&);
+unmentionable-expression-template-type    lround (const number-or-expression-template-type&);
+unmentionable-expression-template-type    llround(const number-or-expression-template-type&);
+unmentionable-expression-template-type    exp    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    log    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    log10    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    cos    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sin    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    tan    (const number-or-expression-template-type&);
+unmentionable-expression-template-type    acos   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    asin   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    atan   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    cosh   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    sinh   (const number-or-expression-template-type&);
+unmentionable-expression-template-type    tanh   (const number-or-expression-template-type&);
+
+unmentionable-expression-template-type    ldexp (const number-or-expression-template-type&, int);
+unmentionable-expression-template-type    frexp (const number-or-expression-template-type&, int*);
+unmentionable-expression-template-type    pow   (const number-or-expression-template-type&, const number-or-expression-template-type&);
+unmentionable-expression-template-type    fmod  (const number-or-expression-template-type&, const number-or-expression-template-type&);
+unmentionable-expression-template-type    atan2 (const number-or-expression-template-type&, const number-or-expression-template-type&);
+
+

+ These functions all behave exactly as their standard library C++11 counterparts + do: their argument is either an instance of number + or an expression template derived from it; If the argument is of type number<Backend, et_off> + then that is also the return type, otherwise the return type is an expression + template. +

+

+ These functions are normally implemented by the Backend type. However, default + versions are provided for Backend types that don't have native support for + these functions. Please note however, that this default support requires + the precision of the type to be a compile time constant - this means for + example that the GMP MPF Backend will + not work with these functions when that type is used at variable precision. +

+

+ Also note that with the exception of abs + that these functions can only be used with floating-point Backend types (if + any other types such as fixed precision or complex types are added to the + library later, then these functions may be extended to support those number + types). +

+

+ The precision of these functions is generally deterimined by the backend + implementation. For example the precision of these functions when used with + mpfr_float + is determined entirely by MPFR. + When these functions use our own implementations, the accuracy of the transcendal + functions is generally a few epsilon. Note however, that the trigonmetrical + functions incur the usual accuracy loss when reducing arguments by large + multiples of π. Also note that both gmp_float + and cpp_dec_float + have a number of guard digits beyond their stated precision, so the error + rates listed for these are in some sense artificially low. +

+

+ The following table shows the error rates we observe for these functions + with various backend types, functions not listed here are exact (tested on + Win32 with VC++10, MPFR-3.0.0, MPIR-2.1.1): +

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Function +

+
+

+ mpfr_float_50 +

+
+

+ mpf_float_50 +

+
+

+ cpp_dec_float_50 +

+
+

+ sqrt +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ exp +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ log +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ log10 +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ cos +

+
+

+ 700eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ sin +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ tan +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ acos +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ asin +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ atan +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ cosh +

+
+

+ 1045eps[1] +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ sinh +

+
+

+ 2eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ tanh +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+
+

+ pow +

+
+

+ 0eps +

+
+

+ 4eps +

+
+

+ 3eps +

+
+

+ atan2 +

+
+

+ 1eps +

+
+

+ 0eps +

+
+

+ 0eps +

+

[1] + It's likely that the inherent error in the input values to our + test cases are to blame here. +

+
+ + Traits Class + Support +
+
template <class T>
+struct component_type;
+
+

+ If this is a type with multiple components (for example rational or complex + types), then this trait has a single member type + that is the type of those components. +

+
template <class T>
+struct number_category;
+
+

+ A traits class that inherits from mpl::int_<N> + where N is one of the enumerated + values number_kind_integer, + number_kind_floating_point, + number_kind_rational, number_kind_fixed_point, or number_kind_unknown. This traits class + is specialized for any type that has std::numeric_limits + support as well as for classes in this library: which means it can be used + for generic code that must work with built in arithmetic types as well as + multiprecision ones. +

+
template <class T>
+struct is_number;
+
+

+ A traits class that inherits from mpl::true_ + if T is an instance of number<>, otherwise from mpl::false_. +

+
template <class T>
+struct is_number_expression;
+
+

+ A traits class that inherits from mpl::true_ + if T is an expression template type derived from number<>, otherwise from mpl::false_. +

+
+ + Integer + functions +
+

+ In addition to functioning with types from this library, these functions + are also overloaded for built in integer types if you include <boost/multiprecision/integer.hpp>. + Further, when used with fixed precision types (whether built in integers + or multiprecision ones), the functions will promote to a wider type internally + when the algorithm requires it. Versions overloaded for built in integer + types return that integer type rather than an expression template. +

+
unmentionable-expression-template-type    pow(const number-or-expression-template-type& b, unsigned p);
+
+

+ Returns bp as an expression template. Note that this + function should be used with extreme care as the result can grow so large + as to take "effectively forever" to compute, or else simply run + the host machine out of memory. This is the one function in this category + that is not overloaded for built in integer types, further, it's probably + not a good idea to use it with fixed precision cpp_int's + either. +

+
unmentionable-expression-template-type    powm(const number-or-expression-template-type& b, const number-or-expression-template-type& p, const number-or-expression-template-type& m);
+
+

+ Returns bp mod m as an expression template. Fixed precision + types are promoted internally to ensure accuracy. +

+
template <class Backend, expression_template_option ExpressionTemplates>
+void divide_qr(const number-or-expression-template-type& x, const number-or-expression-template-type& y,
+               number<Backend, ExpressionTemplates>& q, number<Backend, ExpressionTemplates>& r);
+
+

+ Divides x by y and returns both the quotient and remainder. After the call + q = + x / y and r + = x % y. +

+
template <class Integer>
+Integer integer_modulus(const number-or-expression-template-type& x, Integer val);
+
+

+ Returns the absolute value of x + % val. +

+
unsigned lsb(const number-or-expression-template-type& x);
+
+

+ Returns the index of the least significant bit that is set to 1. +

+

+ Throws a std::range_error if the argument is <= 0. +

+
template <class Backend, class ExpressionTemplates>
+bool bit_test(const number<Backend, ExpressionTemplates>& val, unsigned index);
+
+

+ Returns true if the bit at + index in val is set. +

+
template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_set(number<Backend, ExpressionTemplates>& val, unsigned index);
+
+

+ Sets the bit at index in val, and + returns val. +

+
template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_unset(number<Backend, ExpressionTemplates>& val, unsigned index);
+
+

+ Unsets the bit at index in val, + and returns val. +

+
template <class Backend, class ExpressionTemplates>
+number<Backend, ExpressionTemplates>& bit_flip(number<Backend, ExpressionTemplates>& val, unsigned index);
+
+

+ Flips the bit at index in val, + and returns val. +

+
template <class Engine>
+bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials, Engine& gen);
+bool miller_rabin_test(const number-or-expression-template-type& n, unsigned trials);
+
+

+ Tests to see if the number n is probably prime - the + test excludes the vast majority of composite numbers by excluding small prime + factors and performing a single Fermat test. Then performs trials + Miller-Rabin tests. Returns false + if n is definitely composite, or true + if n is probably prime with the probability of it being + composite less than 0.25^trials. Fixed precision types are promoted internally + to ensure accuracy. +

+
+ + Rational + Number Functions +
+
typename component_type<number-or-expression-template-type>::type numerator  (const number-or-expression-template-type&);
+typename component_type<number-or-expression-template-type>::type denominator(const number-or-expression-template-type&);
+
+

+ These functions return the numerator and denominator of a rational number + respectively. +

+
+ + Boost.Math + Interoperability Support +
+
namespace boost{ namespace math{
+
+int  fpclassify     (const number-or-expression-template-type&, int);
+bool isfinite       (const number-or-expression-template-type&, int);
+bool isnan          (const number-or-expression-template-type&, int);
+bool isinf          (const number-or-expression-template-type&, int);
+bool isnormal       (const number-or-expression-template-type&, int);
+
+}} // namespaces
+
+

+ These floating-point classification functions behave exactly as their Boost.Math + equivalents. +

+

+ Other Boost.Math functions and templates may also be specialized or overloaded + to ensure interoperability. +

+
+ + std::numeric_limits + support +
+
namespace std{
+
+template <class Backend, ExpressionTemplates>
+struct numeric_limits<boost::multiprecision<Backend, ExpressionTemplates> >
+{
+   /* Usual members here */
+};
+
+}
+
+

+ Class template std::numeric_limits is specialized for all instantiations + of number whose precision + is known at compile time, plus those types whose precision is unlimited (though + it is much less useful in those cases). It is not specialized for types whose + precision can vary at compile time (such as mpf_float). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/ref/tom_int_ref.html b/doc/html/boost_multiprecision/ref/tom_int_ref.html new file mode 100644 index 00000000..3134b00b --- /dev/null +++ b/doc/html/boost_multiprecision/ref/tom_int_ref.html @@ -0,0 +1,54 @@ + + + +tom_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+class tommath_int;
+
+typedef number<tommath_int >         tom_int;
+
+}} // namespaces
+
+

+ Class template tommath_int + fulfills all of the requirements for a Backend + type. Its members and non-member functions are deliberately not documented: + these are considered implementation details that are subject to change. +

+

+ The type of number_category<cpp_int<Args...> >::type is mpl::int_<number_kind_integer>. +

+

+ More information on this type can be found in the tutorial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut.html b/doc/html/boost_multiprecision/tut.html new file mode 100644 index 00000000..a54194d1 --- /dev/null +++ b/doc/html/boost_multiprecision/tut.html @@ -0,0 +1,86 @@ + + + +Tutorial + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/conversions.html b/doc/html/boost_multiprecision/tut/conversions.html new file mode 100644 index 00000000..29ca1eff --- /dev/null +++ b/doc/html/boost_multiprecision/tut/conversions.html @@ -0,0 +1,168 @@ + + + +Constructing and Interconverting Between Number Types + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ All of the number types that are based on number + have certain conversion rules in common. In particular: +

+
  • + Any number type can be constructed (or assigned) from any builtin arithmetic + type, as long as the conversion isn't lossy (for example float to int + conversion): +
+
cpp_dec_float_50 df(0.5);   // OK construction from double
+cpp_int          i(450);    // OK constructs from signed int
+cpp_int          j = 3.14;  // Error, lossy conversion.
+
+
  • + A number can be explicitly constructed from an arithmetic type, even + when the conversion is lossy: +
+
cpp_int          i(3.14);       // OK explicit conversion
+i = static_cast<cpp_int>(3.14)  // OK explicit conversion
+i.assign(3.14);                 // OK, explicit assign and avoid a temporary from the cast above
+i = 3.14;                       // Error, no implicit assignment operator for lossy conversion.
+cpp_int          j = 3.14;      // Error, no implicit constructor for lossy conversion.
+
+
  • + A number can be converted + to any built in type, via the convert_to + member function: +
+
mpz_int z(2);
+int i = z.template convert_to<int>(); // sets i to 2
+
+

+ Additional conversions may be supported by particular backends. +

+
  • + A number can be converted + to any built in type, via an explicit conversion operator: this functionality + is only available on compilers supporting C++11's explicit conversion + syntax. +
+
mpz_int z(2);
+int i = z;                     // Error, implicit conversion not allowed.
+int j = static_cast<int>(z);   // OK explicit conversion.
+
+
  • + Any number type can be explicitly constructed (or + assigned) from a const char* + or a std::string: +
+
// pi to 50 places from a string:
+cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510");
+// Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly:
+cpp_int          i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000");
+// Invalid input always results in a std::runtime_error being thrown:
+i = static_cast<cpp_int>("3.14");
+// implicit conversions from strings are not allowed:
+i = "23"; // Error, no assignment operator for implicit conversion from string
+// assign member function, avoids having to create a temporary via a static_cast:
+i.assign("23");  // OK
+
+
  • + Any number type will interoperate with the builtin types in arithmetic + expressions as long as the conversions are not lossy: +
+
// pi to 50 places from a string:
+cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
+// Multiply by 2 - using an integer literal here is usually more efficient
+// than constructing a temporary:
+df *= 2;
+
+// You can't mix integer types with floats though:
+cpp_int i = 2;
+i *= 3.14;  // Error, no *= operator will be found.
+
+
  • + Any number type can be streamed to and from the C++ iostreams: +
+
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
+// Now print at full precision:
+std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
+   << df << std::endl
+cpp_int i = 1;
+i <<= 256;
+// Now print in hex format with prefix:
+std::cout << std::hex << std::showbase << i << std::endl;
+
+
  • + Interconversions between number types of the same family are allowed + and are implicit conversions if no loss of precision is involved, and + explicit if it is: +
+
int128_t     i128 = 0;
+int266_t     i256 = i128;  // OK implicit widening conversion
+i128_t            = i256;  // Error, no assignment operator found, narrowing conversion is explict
+i128_t            = static_cast<int128_t>(i256); // OK, explicit narrowing conversion
+
+mpz_int      z    = 0;
+mpf_float    f    = z;    // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit
+
+mpf_float_50 f50  = 2;
+f                 = f50;  // OK, conversion from fixed to variable precision, f will have 50 digits precision.
+f50               = f;    // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
+
+
  • + Some interconversions between number types are completely generic, and + are always available, albeit the conversions are always explicit: +
+
cpp_int cppi(2);
+// We can always convert between numbers of the same category - 
+// int to int, rational to rational, or float to float, so this is OK
+// as long as we use an explicit conversion:
+mpz_int z(cppi);
+// We can always promote from int to rational, int to float, or rational to float:
+cpp_rational     cppr(cppi);  // OK, int to rational
+cpp_dec_float_50 df(cppi);    // OK, int to float
+df                  = static_cast<cpp_dec_float_50>(cppr);  // OK, explicit rational to float conversion
+// However narrowing and/or implicit conversions always fail:
+cppi                =   df;    // Compiler error, conversion not allowed
+
+
  • + Other interconversions may be allowed as special cases, whenever the + backend allows it: +
+
mpf_t     m;           // Native GMP type.
+mpf_init_set_ui(m, 0); // set to a value;
+mpf_float i(m);        // copies the value of the native type.
+
+

+ More information on what additional types a backend supports conversions + from are given in the tutorial for each backend. The converting constructor + will be implict if the backend's converting constructor is also implicit, + and explicit if the backends converting constructor is also explicit. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats.html b/doc/html/boost_multiprecision/tut/floats.html new file mode 100644 index 00000000..bb8f542f --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats.html @@ -0,0 +1,199 @@ + + + +Floating Point Numbers + + + + + + + + +
+PrevUpHomeNext +
+
+ + +

+ The following back-ends provide floating point arithmetic: +

+
++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend Type +

+
+

+ Header +

+
+

+ Radix +

+
+

+ Dependencies +

+
+

+ Pros +

+
+

+ Cons +

+
+

+ 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. +

+
+

+ mpf_float<N> +

+
+

+ boost/multiprecision/gmp.hpp +

+
+

+ 2 +

+
+

+ GMP +

+
+

+ Very fast and efficient back-end. +

+
+

+ Dependency on GNU licensed GMP + library. +

+
+

+ 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. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html b/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html new file mode 100644 index 00000000..b671a7b9 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html @@ -0,0 +1,164 @@ + + + +cpp_dec_float + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/cpp_dec_float.hpp> +

+
namespace boost{ namespace multiprecision{
+
+template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void>
+class cpp_dec_float;
+
+typedef number<cpp_dec_float<50> > cpp_dec_float_50;
+typedef number<cpp_dec_float<100> > cpp_dec_float_100;
+
+}} // namespaces
+
+

+ The cpp_dec_float back-end + is used in conjunction with number: + It acts as an entirely C++ (header only and dependency free) floating-point + number type that is a drop-in replacement for the native C++ floating-point + types, but with much greater precision. +

+

+ Type cpp_dec_float can + be used at fixed precision by specifying a non-zero Digits10 + template parameter. The typedefs cpp_dec_float_50 + and cpp_dec_float_100 provide + arithmetic types at 50 and 100 decimal digits precision respectively. Optionally, + you can specify an integer type to use for the exponent, this defaults + to a 32-bit integer type which is more than large enough for the vast majority + of use cases, but larger types such as long + long can also be specified if you + need a truely huge exponent range. +

+

+ Normally cpp_dec_float + allocates no memory: all of the space required for its digits are allocated + directly within the class. As a result care should be taken not to use + the class with too high a digit count as stack space requirements can grow + out of control. If that represents a problem then providing an allocator + as the final template parameter causes cpp_dec_float + to dynamically allocate the memory it needs: this significantly reduces + the size of cpp_dec_float + and increases the viable upper limit on the number of digits at the expense + of performance. However, please bear in mind that arithmetic operations + rapidly become very expensive as the digit count grows: + the current implementation really isn't optimized or designed for large + digit counts. +

+

+ There is full standard library and numeric_limits + support available for this type. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed cpp_dec_floats + have a value of zero. +
  • +
  • + The radix of this type is 10. As a result it can behave subtly differently + from base-2 types. +
  • +
  • + The type has a number of internal guard digits over and above those + specified in the template argument. Normally these should not be visible + to the user. +
  • +
  • + The type supports both infinities and NaN's. An infinity is generated + whenever the result would overflow, and a NaN is generated for any + mathematically undefined operation. +
  • +
  • + There is a std::numeric_limits specialisation for + this type. +
  • +
  • + Any number instantiated + on this type, is convertible to any other number + instantiated on this type - for example you can convert from number<cpp_dec_float<50> > to number<cpp_dec_float<SomeOtherValue> >. + Narrowing conversions are truncating and explicit. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid floating + point number. +
  • +
  • + The actual precision of a cpp_dec_float + is always slightly higher than the number of digits specified in the + template parameter, actually how much higher is an implementation detail + but is always at least 8 decimal digits. +
  • +
  • + Operations involving cpp_dec_float + are always truncating. However, note that since their are guard digits + in effect, in practice this has no real impact on accuracy for most + use cases. +
  • +
+
+ + cpp_dec_float + example: +
+

+

+
#include <boost/multiprecision/cpp_dec_float.hpp>
+
+using namespace boost::multiprecision;
+
+// Operations at fixed precision and full numeric_limits support:
+cpp_dec_float_100 b = 2;
+std::cout << std::numeric_limits<cpp_dec_float_100>::digits << std::endl;
+// Note that digits10 is the same as digits, since we're base 10! :
+std::cout << std::numeric_limits<cpp_dec_float_100>::digits10 << std::endl;
+// We can use any C++ std lib function, lets print all the digits as well:
+std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10)
+   << log(b) << std::endl; // print log(2)
+// We can also use any function from Boost.Math:
+std::cout << boost::math::tgamma(b) << std::endl;
+// These even work when the argument is an expression template:
+std::cout << boost::math::tgamma(b * b) << std::endl;
+// And since we have an extended exponent range we can generate some really large 
+// numbers here (4.0238726007709377354370243e+2564):
+std::cout << boost::math::tgamma(cpp_dec_float_100(1000)) << std::endl;
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg.html b/doc/html/boost_multiprecision/tut/floats/fp_eg.html new file mode 100644 index 00000000..a2567273 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg.html @@ -0,0 +1,46 @@ + + + +Examples + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg/aos.html b/doc/html/boost_multiprecision/tut/floats/fp_eg/aos.html new file mode 100644 index 00000000..4a7b521e --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg/aos.html @@ -0,0 +1,118 @@ + + + +Area of Circle + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Generic numeric programming employs templates to use the same code for + different floating-point types and functions. Consider the area of a + circle a of radius r, given by +

+

+ a = π * r2 +

+

+ The area of a circle can be computed in generic programming using Boost.Math + for the constant π as shown below: +

+

+

+
#include <boost/math/constants/constants.hpp>
+
+template<typename T>
+inline T area_of_a_circle(T r)
+{
+   using boost::math::constants::pi;
+   return pi<T>() * r * r;
+}
+
+

+

+

+ It is possible to use area_of_a_circle() with built-in floating-point types + as well as floating-point types from Boost.Multiprecision. In particular, + consider a system with 4-byte single-precision float, 8-byte double-precision + double and also the cpp_dec_float_50 + data type from Boost.Multiprecision with 50 decimal digits of precision. +

+

+ We can compute and print the approximate area of a circle with radius + 123/100 for float, double and cpp_dec_float_50 + with the program below. +

+

+

+
#include <iostream>
+#include <iomanip>
+#include <boost/multiprecision/cpp_dec_float.hpp>
+
+using boost::multiprecision::cpp_dec_float_50;
+
+int main(int, char**)
+{
+   const float r_f(float(123) / 100);
+   const float a_f = area_of_a_circle(r_f);
+
+   const double r_d(double(123) / 100);
+   const double a_d = area_of_a_circle(r_d);
+
+   const cpp_dec_float_50 r_mp(cpp_dec_float_50(123) / 100);
+   const cpp_dec_float_50 a_mp = area_of_a_circle(r_mp);
+
+   // 4.75292
+   std::cout
+      << std::setprecision(std::numeric_limits<float>::digits10)
+      << a_f
+      << std::endl;
+
+   // 4.752915525616
+   std::cout
+      << std::setprecision(std::numeric_limits<double>::digits10)
+      << a_d
+      << std::endl;
+
+   // 4.7529155256159981904701331745635599135018975843146
+   std::cout
+      << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10)
+      << a_mp
+      << std::endl;
+}
+
+

+

+

+ In the next example we'll look at calling both standard library and Boost.Math + functions from within generic code. We'll also show how to cope with + template arguments which are expression-templates rather than number + types. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg/gi.html b/doc/html/boost_multiprecision/tut/floats/fp_eg/gi.html new file mode 100644 index 00000000..f5599b78 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg/gi.html @@ -0,0 +1,161 @@ + + + +Calculating an Integral + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Similar to the generic derivative example, we can calculate integrals + in a similar manner: +

+

+

+
template<typename value_type, typename function_type>
+inline value_type integral(const value_type a,
+                           const value_type b,
+                           const value_type tol,
+                           function_type func)
+{
+   unsigned n = 1U;
+
+   value_type h = (b - a);
+   value_type I = (func(a) + func(b)) * (h / 2);
+
+   for(unsigned k = 0U; k < 8U; k++)
+   {
+      h /= 2;
+
+      value_type sum(0);
+      for(unsigned j = 1U; j <= n; j++)
+      {
+         sum += func(a + (value_type((j * 2) - 1) * h));
+      }
+
+      const value_type I0 = I;
+      I = (I / 2) + (h * sum);
+
+      const value_type ratio     = I0 / I;
+      const value_type delta     = ratio - 1;
+      const value_type delta_abs = ((delta < 0) ? -delta : delta);
+
+      if((k > 1U) && (delta_abs < tol))
+      {
+         break;
+      }
+
+      n *= 2U;
+   }
+
+   return I;
+}
+
+

+

+

+ The following sample program shows how the function can be called, we + begin by defining a function object, which when integrated should yield + the Bessel J function: +

+

+

+
template<typename value_type>
+class cyl_bessel_j_integral_rep
+{
+public:
+   cyl_bessel_j_integral_rep(const unsigned N,
+      const value_type& X) : n(N), x(X) { }
+
+   value_type operator()(const value_type& t) const
+   {
+      // pi * Jn(x) = Int_0^pi [cos(x * sin(t) - n*t) dt]
+      return cos(x * sin(t) - (n * t));
+   }
+
+private:
+   const unsigned n;
+   const value_type x;
+};
+
+

+

+

+

+
   /* The function can now be called as follows: */
+int main(int, char**)
+{
+   using boost::math::constants::pi;
+   typedef boost::multiprecision::cpp_dec_float_50 mp_type;
+
+   const float j2_f =
+      integral(0.0F,
+      pi<float>(),
+      0.01F,
+      cyl_bessel_j_integral_rep<float>(2U, 1.23F)) / pi<float>();
+
+   const double j2_d =
+      integral(0.0,
+      pi<double>(),
+      0.0001,
+      cyl_bessel_j_integral_rep<double>(2U, 1.23)) / pi<double>();
+
+   const mp_type j2_mp =
+      integral(mp_type(0),
+      pi<mp_type>(),
+      mp_type(1.0E-20),
+      cyl_bessel_j_integral_rep<mp_type>(2U, mp_type(123) / 100)) / pi<mp_type>();
+
+   // 0.166369
+   std::cout
+      << std::setprecision(std::numeric_limits<float>::digits10)
+      << j2_f
+      << std::endl;
+
+   // 0.166369383786814
+   std::cout
+      << std::setprecision(std::numeric_limits<double>::digits10)
+      << j2_d
+      << std::endl;
+
+   // 0.16636938378681407351267852431513159437103348245333
+   std::cout
+      << std::setprecision(std::numeric_limits<mp_type>::digits10)
+      << j2_mp
+      << std::endl;
+
+   //
+   // Print true value for comparison:
+   // 0.166369383786814073512678524315131594371033482453329
+   std::cout << boost::math::cyl_bessel_j(2, mp_type(123) / 100) << std::endl;
+}
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg/jel.html b/doc/html/boost_multiprecision/tut/floats/fp_eg/jel.html new file mode 100644 index 00000000..fbece29c --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg/jel.html @@ -0,0 +1,222 @@ + + + +Defining a Lambda Function. + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ In this example we'll show several implementations of the Jahnke + and Emden Lambda function, each implementation a little more + sophisticated than the last. +

+

+ The Jahnke-Emden Lambda function is defined by the equation: +

+

+ JahnkeEmden(v, z) = Γ(v+1) * Jv(z) / (z / 2)v +

+

+ If we were to implement this at double precision using Boost.Math's facilities + for the Gamma and Bessel function calls it would look like this: +

+

+

+
double JEL1(double v, double z)
+{
+   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / std::pow(z / 2, v);
+}
+
+

+

+

+ Calling this function as: +

+
std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::digits10);
+std::cout << JEL1(2.5, 0.5) << std::endl;
+
+

+ Yields the output: +

+
9.822663964796047e-001
+

+ Now let's implement the function again, but this time using the multiprecision + type cpp_dec_float_50 + as the argument type: +

+

+

+
boost::multiprecision::cpp_dec_float_50
+   JEL2(boost::multiprecision::cpp_dec_float_50 v, boost::multiprecision::cpp_dec_float_50 z)
+{
+   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / boost::multiprecision::pow(z / 2, v);
+}
+
+

+

+

+ The implementation is almost the same as before, but with one key difference + - we can no longer call std::pow, + instead we must call the version inside the boost::multiprecision + namespace. In point of fact, we could have omitted the namespace prefix + on the call to pow since + the right overload would have been found via argument + dependent lookup in any case. +

+

+ Note also that the first argument to pow + along with the argument to tgamma + in the above code are actually expression templates. The pow and tgamma + functions will handle these arguments just fine. +

+

+ Here's an example of how the function may be called: +

+
std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10);
+std::cout << JEL2(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl;
+
+

+ Which outputs: +

+
9.82266396479604757017335009796882833995903762577173e-01
+

+ Now that we've seen some non-template examples, lets repeat the code + again, but this time as a template that can be called either with a builtin + type (float, double etc), or with a multiprecision + type: +

+

+

+
template <class Float>
+Float JEL3(Float v, Float z)
+{
+   using std::pow;
+   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v);
+}
+
+

+

+

+ Once again the code is almost the same as before, but the call to pow has changed yet again. We need + the call to resolve to either std::pow + (when the argument is a builtin type), or to boost::multiprecision::pow + (when the argument is a multiprecision type). We do that by making the + call unqualified so that versions of pow + defined in the same namespace as type Float + are found via argument dependent lookup, while the using + std::pow directive makes the standard library + versions visible for builtin floating point types. +

+

+ Let's call the function with both double + and multiprecision arguments: +

+
std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::digits10);
+std::cout << JEL3(2.5, 0.5) << std::endl;
+std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10);
+std::cout << JEL3(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl;
+
+

+ Which outputs: +

+
9.822663964796047e-001
+9.82266396479604757017335009796882833995903762577173e-01
+
+

+ Unfortunately there is a problem with this version: if we were to call + it like this: +

+
boost::multiprecision::cpp_dec_float_50 v(2), z(0.5);
+JEL3(v + 0.5, z);
+
+

+ Then we would get a long and inscrutable error message from the compiler: + the problem here is that the first argument to JEL3 + is not a number type, but an expression template. We could obviously + add a typecast to fix the issue: +

+
JEL(cpp_dec_float_50(v + 0.5), z);
+
+

+ However, if we want the function JEL to be truely reusable, then a better + solution might be preferred. To achieve this we can borrow some code + from Boost.Math which calculates the return type of mixed-argument functions, + here's how the new code looks now: +

+

+

+
template <class Float1, class Float2>
+typename boost::math::tools::promote_args<Float1, Float2>::type
+   JEL4(Float1 v, Float2 z)
+{
+   using std::pow;
+   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v);
+}
+
+

+

+

+ As you can see the two arguments to the function are now separate template + types, and the return type is computed using the promote_args + metafunction from Boost.Math. +

+

+ Now we can call: +

+
std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_100>::digits10);
+std::cout << JEL4(cpp_dec_float_100(2) + 0.5, cpp_dec_float_100(0.5)) << std::endl;
+
+

+ And get 100 digits of output: +

+
9.8226639647960475701733500979688283399590376257717309069410413822165082248153638454147004236848917775e-01
+

+ As a bonus, we can now call the function not just with expression templates, + but with other mixed types as well: for example float + and double or int and double, + and the correct return type will be computed in each case. +

+

+ Note that while in this case we didn't have to change the body of the + function, in the general case any function like this which creates local + variables internally would have to use promote_args + to work out what type those variables should be, for example: +

+
template <class Float1, class Float2>
+typename boost::math::tools::promote_args<Float1, Float2>::type
+   JEL5(Float1 v, Float2 z)
+{
+   using std::pow;
+   typedef typename boost::math::tools::promote_args<Float1, Float2>::type variable_type;
+   variable_type t = pow(z / 2, v);
+   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / t;
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg/nd.html b/doc/html/boost_multiprecision/tut/floats/fp_eg/nd.html new file mode 100644 index 00000000..75c6287d --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg/nd.html @@ -0,0 +1,202 @@ + + + +Calculating a Derivative + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ In this example we'll add even more power to generic numeric programming + using not only different floating-point types but also function objects + as template parameters. Consider some well-known central difference rules + for numerically computing the first derivative of a function f′(x) + with x ∈ ℜ: +

+

+ +

+

+ Where the difference terms mn are given by: +

+

+ +

+

+ and dx is the step-size of the derivative. +

+

+ The third formula in Equation 1 is a three-point central difference rule. + It calculates the first derivative of f′(x) to O(dx6), + where dx is the given step-size. For example, if + the step-size is 0.01 this derivative calculation has about 6 decimal + digits of precision - just about right for the 7 decimal digits of single-precision + float. Let's make a generic template subroutine using this three-point + central difference rule. In particular: +

+

+

+
template<typename value_type, typename function_type>
+   value_type derivative(const value_type x, const value_type dx, function_type func)
+{
+   // Compute d/dx[func(*first)] using a three-point
+   // central difference rule of O(dx^6).
+
+   const value_type dx1 = dx;
+   const value_type dx2 = dx1 * 2;
+   const value_type dx3 = dx1 * 3;
+
+   const value_type m1 = (func(x + dx1) - func(x - dx1)) / 2;
+   const value_type m2 = (func(x + dx2) - func(x - dx2)) / 4;
+   const value_type m3 = (func(x + dx3) - func(x - dx3)) / 6;
+
+   const value_type fifteen_m1 = 15 * m1;
+   const value_type six_m2     =  6 * m2;
+   const value_type ten_dx1    = 10 * dx1;
+
+   return ((fifteen_m1 - six_m2) + m3) / ten_dx1;
+}
+
+

+

+

+ The derivative() + template function can be used to compute the first derivative of any + function to O(dx6). For example, consider the first + derivative of sin(x) evaluated at x = + π/3. In other words, +

+

+ +

+

+ The code below computes the derivative in Equation 3 for float, double + and boost's multiple-precision type cpp_dec_float_50. +

+

+

+
#include <iostream>
+#include <iomanip>
+#include <boost/multiprecision/cpp_dec_float.hpp>
+#include <boost/math/constants/constants.hpp>
+
+
+int main(int, char**)
+{
+   using boost::math::constants::pi;
+   using boost::multiprecision::cpp_dec_float_50;
+   //
+   // We'll pass a function pointer for the function object passed to derivative,
+   // the typecast is needed to select the correct overload of std::sin:
+   //
+   const float d_f = derivative(
+      pi<float>() / 3,
+      0.01F,
+      static_cast<float(*)(float)>(std::sin)
+   );
+
+   const double d_d = derivative(
+      pi<double>() / 3,
+      0.001,
+      static_cast<double(*)(double)>(std::sin)
+      );
+   //
+   // In the cpp_dec_float_50 case, the sin function is multiply overloaded
+   // to handle expression templates etc.  As a result it's hard to take its
+   // address without knowing about its implementation details.  We'll use a 
+   // C++11 lambda expression to capture the call.
+   // We also need a typecast on the first argument so we don't accidently pass
+   // an expression template to a template function:
+   //
+   const cpp_dec_float_50 d_mp = derivative(
+      cpp_dec_float_50(pi<cpp_dec_float_50>() / 3),
+      cpp_dec_float_50(1.0E-9),
+      [](const cpp_dec_float_50& x) -> cpp_dec_float_50
+      {
+         return sin(x);
+      }
+      );
+
+   // 5.000029e-001
+   std::cout
+      << std::setprecision(std::numeric_limits<float>::digits10)
+      << d_f
+      << std::endl;
+
+   // 4.999999999998876e-001
+   std::cout
+      << std::setprecision(std::numeric_limits<double>::digits10)
+      << d_d
+      << std::endl;
+
+   // 4.99999999999999999999999999999999999999999999999999e-01
+   std::cout
+      << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10)
+      << d_mp
+      << std::endl;
+}
+
+

+

+

+ The expected value of the derivative is 0.5. This central difference + rule in this example is ill-conditioned, meaning it suffers from slight + loss of precision. With that in mind, the results agree with the expected + value of 0.5. +

+

+ We can take this a step further and use our derivative function to compute + a partial derivative. For example if we take the incomplete gamma function + P(a, z), and take the derivative with respect to + z at (2,2) then we can calculate + the result as shown below, for good measure we'll compare with the "correct" + result obtained from a call to gamma_p_derivative, + the results agree to approximately 44 digits: +

+

+

+
cpp_dec_float_50 gd = derivative(
+   cpp_dec_float_50(2),
+   cpp_dec_float_50(1.0E-9),
+   [](const cpp_dec_float_50& x) ->cpp_dec_float_50
+   {
+      return boost::math::gamma_p(2, x);
+   }
+);
+// 2.70670566473225383787998989944968806815263091819151e-01
+std::cout
+   << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10)
+   << gd
+   << std::endl;
+// 2.70670566473225383787998989944968806815253190143120e-01
+std::cout << boost::math::gamma_p_derivative(cpp_dec_float_50(2), cpp_dec_float_50(2)) << std::endl;
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/fp_eg/poly_eg.html b/doc/html/boost_multiprecision/tut/floats/fp_eg/poly_eg.html new file mode 100644 index 00000000..2a6884ec --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/fp_eg/poly_eg.html @@ -0,0 +1,147 @@ + + + +Polynomial Evaluation + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ In this example we'll look at polynomial evaluation, this is not only + an important use case, but it's one that number + performs particularly well at because the expression templates completely + eliminate all temporaries from a Horner + polynomial evaluation scheme. +

+

+ The following code evaluates sin(x) as a polynomial, accurate to at least + 64 decimal places: +

+

+

+
using boost::multiprecision::cpp_dec_float;
+typedef boost::multiprecision::number<cpp_dec_float<64> > mp_type;
+
+mp_type mysin(const mp_type& x)
+{
+  // Approximation of sin(x * pi/2) for -1 <= x <= 1, using an order 63 polynomial.
+  static const std::array<mp_type, 32U> coefs =
+  {{
+    mp_type("+1.5707963267948966192313216916397514420985846996875529104874722961539082031431044993140174126711"), //"),
+    mp_type("-0.64596409750624625365575656389794573337969351178927307696134454382929989411386887578263960484"), // ^3
+    mp_type("+0.07969262624616704512050554949047802252091164235106119545663865720995702920146198554317279"), // ^5
+    mp_type("-0.0046817541353186881006854639339534378594950280185010575749538605102665157913157426229824"), // ^7
+    mp_type("+0.00016044118478735982187266087016347332970280754062061156858775174056686380286868007443"), // ^9
+    mp_type("-3.598843235212085340458540018208389404888495232432127661083907575106196374913134E-6"), // ^11
+    mp_type("+5.692172921967926811775255303592184372902829756054598109818158853197797542565E-8"), // ^13
+    mp_type("-6.688035109811467232478226335783138689956270985704278659373558497256423498E-10"), // ^15
+    mp_type("+6.066935731106195667101445665327140070166203261129845646380005577490472E-12"), // ^17
+    mp_type("-4.377065467313742277184271313776319094862897030084226361576452003432E-14"), // ^19
+    mp_type("+2.571422892860473866153865950420487369167895373255729246889168337E-16"), // ^21
+    mp_type("-1.253899540535457665340073300390626396596970180355253776711660E-18"), // ^23
+    mp_type("+5.15645517658028233395375998562329055050964428219501277474E-21"), // ^25
+    mp_type("-1.812399312848887477410034071087545686586497030654642705E-23"), // ^27
+    mp_type("+5.50728578652238583570585513920522536675023562254864E-26"), // ^29
+    mp_type("-1.461148710664467988723468673933026649943084902958E-28"), // ^31
+    mp_type("+3.41405297003316172502972039913417222912445427E-31"), // ^33
+    mp_type("-7.07885550810745570069916712806856538290251E-34"), // ^35
+    mp_type("+1.31128947968267628970845439024155655665E-36"), // ^37
+    mp_type("-2.18318293181145698535113946654065918E-39"), // ^39
+    mp_type("+3.28462680978498856345937578502923E-42"), // ^41
+    mp_type("-4.48753699028101089490067137298E-45"), // ^43
+    mp_type("+5.59219884208696457859353716E-48"), // ^45
+    mp_type("-6.38214503973500471720565E-51"), // ^47
+    mp_type("+6.69528558381794452556E-54"), // ^49
+    mp_type("-6.47841373182350206E-57"), // ^51
+    mp_type("+5.800016389666445E-60"), // ^53
+    mp_type("-4.818507347289E-63"), // ^55
+    mp_type("+3.724683686E-66"), // ^57
+    mp_type("-2.6856479E-69"), // ^59
+    mp_type("+1.81046E-72"), // ^61
+    mp_type("-1.133E-75"), // ^63
+  }};
+
+  const mp_type v = x * 2 / boost::math::constants::pi<mp_type>();
+  const mp_type x2 = (v * v);
+  //
+  // Polynomial evaluation follows, if mp_type allocates memory then
+  // just one such allocation occurs - to initialize the variable "sum" -
+  // and no temporaries are created at all.
+  //
+  const mp_type sum = (((((((((((((((((((((((((((((((     + coefs[31U]
+                                                     * x2 + coefs[30U])
+                                                     * x2 + coefs[29U])
+                                                     * x2 + coefs[28U])
+                                                     * x2 + coefs[27U])
+                                                     * x2 + coefs[26U])
+                                                     * x2 + coefs[25U])
+                                                     * x2 + coefs[24U])
+                                                     * x2 + coefs[23U])
+                                                     * x2 + coefs[22U])
+                                                     * x2 + coefs[21U])
+                                                     * x2 + coefs[20U])
+                                                     * x2 + coefs[19U])
+                                                     * x2 + coefs[18U])
+                                                     * x2 + coefs[17U])
+                                                     * x2 + coefs[16U])
+                                                     * x2 + coefs[15U])
+                                                     * x2 + coefs[14U])
+                                                     * x2 + coefs[13U])
+                                                     * x2 + coefs[12U])
+                                                     * x2 + coefs[11U])
+                                                     * x2 + coefs[10U])
+                                                     * x2 + coefs[9U])
+                                                     * x2 + coefs[8U])
+                                                     * x2 + coefs[7U])
+                                                     * x2 + coefs[6U])
+                                                     * x2 + coefs[5U])
+                                                     * x2 + coefs[4U])
+                                                     * x2 + coefs[3U])
+                                                     * x2 + coefs[2U])
+                                                     * x2 + coefs[1U])
+                                                     * x2 + coefs[0U])
+                                                     * v;
+
+  return sum;
+}
+
+

+

+

+ Calling the function like so: +

+
mp_type pid4 = boost::math::constants::pi<mp_type>() / 4;
+std::cout << std::setprecision(std::numeric_limits< ::mp_type>::digits10) << std::scientific;
+std::cout << mysin(pid4) << std::endl;
+
+

+ Yields the expected output: +

+
7.0710678118654752440084436210484903928483593768847403658833986900e-01
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/gmp_float.html b/doc/html/boost_multiprecision/tut/floats/gmp_float.html new file mode 100644 index 00000000..566ffc47 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/gmp_float.html @@ -0,0 +1,183 @@ + + + +gmp_float + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/gmp.hpp> +

+
namespace boost{ namespace multiprecision{
+
+template <unsigned Digits10>
+class gmp_float;
+
+typedef number<gmp_float<50> >    mpf_float_50;
+typedef number<gmp_float<100> >   mpf_float_100;
+typedef number<gmp_float<500> >   mpf_float_500;
+typedef number<gmp_float<1000> >  mpf_float_1000;
+typedef number<gmp_float<0> >     mpf_float;
+
+}} // namespaces
+
+

+ The gmp_float back-end + is used in conjunction with number + : it acts as a thin wrapper around the GMP + mpf_t to provide an real-number + type that is a drop-in replacement for the native C++ floating-point types, + but with much greater precision. +

+

+ Type gmp_float can be used + at fixed precision by specifying a non-zero Digits10 + template parameter, or at variable precision by setting the template argument + to zero. The typedefs mpf_float_50, mpf_float_100, mpf_float_500, mpf_float_1000 + provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision + respectively. The typedef mpf_float provides a variable precision type + whose precision can be controlled via the numbers + member functions. +

+
+ + + + + +
[Note]Note

+ This type only provides standard library and numeric_limits + support when the precision is fixed at compile time. +

+

+ As well as the usual conversions from arithmetic and string types, instances + of number<mpf_float<N> > are copy constructible and assignable + from: +

+
    +
  • + The GMP native types mpf_t, mpz_t, + mpq_t. +
  • +
  • + The number wrappers + around those types: number<mpf_float<M> >, + number<gmp_int>, + number<gmp_rational>. +
  • +
+

+ It's also possible to access the underlying mpf_t + via the data() + member function of gmp_float. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed gmp_floats + have the value zero (this is the GMP + library's default behavior). +
  • +
  • + No changes are made to the GMP + library's global settings, so this type can be safely mixed with existing + GMP code. +
  • +
  • + This backend supports rvalue-references and is move-aware, making instantiations + of number on this backend + move aware. +
  • +
  • + It is not possible to round-trip objects of this type to and from a + string and get back exactly the same value. This appears to be a limitation + of GMP. +
  • +
  • + Since the underlying GMP types + have no notion of infinities or NaN's, care should be taken to avoid + numeric overflow or division by zero. That latter will result in a + std::overflow_error being thrown, while generating excessively large + exponents may result in instability of the underlying GMP + library (in testing, converting a number with an excessively large + or small exponent to a string caused GMP + to segfault). +
  • +
  • + This type can equally be used with MPIR + as the underlying implementation - indeed that is the recommended option + on Win32. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid floating + point number. +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
+
+ + + GMP example: +
+

+

+
#include <boost/multiprecision/gmp.hpp>
+
+using namespace boost::multiprecision;
+
+// Operations at variable precision and limited standard library support:
+mpf_float a = 2;
+mpf_float::default_precision(1000);
+std::cout << mpf_float::default_precision() << std::endl;
+std::cout << sqrt(a) << std::endl; // print root-2
+
+// Operations at fixed precision and full standard library support:
+mpf_float_100 b = 2;
+std::cout << std::numeric_limits<mpf_float_100>::digits << std::endl;
+// We can use any C++ std lib function:
+std::cout << log(b) << std::endl; // print log(2)
+// We can also use any function from Boost.Math:
+std::cout << boost::math::tgamma(b) << std::endl;
+// These even work when the argument is an expression template:
+std::cout << boost::math::tgamma(b * b) << std::endl;
+
+// Access the underlying representation:
+mpf_t f;
+mpf_init(f);
+mpf_set(f, a.backend().data());
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/floats/mpfr_float.html b/doc/html/boost_multiprecision/tut/floats/mpfr_float.html new file mode 100644 index 00000000..2bee41f5 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/floats/mpfr_float.html @@ -0,0 +1,272 @@ + + + +mpfr_float + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/mpfr_float.hpp> +

+
namespace boost{ namespace multiprecision{
+
+enum mpfr_allocation_type
+{
+   allocate_stack,
+   allocate_dynamic
+};
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType = allocate_dynamic>
+class mpfr_float_backend;
+
+typedef number<mpfr_float_backend<50> >    mpfr_float_50;
+typedef number<mpfr_float_backend<100> >   mpfr_float_100;
+typedef number<mpfr_float_backend<500> >   mpfr_float_500;
+typedef number<mpfr_float_backend<1000> >  mpfr_float_1000;
+typedef number<mpfr_float_backend<0> >     mpfr_float;
+
+typedef number<mpfr_float_backend<50, allocate_stack> >    static_mpfr_float_50;
+typedef number<mpfr_float_backend<100, allocate_stack> >   static_mpfr_float_100;
+
+}} // namespaces
+
+

+ The mpfr_float_backend + type is used in conjunction with number: + It acts as a thin wrapper around the MPFR + mpfr_t to provide an real-number + type that is a drop-in replacement for the native C++ floating-point types, + but with much greater precision. +

+

+ Type mpfr_float_backend + can be used at fixed precision by specifying a non-zero Digits10 + template parameter, or at variable precision by setting the template argument + to zero. The typedefs mpfr_float_50, mpfr_float_100, mpfr_float_500, mpfr_float_1000 + provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision + respectively. The typedef mpfr_float provides a variable precision type + whose precision can be controlled via the numbers + member functions. +

+

+ In addition the second template parameter lets you choose between dynamic + allocation (the default, and uses MPFR's normal allocation routines), or + stack allocation (where all the memory required for the underlying data + types is stored within mpfr_float_backend). + The latter option can result in significantly faster code, at the expense + of growing the size of mpfr_float_backend. + It can only be used at fixed precision, and should only be used for lower + digit counts. Note that we can not guarentee that using allocate_stack + won't cause any calls to mpfr's allocation routines, as mpfr may call these + inside it's own code. The following table gives an idea of the performance + tradeoff's at 50 decimal digits precision[2]: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + +
+

+ Type +

+
+

+ Bessel function evaluation, relative times +

+
+

+ number<mpfr_float_backend<50, allocate_static>, + et_on> +

+
+

+ 1.0 (5.5s) +

+
+

+ number<mpfr_float_backend<50, allocate_static>, + et_off> +

+
+

+ 1.05 (5.8s) +

+
+

+ number<mpfr_float_backend<50, allocate_dynamic>, + et_on> +

+
+

+ 1.05 (5.8s) +

+
+

+ number<mpfr_float_backend<50, allocate_dynamic>, + et_off> +

+
+

+ 1.16 (6.4s) +

+
+
+ + + + + +
[Note]Note

+ This type only provides numeric_limits + support when the precision is fixed at compile time. +

+

+ As well as the usual conversions from arithmetic and string types, instances + of number<mpfr_float_backend<N> > are copy constructible and assignable + from: +

+
    +
  • + The GMP native types mpf_t, mpz_t, + mpq_t. +
  • +
  • + The MPFR native type mpfr_t. +
  • +
  • + The number wrappers + around those types: number<mpfr_float_backend<M> >, + number<mpf_float<M> >, number<gmp_int>, number<gmp_rational>. +
  • +
+

+ It's also possible to access the underlying mpf_t + via the data() member function of gmp_float. +

+

+ Things you should know when using this type: +

+
    +
  • + A default constructed mpfr_float_backend + is set to a NaN (this is the default MPFR + behavior). +
  • +
  • + All operations use round to nearest. +
  • +
  • + No changes are made to GMP or + MPFR global settings, so this + type can coexist with existing MPFR + or GMP code. +
  • +
  • + The code can equally use MPIR + in place of GMP - indeed that + is the preferred option on Win32. +
  • +
  • + This backend supports rvalue-references and is move-aware, making instantiations + of number on this backend + move aware. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid floating + point number. +
  • +
  • + Division by zero results in an infinity. +
  • +
+
+ + + MPFR example: +
+

+

+
#include <boost/multiprecision/mpfr.hpp>
+
+using namespace boost::multiprecision;
+
+// Operations at variable precision and no numeric_limits support:
+mpfr_float a = 2;
+mpfr_float::default_precision(1000);
+std::cout << mpfr_float::default_precision() << std::endl;
+std::cout << sqrt(a) << std::endl; // print root-2
+
+// Operations at fixed precision and full numeric_limits support:
+mpfr_float_100 b = 2;
+std::cout << std::numeric_limits<mpfr_float_100>::digits << std::endl;
+// We can use any C++ std lib function:
+std::cout << log(b) << std::endl; // print log(2)
+// We can also use any function from Boost.Math:
+std::cout << boost::math::tgamma(b) << std::endl;
+// These even work when the argument is an expression template:
+std::cout << boost::math::tgamma(b * b) << std::endl;
+
+// Access the underlying data:
+mpfr_t r;
+mpfr_init(r);
+mpfr_set(r, b.backend().data(), GMP_RNDN);
+
+

+

+
+

+

[2] + Compiled with VC++10 and /Ox, with MPFR-3.0.0 and MPIR-2.3.0 +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints.html b/doc/html/boost_multiprecision/tut/ints.html new file mode 100644 index 00000000..2494b3ac --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints.html @@ -0,0 +1,191 @@ + + + +Integer Types + + + + + + + + +
+PrevUpHomeNext +
+
+ + +

+ The following back-ends provide integer arithmetic: +

+
++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend Type +

+
+

+ Header +

+
+

+ Radix +

+
+

+ Dependencies +

+
+

+ Pros +

+
+

+ Cons +

+
+

+ cpp_int +

+
+

+ boost/multiprecision/cpp_int.hpp +

+
+

+ 2 +

+
+

+ None +

+
+

+ Very versatile, Boost licensed, all C++ integer type which support + both arbitrary + precision and fixed precision integer types. +

+
+

+ Slower than GMP, though + typically not as slow as libtommath +

+
+

+ gmp_int +

+
+

+ boost/multiprecision/gmp.hpp +

+
+

+ 2 +

+
+

+ GMP +

+
+

+ Very fast and efficient back-end. +

+
+

+ Dependency on GNU licensed GMP + library. +

+
+

+ tom_int +

+
+

+ boost/multiprecision/tommath.hpp +

+
+

+ 2 +

+
+

+ libtommath +

+
+

+ Public domain back-end with no licence restrictions. +

+
+

+ Slower than GMP. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/cpp_int.html b/doc/html/boost_multiprecision/tut/ints/cpp_int.html new file mode 100644 index 00000000..68c0d7be --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/cpp_int.html @@ -0,0 +1,366 @@ + + + +cpp_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/cpp_int.hpp> +

+
namespace boost{ namespace multiprecision{
+
+typedef unspecified-type limb_type;
+
+enum cpp_integer_type    { signed_magnitude, unsigned_magnitude };
+enum cpp_int_check_type  { checked, unchecked };
+
+template <unsigned MinDigits = 0,
+          unsigned MaxDits = 0,
+          cpp_integer_type SignType = signed_magnitude,
+          cpp_int_check_type Checked = unchecked,
+          class Allocator = std::allocator<limb_type> >
+class cpp_int_backend;
+//
+// Expression templates default to et_off if there is no allocator:
+//
+template <unsigned MinDigits, unsigned MaxDigits, cpp_integer_type SignType, cpp_int_check_type Checked>
+struct expression_template_default<cpp_int_backend<MinDigits, MaxDigits, SignType, Checked, void> >
+{ static const expression_template_option value = et_off; };
+
+typedef number<cpp_int_backend<> >              cpp_int;    // arbitrary precision integer
+typedef rational_adapter<cpp_int_backend<> >    cpp_rational_backend;
+typedef number<cpp_rational_backend>            cpp_rational; // arbitrary precision rational number
+
+// Fixed precision unsigned types:
+typedef number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >   uint128_t;
+typedef number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >   uint256_t;
+typedef number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >   uint512_t;
+typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> > uint1024_t;
+
+// Fixed precision signed types:
+typedef number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >     int128_t;
+typedef number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >     int256_t;
+typedef number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >     int512_t;
+typedef number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >   int1024_t;
+
+// Over again, but with checking enabled this time:
+typedef number<cpp_int_backend<0, 0, signed_magnitude, checked> >                 checked_cpp_int;
+typedef rational_adapter<cpp_int_backend<0, 0, signed_magnitude, checked> >       checked_cpp_rational_backend;
+typedef number<cpp_rational_backend>                                              checked_cpp_rational;
+
+// Checked fixed precision unsigned types:
+typedef number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >     checked_uint128_t;
+typedef number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >     checked_uint256_t;
+typedef number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >     checked_uint512_t;
+typedef number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> >   checked_uint1024_t;
+
+// Fixed precision signed types:
+typedef number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >       checked_int128_t;
+typedef number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >       checked_int256_t;
+typedef number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >       checked_int512_t;
+typedef number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >     checked_int1024_t;
+
+}} // namespaces
+
+

+ The cpp_int_backend type + is normally used via one of the convenience typedefs given above. +

+

+ This back-end is the "Swiss Army Knife" of integer types as it + can represent both fixed and arbitrary + precision integer types, and both signed and unsigned types. There + are five template arguments: +

+
+

+
+
MinBits
+

+ Determines the number of Bits to store directly within the object + before resorting to dynamic memory allocation. When zero, this field + is determined automatically based on how many bits can be stored + in union with the dynamic storage header: setting a larger value + may improve performance as larger integer values will be stored internally + before memory allocation is required. +

+
MaxBits
+

+ Determines the maximum number of bits to be stored in the type: resulting + in a fixed precision type. When this value is the same as MinBits, + then the Allocator parameter is ignored, as no dynamic memory allocation + will ever be performed: in this situation the Allocator parameter + should be set to type void. + Note that this parameter should not be used simply to prevent large + memory allocations, not only is that role better performed by the + allocator, but fixed precision integers have a tendency to allocate + all of MaxBits of storage more often than one would expect. +

+
SignType
+

+ Determines whether the resulting type is signed or not. Note that + for arbitrary + precision types this parameter must be signed_magnitude. + For fixed precision types then this type may be either signed_magnitude or unsigned_magnitude. +

+
Checked
+

+ This parameter has two values: checked + or unchecked. See + below. +

+
Allocator
+

+ The allocator to use for dynamic memory allocation, or type void if MaxBits == MinBits. +

+
+
+

+ When the template parameter Checked is set to checked + then the result is a checked-integer, checked and + unchecked integers have the following properties: +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Condition +

+
+

+ Checked-Integer +

+
+

+ Unchecked-Integer +

+
+

+ Numeric overflow in fixed precision arithmetic +

+
+

+ Throws a std::overflow_error. +

+
+

+ Performs arithmetic modulo 2MaxBits +

+
+

+ Constructing an integer from a value that can not be represented + in the target type +

+
+

+ Throws a std::range_error. +

+
+

+ Converts the value modulo 2MaxBits, signed to unsigned conversions + extract the last MaxBits bits of the 2's complement representation + of the input value. +

+
+

+ Unsigned subtraction yielding a negative value. +

+
+

+ Throws a std::range_error. +

+
+

+ Yields the value that would result from treating the unsigned + type as a 2's complement signed type. +

+
+

+ Attempting a bitwise operation on a negative value. +

+
+

+ Throws a std::range_error +

+
+

+ Yields the value, but not the bit pattern, that would result + from performing the operation on a 2's complement integer type. +

+
+

+ Things you should know when using this type: +

+
    +
  • + Default constructed cpp_int_backends + have the value zero. +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
  • + Construction from a string that contains invalid non-numeric characters + results in a std::runtime_error being thrown. +
  • +
  • + Since the precision of cpp_int_backend + is necessarily limited when the allocator parameter is void, care should + be taken to avoid numeric overflow when using this type unless you + actually want modulo-arithmetic behavior. +
  • +
  • + The type uses a sign-magnitude representation internally, so type + int128_t has 128-bits + of precision plus an extra sign bit. In this respect the behaviour + of these types differs from built-in 2's complement types. In might + be tempting to use a 127-bit type instead, and indeed this does work, + but behaviour is still slightly different from a 2's complement built-in + type as the min and max values are identical (apart from the sign), + where as they differ by one for a true 2's complement type. That said + it should be noted that there's no requirement for built-in types to + be 2's complement either - it's simply that this is the most common + format by far. +
  • +
  • + Attempting to print negative values as either an Octal or Hexadecimal + string results in a std::runtime_error + being thrown, this is a direct consequence of the sign-magnitude representation. +
  • +
  • + The fixed precision types [checked_][u]intXXX_t have expression template + support turned off - it seems to make little difference to the performance + of these types either way - so we may as well have the faster compile + times by turning the feature off. +
  • +
  • + Unsigned types support subtraction - the result is "as if" + a 2's complement operation had been performed as long as they are not + checked-integers (see above). In other words they + behave pretty much as a built in integer type would in this situation. + So for example if we were using uint128_t + then uint128_t(1)-4 + would result in the value 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD + of type uint128_t. + However, had this operation been performed on checked_uint128_t + then a std::range_error would have been thrown. +
  • +
  • + Unary negation of unsigned types results in a compiler error (static + assertion). +
  • +
  • + This backend supports rvalue-references and is move-aware, making instantiations + of number on this backend + move aware. +
  • +
  • + When used at fixed precision, the size of this type is always one machine + word larger than you would expect for an N-bit integer: the extra word + stores both the sign, and how many machine words in the integer are + actually in use. The latter is an optimisation for larger fixed precision + integers, so that a 1024-bit integer has almost the same performance + characterists as a 128-bit integer, rather than being 4 times slower + for addition and 16 times slower for multiplication (assuming the values + involved would always fit in 128 bits). Typically this means you can + use an integer type wide enough for the "worst case senario" + with only minor performance degradation even if most of the time the + arithmetic could in fact be done with a narrower type. +
  • +
  • + When used at fixed precision and MaxBits is smaller than the number + of bits in the largest native integer type, then internally cpp_int_backend switches to a "trivial" + implementation where it is just a thin wrapper around a single integer. + Note that it will still be slightly slower than a bare native integer, + as it emulates a signed-magnitude representation rather than simply + using the platforms native sign representation: this ensures there + is no step change in behavior as a cpp_int grows in size. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/cpp_int.hpp>
+
+using namespace boost::multiprecision;
+
+int128_t v = 1;
+
+// Do some fixed precision arithmetic:
+for(unsigned i = 1; i <= 20; ++i)
+   v *= i;
+
+std::cout << v << std::endl; // prints 20!
+
+// Repeat at arbitrary precision:
+cpp_int u = 1;
+for(unsigned i = 1; i <= 100; ++i)
+   u *= i;
+
+std::cout << u << std::endl; // prints 100!
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/egs.html b/doc/html/boost_multiprecision/tut/ints/egs.html new file mode 100644 index 00000000..bc357417 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/egs.html @@ -0,0 +1,38 @@ + + + +Examples + + + + + + + + +
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/egs/bitops.html b/doc/html/boost_multiprecision/tut/ints/egs/bitops.html new file mode 100644 index 00000000..9b061f26 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/egs/bitops.html @@ -0,0 +1,94 @@ + + + +Bit Operations + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ In this example we'll show how individual bits within an integer may + be manipulated, we'll start with an often needed calculation of 2n - + 1, which we could obviously implement like this: +

+

+

+
using boost::multiprecision::cpp_int;
+
+cpp_int b1(unsigned n)
+{
+   cpp_int r(1);
+   return (r << n) - 1;
+}
+
+

+

+

+ Calling: +

+
std::cout << std::hex << std::showbase << b1(200) << std::endl;
+
+

+ Yields as expected: +

+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+

+ However, we could equally just set the n'th bit in the result, like this: +

+

+

+
cpp_int b2(unsigned n)
+{
+   cpp_int r(0);
+   return --bit_set(r, n);
+}
+
+

+

+

+ Note how the bit_set + function sets the specified bit in its argument and then returns a reference + to the result - which we can then simply decrement. The result from a + call to b2 is the same + as that to b1. +

+

+ We can equally test bits, so for example the n'th bit of the result returned + from b2 shouldn't be + set unless we increment it first: +

+
assert(!bit_test(b1(200), 200));     // OK
+assert(bit_test(++b1(200), 200));    // OK
+
+

+ And of course if we flip the n'th bit after increment, then we should + get back to zero: +

+
assert(!bit_flip(++b1(200), 200));   // OK
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/egs/factorials.html b/doc/html/boost_multiprecision/tut/ints/egs/factorials.html new file mode 100644 index 00000000..76a984f4 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/egs/factorials.html @@ -0,0 +1,145 @@ + + + +Factorials + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ In this simple example, we'll write a routine to print out all of the + factorials which will fit into a 128-bit integer. At the end of the routine + we do some fancy iostream formatting of the results: +

+

+

+
#include <boost/multiprecision/cpp_int.hpp>
+#include <iostream>
+#include <iomanip>
+#include <vector>
+
+
+void print_factorials()
+{
+   using boost::multiprecision::cpp_int;
+   //
+   // Print all the factorials that will fit inside a 128-bit integer.
+   //
+   // Begin by building a big table of factorials, once we know just how 
+   // large the largest is, we'll be able to "pretty format" the results.
+   //
+   // Calculate the largest number that will fit inside 128 bits, we could
+   // also have used numeric_limits<int128_t>::max() for this value:
+   cpp_int limit = (cpp_int(1) << 128) - 1;
+   // 
+   // Our table of values:
+   std::vector<cpp_int> results;
+   //
+   // Initial values:
+   unsigned i = 1;
+   cpp_int factorial = 1;
+   //
+   // Cycle through the factorials till we reach the limit:
+   while(factorial < limit)
+   {
+      results.push_back(factorial);
+      ++i;
+      factorial *= i;
+   }
+   //
+   // Lets see how many digits the largest factorial was:
+   unsigned digits = results.back().str().size();
+   //
+   // Now print them out, using right justification, while we're at it
+   // we'll indicate the limit of each integer type, so begin by defining
+   // the limits for 16, 32, 64 etc bit integers:
+   cpp_int limits[] = {
+      (cpp_int(1) << 16) - 1,
+      (cpp_int(1) << 32) - 1,
+      (cpp_int(1) << 64) - 1,
+      (cpp_int(1) << 128) - 1,
+   };
+   std::string bit_counts[] = { "16", "32", "64", "128" };
+   unsigned current_limit = 0;
+   for(unsigned j = 0; j < results.size(); ++j)
+   {
+      if(limits[current_limit] < results[j])
+      {
+         std::string message = "Limit of " + bit_counts[current_limit] + " bit integers";
+         std::cout << std::setfill('.') << std::setw(digits+1) << std::right << message << std::setfill(' ') << std::endl;
+         ++current_limit;
+      }
+      std::cout << std::setw(digits + 1) << std::right << results[j] << std::endl;
+   }
+}
+
+

+

+

+ The output from this routine is: +

+
+                                       1
+                                       2
+                                       6
+                                      24
+                                     120
+                                     720
+                                    5040
+                                   40320
+................Limit of 16 bit integers
+                                  362880
+                                 3628800
+                                39916800
+                               479001600
+................Limit of 32 bit integers
+                              6227020800
+                             87178291200
+                           1307674368000
+                          20922789888000
+                         355687428096000
+                        6402373705728000
+                      121645100408832000
+                     2432902008176640000
+................Limit of 64 bit integers
+                    51090942171709440000
+                  1124000727777607680000
+                 25852016738884976640000
+                620448401733239439360000
+              15511210043330985984000000
+             403291461126605635584000000
+           10888869450418352160768000000
+          304888344611713860501504000000
+         8841761993739701954543616000000
+       265252859812191058636308480000000
+      8222838654177922817725562880000000
+    263130836933693530167218012160000000
+   8683317618811886495518194401280000000
+ 295232799039604140847618609643520000000
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/gmp_int.html b/doc/html/boost_multiprecision/tut/ints/gmp_int.html new file mode 100644 index 00000000..385392f9 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/gmp_int.html @@ -0,0 +1,137 @@ + + + +gmp_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/gmp.hpp> +

+
namespace boost{ namespace multiprecision{
+
+class gmp_int;
+
+typedef number<gmp_int >         mpz_int;
+
+}} // namespaces
+
+

+ The gmp_int back-end is + used via the typedef boost::multiprecision::mpz_int. + It acts as a thin wrapper around the GMP + mpz_t to provide an integer + type that is a drop-in replacement for the native C++ integer types, but + with unlimited precision. +

+

+ As well as the usual conversions from arithmetic and string types, type + mpz_int is copy constructible + and assignable from: +

+
    +
  • + The GMP native types: mpf_t, mpz_t, + mpq_t. +
  • +
  • + Instances of number<T> that are wrappers around those + types: number<gmp_float<N> >, number<gmp_rational>. +
  • +
+

+ It's also possible to access the underlying mpz_t + via the data() + member function of gmp_int. +

+

+ Things you should know when using this type: +

+
    +
  • + No changes are made to the GMP library's global settings - so you can + safely mix this type with existing code that uses GMP. +
  • +
  • + Default constructed gmp_ints + have the value zero (this is GMP's default behavior). +
  • +
  • + Formatted IO for this type does not support octal or hexadecimal notation + for negative values, as a result performing formatted output on this + type when the argument is negative and either of the flags std::ios_base::oct or std::ios_base::hex + are set, will result in a std::runtime_error + will be thrown. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid integer. +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
  • + Although this type is a wrapper around GMP + it will work equally well with MPIR. + Indeed use of MPIR is recommended + on Win32. +
  • +
  • + This backend supports rvalue-references and is move-aware, making instantiations + of number on this backend + move aware. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/gmp.hpp>
+
+using namespace boost::multiprecision;
+
+mpz_int v = 1;
+
+// Do some arithmetic:
+for(unsigned i = 1; i <= 1000; ++i)
+   v *= i;
+
+std::cout << v << std::endl; // prints 1000!
+
+// Access the underlying representation:
+mpz_t z;
+mpz_init(z);
+mpz_set(z, v.backend().data());
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/ints/tom_int.html b/doc/html/boost_multiprecision/tut/ints/tom_int.html new file mode 100644 index 00000000..62e8c343 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/ints/tom_int.html @@ -0,0 +1,123 @@ + + + +tom_int + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/tommath.hpp> +

+
namespace boost{ namespace multiprecision{
+
+class tommath_int;
+
+typedef number<tommath_int >         tom_int;
+
+}} // namespaces
+
+

+ The tommath_int back-end + is used via the typedef boost::multiprecision::tom_int. + It acts as a thin wrapper around the libtommath + tom_int to provide an integer + type that is a drop-in replacement for the native C++ integer types, but + with unlimited precision. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed objects have the value zero (this is libtommath's + default behavior). +
  • +
  • + Although tom_int is + mostly a drop in replacement for the builtin integer types, it should + be noted that it is a rather strange beast as it's a signed type that + is not a 2's complement type. As a result the bitwise operations | & ^ will throw a std::runtime_error + exception if either of the arguments is negative. Similarly the complement + operator~ is deliberately + not implemented for this type. +
  • +
  • + Formatted IO for this type does not support octal or hexadecimal notation + for negative values, as a result performing formatted output on this + type when the argument is negative and either of the flags std::ios_base::oct or std::ios_base::hex + are set, will result in a std::runtime_error + will be thrown. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid integer. +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/tommath.hpp>
+
+boost::multiprecision::tom_int v = 1;
+
+// Do some arithmetic:
+for(unsigned i = 1; i <= 1000; ++i)
+   v *= i;
+
+std::cout << v << std::endl; // prints 1000!
+std::cout << std::hex << v << std::endl; // prints 1000! in hex format
+
+try{
+   std::cout << std::hex << -v << std::endl; // Ooops! can't print a negative value in hex format!
+}
+catch(const std::runtime_error& e)
+{
+   std::cout << e.what() << std::endl;
+}
+
+try{
+   // v is not a 2's complement type, bitwise operations are only supported
+   // on positive values:
+   v = -v & 2;
+}
+catch(const std::runtime_error& e)
+{
+   std::cout << e.what() << std::endl;
+}
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/lits.html b/doc/html/boost_multiprecision/tut/lits.html new file mode 100644 index 00000000..b64f2793 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/lits.html @@ -0,0 +1,63 @@ + + + +Literal Types and constexpr Support + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ There is limited support for constexpr + in the library, currently the number + front end supports constexpr + on default construction and all forwarding constructors, but not on any of + the non-member operators. So if some type B + is a literal type, then number<B> + is also a literal type, and you will be able to compile-time-construct such + a type from any literal that B + is compile-time-constructible from. However, you will not be able to perform + compile-time arithmetic on such types. +

+

+ Currently the only backend type provided by the library that is also a literal + type are instantiations of cpp_int_backend + where the Allocator parameter is type void, + and the Checked parameter is boost::multiprecision::unchecked. +

+

+ For example: +

+
using namespace boost::multiprecision;
+
+constexpr int128_t            i = 0;     // OK, fixed precision int128_t has no allocator.
+constexpr uint1024_t          j = 0xFFFFFFFF00000000uLL;  // OK, fixed precision uint1024_t has no allocator.
+
+constexpr checked_uint128_t   k = -1; // Error, checked type is not a literal type as we need runtime error checking.
+constexpr cpp_int             l = 2;  // Error, type is not a literal as it performs memory management.
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/mixed.html b/doc/html/boost_multiprecision/tut/mixed.html new file mode 100644 index 00000000..8b609e43 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/mixed.html @@ -0,0 +1,169 @@ + + + +Mixed Precision Arithmetic + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Mixed precision arithmetic is fully supported by the library, there are two + different forms: +

+
    +
  • + Where the operands are of different precision. +
  • +
  • + Where the operands are of the same precision, but yield a higher precision + result. +
  • +
+
+ + Mixing + Operands of Differing Precision +
+

+ If the arguments to a binary operator are of different precision, then the + operation is allowed as long as there is an unambiguous implicit conversion + from one argument type to the other. In all cases the arithmetic is performed + "as if" the lower precision type is promoted to the higher precision + type before applying the operator. However, particular backends may optimise + this and avoid actually creating a temporary if they are able to do so. +

+

+ For example: +

+
mpfr_float_50         a(2), b;
+mpfr_float_100        c(3), d;
+static_mpfr_float_50  e(5), f;
+mpz_int               i(20);
+
+d = a * c;  // OK, result of operand is an mpfr_float_100.
+b = a * c;  // Error, can't convert the result to an mpfr_float_50 as it will lose digits.
+f = a * e;  // Error, operator is ambiguous, result could be of either type.
+f = e * i;  // OK, unambiguous conversion from mpz_int to static_mpfr_float_50
+
+
+ + Operands + of the Same Precision +
+

+ Sometimes you want to apply an operator to two arguments of the same precision + in such a way as to obtain a result of higher precision. The most common + situation occurs with fixed precision integers, where you want to multiply + two N-bit numbers to obtain a 2N-bit result. This is supported in this library + by the following free functions: +

+
template <class ResultType, class Source1 class Source2>
+ResultType& add(ResultType& result, const Source1& a, const Source2& b);
+
+template <class ResultType, class Source1 class Source2>
+ResultType& subtract(ResultType& result, const Source1& a, const Source2& b);
+
+template <class ResultType, class Source1 class Source2>
+ResultType& multiply(ResultType& result, const Source1& a, const Source2& b);
+
+

+ These functions apply the named operator to the arguments a + and b and store the result in result, + returning result. In all cases they behave "as + if" arguments a and b were + first promoted to type ResultType + before applying the operator, though particular backends may well avoid that + step by way of an optimization. +

+

+ The type ResultType must + be an instance of class number, + and the types Source1 and + Source2 may be either instances + of class number or native + integer types. The latter is an optimization that allows arithmetic to be + performed on native integer types producing an extended precision result. +

+

+ For example: +

+

+

+
#include <boost/multiprecision/cpp_int.hpp>
+
+using namespace boost::multiprecision;
+
+boost::uint64_t i = (std::numeric_limits<boost::uint64_t>::max)();
+boost::uint64_t j = 1;
+
+uint128_t ui128;
+uint256_t ui256;
+//
+// Start by performing arithmetic on 64-bit integers to yield 128-bit results:
+//
+std::cout << std::hex << std::showbase << i << std::endl;
+std::cout << std::hex << std::showbase << add(ui128, i, j) << std::endl;
+std::cout << std::hex << std::showbase << multiply(ui128, i, i) << std::endl;
+//
+// The try squaring a 128-bit integer to yield a 256-bit result:
+//
+ui128 = (std::numeric_limits<uint128_t>::max)();
+std::cout << std::hex << std::showbase << multiply(ui256, ui128, ui128) << std::endl;
+
+

+

+

+ Produces the output: +

+

+

+
0xffffffffffffffff
+0x10000000000000000
+0xFFFFFFFFFFFFFFFE0000000000000001
+0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000001
+
+

+

+
+ + Backends + With Optimized Mixed Precision Arithmetic +
+

+ The following backends have at least some direct support for mixed precision + arithmetic, and therefore avoid creating unnecessary temporaries when using + the interfaces above. Therefore when using these types it's more efficient + to use mixed precision arithmetic, than it is to explicitly cast the operands + to the result type: +

+

+ mpfr_float, + gmp_float, + cpp_int. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/primetest.html b/doc/html/boost_multiprecision/tut/primetest.html new file mode 100644 index 00000000..fb38c41b --- /dev/null +++ b/doc/html/boost_multiprecision/tut/primetest.html @@ -0,0 +1,109 @@ + + + +Primality Testing + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ The library implements a Miller-Rabin test for primality: +

+
#include <boost/multiprecision/miller_rabin.hpp>
+
+template <class Backend, expression_template_option ExpressionTemplates, class Engine>
+bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials, Engine& gen);
+
+template <class Backend, expression_template_option ExpressionTemplates, class Engine>
+bool miller_rabin_test(const number<Backend, ExpressionTemplates>& n, unsigned trials);
+
+

+ These functions perform a Miller-Rabin test for primality, if the result + is false then n + is definitely composite, while if the result is true + then n is prime with probability 0.25^trials. + The algorithm used performs some trial divisions to exclude small prime factors, + does one Fermat test to exclude many more composites, and then uses the Miller-Rabin + algorithm straight out of Knuth Vol 2, which recommends 25 trials for a pretty + strong likelihood that n is prime. +

+

+ The third optional argument is for a Uniform Random Number Generator from + Boost.Random. When not provided the mt19937 + generator is used. Note that when producing random primes then you should + probably use a different random number generator to produce candidate prime + numbers for testing, than is used internally by miller_rabin_test + for determining whether the value is prime. It also helps of course to seed + the generators with some source of randomness. +

+

+ The following example searches for a prime p + for which (p-1)/2 is also probably prime: +

+

+

+
#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/miller_rabin.hpp>
+#include <iostream>
+#include <iomanip>
+
+int main()
+{
+   using namespace boost::random;
+   using namespace boost::multiprecision;
+
+   typedef cpp_int int_type;
+   mt11213b base_gen(clock());
+   independent_bits_engine<mt11213b, 256, int_type> gen(base_gen);
+   //
+   // We must use a different generator for the tests and number generation, otherwise
+   // we get false positives.
+   //
+   mt19937 gen2(clock());
+
+   for(unsigned i = 0; i < 100000; ++i)
+   {
+      int_type n = gen();
+      if(miller_rabin_test(n, 25, gen2))
+      {
+         // Value n is probably prime, see if (n-1)/2 is also prime:
+         std::cout << "We have a probable prime with value: " << std::hex << std::showbase << n << std::endl;
+         if(miller_rabin_test((n-1)/2, 25, gen2))
+         {
+            std::cout << "We have a safe prime with value: " << std::hex << std::showbase << n << std::endl;
+            return 0;
+         }
+      }
+   }
+   std::cout << "Ooops, no safe primes were found" << std::endl;
+   return 1;
+}
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/random.html b/doc/html/boost_multiprecision/tut/random.html new file mode 100644 index 00000000..e52df62e --- /dev/null +++ b/doc/html/boost_multiprecision/tut/random.html @@ -0,0 +1,157 @@ + + + +Generating Random Numbers + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ Random numbers are generated in conjunction with Boost.Random. However, since + Boost.Random is unaware of arbitrary + precision numbers, it's necessary to include the header: +

+
#include <boost/multiprecision/random.hpp>
+
+

+ In order to act as a bridge between the two libraries. +

+

+ Integers with N random bits are generated using independent_bits_engine: +

+

+

+
#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/random.hpp>
+
+using namespace boost::multiprecision;
+using namespace boost::random;
+
+//
+// Declare our random number generator type, the underlying generator
+// is the Mersenne twister mt19937 engine, and 256 bits are generated:
+//
+typedef independent_bits_engine<mt19937, 256, mpz_int> generator_type;
+generator_type gen;
+//
+// Generate some values:
+//
+std::cout << std::hex << std::showbase;
+for(unsigned i = 0; i < 10; ++i)
+   std::cout << gen() << std::endl;
+
+

+

+

+ Alternatively we can generate integers in a given range using uniform_int_distribution, this will invoke + the underlying engine multiple times to build up the required number of bits + in the result: +

+

+

+
#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/random.hpp>
+
+using namespace boost::multiprecision;
+using namespace boost::random;
+
+//
+// Generate integers in a given range using uniform_int,
+// the underlying generator is invoked multiple times
+// to generate enough bits:
+//
+mt19937 mt;
+uniform_int_distribution<mpz_int> ui(0, mpz_int(1) << 256);
+//
+// Generate the numbers:
+//
+std::cout << std::hex << std::showbase;
+for(unsigned i = 0; i < 10; ++i)
+   std::cout << ui(mt) << std::endl;
+
+

+

+

+ Floating point values in [0,1) are generated using uniform_01, + the trick here is to ensure that the underlying generator produces as many + random bits as there are digits in the floating point type. As above independent_bits_engine can be used for + this purpose, note that we also have to convert decimal digits (in the floating + point type) to bits (in the random number generator): +

+

+

+
#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/random.hpp>
+
+using namespace boost::multiprecision;
+using namespace boost::random;
+//
+// We need an underlying generator with at least as many bits as the
+// floating point type to generate numbers in [0, 1) with all the bits
+// in the floating point type randomly filled:
+//
+uniform_01<mpf_float_50> uf;
+independent_bits_engine<mt19937, 50L*1000L/301L, mpz_int> gen;
+//
+// Generate the values:
+//
+std::cout << std::setprecision(50);
+for(unsigned i = 0; i < 20; ++i)
+   std::cout << uf(gen) << std::endl;
+
+

+

+

+ Finally, we can modify the above example to produce numbers distributed according + to some distribution: +

+

+

+
#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/random.hpp>
+
+using namespace boost::multiprecision;
+using namespace boost::random;
+//
+// We can repeat the above example, with other distributions:
+//
+uniform_real_distribution<mpf_float_50> ur(-20, 20);
+gamma_distribution<mpf_float_50> gd(20);
+independent_bits_engine<mt19937, 50L*1000L/301L, mpz_int> gen;
+//
+// Generate some values:
+//
+std::cout << std::setprecision(50);
+for(unsigned i = 0; i < 20; ++i)
+   std::cout << ur(gen) << std::endl;
+for(unsigned i = 0; i < 20; ++i)
+   std::cout << gd(gen) << std::endl;
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational.html b/doc/html/boost_multiprecision/tut/rational.html new file mode 100644 index 00000000..712c33d3 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational.html @@ -0,0 +1,252 @@ + + + +Rational Number Types + + + + + + + + +
+PrevUpHomeNext +
+
+ + +

+ The following back-ends provide rational number arithmetic: +

+
++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend Type +

+
+

+ Header +

+
+

+ Radix +

+
+

+ Dependencies +

+
+

+ Pros +

+
+

+ Cons +

+
+

+ cpp_rational +

+
+

+ boost/multiprecision/cpp_int.hpp +

+
+

+ 2 +

+
+

+ None +

+
+

+ An all C++ Boost-licensed implementation. +

+
+

+ Slower than GMP. +

+
+

+ gmp_rational +

+
+

+ boost/multiprecision/gmp.hpp +

+
+

+ 2 +

+
+

+ GMP +

+
+

+ Very fast and efficient back-end. +

+
+

+ Dependency on GNU licensed GMP + library. +

+
+

+ tommath_rational +

+
+

+ boost/multiprecision/tommath.hpp +

+
+

+ 2 +

+
+

+ libtommath +

+
+

+ All C/C++ implementation that's Boost Software Licence compatible. +

+
+

+ Slower than GMP. +

+
+

+ rational_adapter +

+
+

+ boost/multiprecision/rational_adapter.hpp +

+
+

+ N/A +

+
+

+ none +

+
+

+ All C++ adapter that allows any integer back-end type to be used + as a rational type. +

+
+

+ Requires an underlying integer back-end type. +

+
+

+ boost::rational +

+
+

+ boost/rational.hpp +

+
+

+ N/A +

+
+

+ None +

+
+

+ A C++ rational number type that can used with any number integer type. +

+
+

+ The expression templates used by number + end up being "hidden" inside boost::rational: + performance may well suffer as a result. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational/br.html b/doc/html/boost_multiprecision/tut/rational/br.html new file mode 100644 index 00000000..c8802a42 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational/br.html @@ -0,0 +1,42 @@ + + + +Use With Boost.Rational + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ All of the integer types in this library can be used as template arguments + to boost::rational<IntType>. +

+

+ Note that using the library in this way largely negates the effect of the + expression templates in number. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational/cpp_rational.html b/doc/html/boost_multiprecision/tut/rational/cpp_rational.html new file mode 100644 index 00000000..cb140646 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational/cpp_rational.html @@ -0,0 +1,113 @@ + + + +cpp_rational + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/cpp_int.hpp> +

+
namespace boost{ namespace multiprecision{
+
+typedef rational_adapter<cpp_int_backend<> >    cpp_rational_backend;
+
+typedef number<cpp_rational_backend>         cpp_rational;
+
+}} // namespaces
+
+

+ The cpp_rational_backend + type is used via the typedef boost::multiprecision::cpp_rational. + It provides a rational number type that is a drop-in replacement for the + native C++ number types, but with unlimited precision. +

+

+ As well as the usual conversions from arithmetic and string types, instances + of cpp_rational are copy + constructible and assignable from type cpp_int. +

+

+ There is also a two argument constructor that accepts a numerator and denominator: + both of type cpp_int. +

+

+ There are also non-member functions: +

+
cpp_int numerator(const cpp_rational&);
+cpp_int denominator(const cpp_rational&);
+
+

+ which return the numerator and denominator of the number. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed cpp_rationals + have the value zero. +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid rational + number. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/cpp_int.hpp>
+
+using namespace boost::multiprecision;
+
+cpp_rational v = 1;
+
+// Do some arithmetic:
+for(unsigned i = 1; i <= 1000; ++i)
+   v *= i;
+v /= 10;
+
+std::cout << v << std::endl; // prints 1000! / 10
+std::cout << numerator(v) << std::endl;
+std::cout << denominator(v) << std::endl;
+
+cpp_rational w(2, 3);  // component wise constructor
+std::cout << w << std::endl; // prints 2/3
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational/gmp_rational.html b/doc/html/boost_multiprecision/tut/rational/gmp_rational.html new file mode 100644 index 00000000..9e78cecf --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational/gmp_rational.html @@ -0,0 +1,144 @@ + + + +gmp_rational + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/gmp.hpp> +

+
namespace boost{ namespace multiprecision{
+
+class gmp_rational;
+
+typedef number<gmp_rational >         mpq_rational;
+
+}} // namespaces
+
+

+ The gmp_rational back-end + is used via the typedef boost::multiprecision::mpq_rational. + It acts as a thin wrapper around the GMP + mpq_t to provide a rational + number type that is a drop-in replacement for the native C++ number types, + but with unlimited precision. +

+

+ As well as the usual conversions from arithmetic and string types, instances + of number<gmp_rational> + are copy constructible and assignable from: +

+
    +
  • + The GMP native types: mpz_t, mpq_t. +
  • +
  • + number<gmp_int>. +
  • +
+

+ There is also a two-argument constructor that accepts a numerator and denominator + (both of type number<gmp_int>). +

+

+ There are also non-member functions: +

+
mpz_int numerator(const mpq_rational&);
+mpz_int denominator(const mpq_rational&);
+
+

+ which return the numerator and denominator of the number. +

+

+ It's also possible to access the underlying mpq_t + via the data() + member function of mpq_rational. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed mpq_rationals + have the value zero (this is the GMP + default behavior). +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid rational + number. +
  • +
  • + No changes are made to the GMP + library's global settings, so this type can coexist with existing + GMP code. +
  • +
  • + The code can equally be used with MPIR + as the underlying library - indeed that is the preferred option on + Win32. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/gmp.hpp>
+
+using namespace boost::multiprecision;
+
+mpq_rational v = 1;
+
+// Do some arithmetic:
+for(unsigned i = 1; i <= 1000; ++i)
+   v *= i;
+v /= 10;
+
+std::cout << v << std::endl; // prints 1000! / 10
+std::cout << numerator(v) << std::endl;
+std::cout << denominator(v) << std::endl;
+
+mpq_rational w(2, 3);  // component wise constructor
+std::cout << w << std::endl; // prints 2/3
+
+// Access the underlying data:
+mpq_t q;
+mpq_init(q);
+mpq_set(q, v.backend().data());
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational/rational_adapter.html b/doc/html/boost_multiprecision/tut/rational/rational_adapter.html new file mode 100644 index 00000000..5a7b69ec --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational/rational_adapter.html @@ -0,0 +1,58 @@ + + + +rational_adapter + + + + + + + + +
+PrevUpHomeNext +
+
+ +
namespace boost{ namespace multiprecision{
+
+template <class IntBackend>
+class rational_adpater;
+
+}}
+
+

+ The class template rational_adapter + is a back-end for number + which converts any existing integer back-end into a rational-number back-end. +

+

+ So for example, given an integer back-end type MyIntegerBackend, + the use would be something like: +

+
typedef number<MyIntegerBackend>                    MyInt;
+typedef number<rational_adapter<MyIntegerBackend> > MyRational;
+
+MyRational r = 2;
+r /= 3;
+MyInt i = numerator(r);
+assert(i == 2);
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rational/tommath_rational.html b/doc/html/boost_multiprecision/tut/rational/tommath_rational.html new file mode 100644 index 00000000..12377a87 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rational/tommath_rational.html @@ -0,0 +1,119 @@ + + + +tommath_rational + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ #include <boost/multiprecision/tommath.hpp> +

+
namespace boost{ namespace multiprecision{
+
+typedef rational_adpater<tommath_int>        tommath_rational;
+typedef number<tommath_rational >         tom_rational;
+
+}} // namespaces
+
+

+ The tommath_rational back-end + is used via the typedef boost::multiprecision::tom_rational. + It acts as a thin wrapper around boost::rational<tom_int> to provide a rational number type that + is a drop-in replacement for the native C++ number types, but with unlimited + precision. +

+

+ The advantage of using this type rather than boost::rational<tom_int> directly, is that it is expression-template + enabled, greatly reducing the number of temporaries created in complex + expressions. +

+

+ There are also non-member functions: +

+
tom_int numerator(const tom_rational&);
+tom_int denominator(const tom_rational&);
+
+

+ which return the numerator and denominator of the number. +

+

+ Things you should know when using this type: +

+
    +
  • + Default constructed tom_rationals + have the value zero (this the inherited Boost.Rational behavior). +
  • +
  • + Division by zero results in a std::overflow_error + being thrown. +
  • +
  • + Conversion from a string results in a std::runtime_error + being thrown if the string can not be interpreted as a valid rational + number. +
  • +
  • + No changes are made to libtommath's + global state, so this type can safely coexist with other libtommath + code. +
  • +
  • + Performance of this type has been found to be pretty poor - this need + further investigation - but it appears that Boost.Rational needs some + improvement in this area. +
  • +
+
+ + Example: +
+

+

+
#include <boost/multiprecision/tommath.hpp>
+
+using namespace boost::multiprecision;
+
+tom_rational v = 1;
+
+// Do some arithmetic:
+for(unsigned i = 1; i <= 1000; ++i)
+   v *= i;
+v /= 10;
+
+std::cout << v << std::endl; // prints 1000! / 10
+std::cout << numerator(v) << std::endl;
+std::cout << denominator(v) << std::endl;
+
+tom_rational w(2, 3); // Component wise constructor
+std::cout << w << std::endl; // prints 2/3
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_multiprecision/tut/rounding.html b/doc/html/boost_multiprecision/tut/rounding.html new file mode 100644 index 00000000..1b64cfc3 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/rounding.html @@ -0,0 +1,182 @@ + + + +Rounding Rules for Conversions + + + + + + + + +
+PrevUpHomeNext +
+
+ +

+ As a general rule, all conversions between unrelated types are performed + using basic arithmetic operations, therefore conversions are either exact, + or follow the same rounding rules as arithmetic for the type in question. +

+

+ The following table summarises the situation for conversions from native + types: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Backend +

+
+

+ Rounding Rules +

+
+

+ cpp_int +

+
+

+ Conversions from integer types are exact if the target has sufficient + precision, otherwise they truncate to the first 2^MaxBits bits + (modulo arithmetic). Conversions from floating point types are + truncating to the nearest integer. +

+
+

+ gmp_int +

+
+

+ Conversions are performed by the GMP library except for conversion + from long double + which is truncating. +

+
+

+ tom_int +

+
+

+ Conversions from floating point types are truncating, all others + are performed by libtommath and are exact. +

+
+

+ gmp_float +

+
+

+ Conversions are performed by the GMP library except for conversion + from long double + which should be exact provided the target type has as much precision + as a long double. +

+
+

+ mpfr_float +

+
+

+ All conversions are performed by the underlying MPFR library. +

+
+

+ cpp_dec_float +

+
+

+ All conversions are performed using basic arithmetic operations + and are truncating. +

+
+

+ gmp_rational +

+
+

+ See gmp_int +

+
+

+ cpp_rational +

+
+

+ See cpp_int +

+
+

+ tommath_rational +

+
+

+ See tom_int +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 00000000..e0ee8f21 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,136 @@ + + + +Chapter 1. Boost.Multiprecision + + + + + + +
Next
+ + + + +

Last revised: November 18, 2012 at 15:59:30 GMT

+
+
Next
+ + diff --git a/doc/html4_symbols.qbk b/doc/html4_symbols.qbk new file mode 100644 index 00000000..55bf6588 --- /dev/null +++ b/doc/html4_symbols.qbk @@ -0,0 +1,215 @@ +[/ Symbols and Greek letters (about 120) from HTML4.] +[/ File HTML4_symbols.qbk] +[/ See http://www.htmlhelp.com/reference/html40/entities/symbols.html] +[/ See also http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references] +[/ http://www.alanwood.net/demos/ent4_frame.html] +[/ http://www.unicode.org/charts/PDF/U2200.pdf and others] +[/ All (except 2 angle brackets) show OK on Firefox 2.0] + +[/ See also Latin-1 aka Western (ISO-8859-1) in latin1_symbols.qbk] +[/ http://www.htmlhelp.com/reference/html40/entities/latin1.html] +[/Unicode Latin extended http://www.unicode.org/charts/U0080.pdf] + +[/ Also some miscellaneous math charaters added to this list - see the end.] +[/ For others see also math_symbols.qbk] + +[/ To use, enclose the template name in square brackets.] + +[template fnof[]'''ƒ'''] [/ ƒ Latin small f with hook = function = florin] +[/ Capital Greek start with capital letter, lower case all small.] +[template Alpha[]'''Α'''] [/ ? Greek capital letter alpha] +[template Beta[]'''Β'''] [/ ? Greek capital letter beta] +[template Gamma[]'''Γ'''] [/ G Greek capital letter gamma] +[template Delta[]'''Δ'''] [/ ? Greek capital letter delta] +[template Epsilon[]'''Ε'''] [/ ? Greek capital letter epsilon] +[template Zeta[]'''Ζ'''] [/ ? Greek capital letter zeta] +[template Eta[]'''Η'''] [/ ? Greek capital letter eta] +[template Theta[]'''Θ'''] [/ T Greek capital letter theta] +[template Iota[]'''Ι'''] [/ ? Greek capital letter iota] +[template Kappa[]'''Κ'''] [/ ? Greek capital letter kappa] +[template Lambda[]'''Λ'''] [/ ? Greek capital letter lambda] +[template Mu[]'''Μ'''] [/ ? Greek capital letter mu] +[template Nu[]'''Ν'''] [/ ? Greek capital letter nu] +[template Xi[]'''Ξ'''] [/ ? Greek capital letter xi] +[template Omicron[]'''Ο'''] [/ ? Greek capital letter omicron] +[template Pi[]'''Π'''] [/ ? Greek capital letter pi] +[template Rho[]'''Ρ'''] [/ ? Greek capital letter rho] +[template Sigma[]'''Σ'''] [/ S Greek capital letter sigma] +[template Tau[]'''Τ'''] [/ ? Greek capital letter tau] +[template Upsilon[]'''Υ'''] [/ ? Greek capital letter upsilon] +[template Phi[]'''Φ'''] [/ F Greek capital letter phi] +[template Chi[]'''Χ'''] [/ ? Greek capital letter chi] +[template Psi[]'''Ψ'''] [/ ? Greek capital letter psi] +[template Omega[]'''Ω'''] [/ O Greek capital letter omega] +[template alpha[]'''α'''] [/ a Greek small letter alpha] +[template beta[]'''β'''] [/ ß Greek small letter beta] +[template gamma[]'''γ'''] [/ ? Greek small letter gamma] +[template delta[]'''δ'''] [/ d Greek small letter delta] +[template epsilon[]'''ε'''] [/ e Greek small letter epsilon] +[template zeta[]'''ζ'''] [/ ? Greek small letter zeta] +[template eta[]'''η'''] [/ ? Greek small letter eta] +[template theta[]'''θ'''] [/ ? Greek small letter theta] +[template iota[]'''ι'''] [/ ? Greek small letter iota] +[template kappa[]'''κ'''] [/ ? Greek small letter kappa] +[template lambda[]'''λ'''] [/ ? Greek small letter lambda] +[template mu[]'''μ'''] [/ µ Greek small letter mu] +[template nu[]'''ν'''] [/ ? Greek small letter nu] +[template xi[]'''ξ'''] [/ ? Greek small letter xi] +[template omicron[]'''ο'''] [/ ? Greek small letter omicron] +[template pi[]'''π'''] [/ p Greek small letter pi] +[template rho[]'''ρ'''] [/ ? Greek small letter rho] +[template sigmaf[]'''ς'''] [/ ? Greek small letter final sigma] +[template sigma[]'''σ'''] [/ s Greek small letter sigma] +[template tau[]'''τ'''] [/ t Greek small letter tau] +[template upsilon[]'''υ'''] [/ ? Greek small letter upsilon] +[template phi[]'''φ'''] [/ f Greek small letter phi] +[template chi[]'''χ'''] [/ ? Greek small letter chi] +[template psi[]'''ψ'''] [/ ? Greek small letter psi] +[template omega[]'''ω'''] [/ ? Greek small letter omega] +[template thetasym[]'''ϑ'''] [/ ? Greek small letter theta symbol] +[template upsih[]'''ϒ'''] [/ ? Greek upsilon with hook symbol] +[template piv[]'''ϖ'''] [/ ? Greek pi symbol] + +[template bull[]'''•'''] [/ • bullet = black small circle] +[template hellip[]'''…'''] [/ … horizontal ellipsis = three dot leader] +[template prime[]'''′'''] [/ ' prime = minutes = feet] +[template Prime[]'''″'''] [/ ? double prime = seconds = inches] +[template oline[]'''‾'''] [/ ? overline = spacing overscore] +[template frasl[]'''⁄'''] [/ / fraction slash] +[template weierp[]'''℘'''] [/ P script capital P = power set = Weierstrass p] +[template image[]'''ℑ'''] [/ I blackletter capital I = imaginary part] +[template real[]'''ℜ'''] [/ R blackletter capital R = real part symbol] +[template trade[]'''™'''] [/ ™ trade mark sign] +[template alefsym[]'''ℵ'''] [/ ? alef symbol = first transfinite cardinal] +[template larr[]'''←'''] [/ ? leftwards arrow] +[template uarr[]'''↑'''] [/ ? upwards arrow] +[template rarr[]'''→'''] [/ ? rightwards arrow] +[template darr[]'''↓'''] [/ ? downwards arrow] +[template harr[]'''↔'''] [/ ? left right arrow] +[template crarr[]'''↵'''] [/ ? downwards arrow with corner leftwards = CR] +[template lArr[]'''⇐'''] [/ ? leftwards double arrow] +[template uArr[]'''⇑'''] [/ ? upwards double arrow] +[template rArr[]'''⇒'''] [/ ? rightwards double arrow] +[template dArr[]'''⇓'''] [/ ? downwards double arrow] +[template hArr[]'''⇔'''] [/ ? left right double arrow] +[template forall[]'''∀'''] [/ ? for all] +[template part[]'''∂'''] [/ ? partial differential] +[template exist[]'''∃'''] [/ ? there exists] +[template empty[]'''∅'''] [/ Ø empty set = null set = diameter] +[template nabla[]'''∇'''] [/ ? nabla = backward difference] +[template isin[]'''∈'''] [/ ? element of] +[template notin[]'''∉'''] [/ ? not an element of] +[template ni[]'''∋'''] [/ ? contains as member] +[template prod[]'''∏'''] [/ ? n-ary product = product sign] +[template sum[]'''∑'''] [/ ? n-ary sumation] +[template minus[]'''−'''] [/ - minus sign] +[template lowast[]'''∗'''] [/ * asterisk operator] +[template radic[]'''√'''] [/ v square root = radical sign] +[template prop[]'''∝'''] [/ ? proportional to] +[template infin[]'''∞'''] [/ 8 infinity] +[template ang[]'''∠'''] [/ ? angle] +[template and[]'''∧'''] [/ ? logical and = wedge] +[template or[]'''∨'''] [/ ? logical or = vee] +[template cap[]'''∩'''] [/ n intersection = cap] +[template cup[]'''∪'''] [/ ? union = cup] +[template int[]'''∫'''] [/ ? integral] +[template there4[]'''∴'''] [/ ? therefore] +[template sim[]'''∼'''] [/ ~ tilde operator = varies with = similar to] +[template cong[]'''≅'''] [/ ? approximately equal to] +[template asymp[]'''≈'''] [/ ˜ almost equal to = asymptotic to] +[template ne[]'''≠'''] [/ ? not equal to] +[template equiv[]'''≡'''] [/ = identical to] +[template le[]'''≤'''] [/ = less-than or equal to] +[template ge[]'''≥'''] [/ = greater-than or equal to] +[template subset[]'''⊂'''] [/ ? subset of] +[template superset[]'''⊃'''] [/ ? superset of] +[template nsubset[]'''⊄'''] [/ ? not a subset of] +[template sube[]'''⊆'''] [/ ? subset of or equal to] +[template supe[]'''⊇'''] [/ ? superset of or equal to] +[template oplus[]'''⊕'''] [/ ? circled plus = direct sum] +[template otimes[]'''⊗'''] [/ ? circled times = vector product] +[template perp[]'''⊥'''] [/ ? up tack = orthogonal to = perpendicular] +[template sdot[]'''⋅'''] [/ · dot operator] +[template lceil[]'''⌈'''] [/ ? left ceiling = APL upstile] +[template rceil[]'''⌉'''] [/ ? right ceiling] +[template lfloor[]'''⌊'''] [/ ? left floor = APL downstile] +[template rfloor[]'''⌋'''] [/ ? right floor] +[template lang[]'''〈'''] [/ < left-pointing angle bracket = bra (Firefox shows ?)] +[template rang[]'''〉'''] [/ > right-pointing angle bracket = ket (Firefox shows ?)] +[template loz[]'''◊'''] [/ ? lozenge] +[template spades[]'''♠'''] [/ ? black spade suit] +[template clubs[]'''♣'''] [/ ? black club suit = shamrock] +[template hearts[]'''♥'''] [/ ? black heart suit = valentine] +[template diams[]'''♦'''] [/ ? black diamond suit] +[template euro[]'''€'''] [/ ? Euro currency symbol] +[template lchev[]'''⟨'''] [/ ? left chevron] +[template rchev[]'''⟩'''] [/ right chevron] +[template rflat[]'''⟮'''] [/ right flat bracket Misc Math Symbol A] +[template lflat[]'''⟮'''] [/ left flat bracket] +[/ U2000.pdf punctuation] +[template endash[]'''–'''] [/ em width dash] +[template emdash[]'''—'''] [/ en width dash] +[template hbar[]'''―'''] [/ ? horizontal bar - introducing quoted text] +[template vert2bar[]'''‖'''] [/ ? double vertical bar] +[template line2[]'''‖'''] [/ ? double low line bar] +[template dagger[]'''†'''] [/ ? dagger] +[template dagger2[]'''‡'''] [/ ? double dagger] +[template dot[]'''․'''] [/ dot leader] +[template dot2[]'''‥'''] [/ ? dots leader] +[template ellipsis[]'''…'''] [/ horizontal ellipsis] + +[template dotover[]'''̇'''] [/ dot over symbol] +[template recur[]''' ̇'''] [/ math recurring symbol, eg after 0.333] +[/ Note use of a thin space before digit, so that dot isn't placed directly over the digit.] +[/ Use:1[recur]] + +[/ Other symbols, not in the HTML4 list:] +[template enquad[] ''' '''] [/ en quad space] +[template emquad[] ''' '''] [/ em quad space] +[template enspace[] ''' '''] [/ em half en space] +[template emspace[] ''' '''] [/ em space type size in points] +[template thickspace[] ''' '''] [/ 3 per em space] +[template midspace[] ''' '''] [/ 4 per em space] +[template sixemspace[] ''' '''] [/ 6 em space] +[template figspace[] ''' '''] [/ space = width fixed font digit] +[template punctspace[] ''' '''] [/ space = width punctuation] +[template thin[] ''' '''] [/ thin space ] +[template hair[] ''' '''] [/ hair space] +[template nbsp[] ''' '''] [/ non-breaking space] +[template space[] ''' '''] [/ plain non-breaking space] + +[template nospace[] '''​'''] [/ zero width space] +[template wordjoin[] '''⁠'''] [/ word joiner - no line break either side] +[template narrownbsp[] ''' '''] [/ narrow non-breaking space] +[template hyphen[] '''‐'''] [/ soft hyphen] +[template nbhyphen[] '''‑'''] [/ non-breaking hyphen] + +[template plusminus[]'''±'''] [/ ? plus or minus sign] +[template sqrt[]'''√'''] [/ ? square root sqrt symbol] +[/template pow2[]'''⁳'''] [/ 2073 is NOT superscript 2 character] +[template pow2[]'''²'''] [/ superscript 2 character] +[template pow3[]'''³'''] [/ superscript 3 character] +[template pown[]'''ⁿ'''] [/ superscript n character] +[template frac12[]'''½'''] [/ fraction half] +[template frac14[]'''¼'''] [/ fraction quarter] +[template frac34[]'''¾'''] [/ fraction three quarter] +[template sup1[]'''¹'''] [/ superscript one = superscript digit one ] +[template sup2[]'''²'''] [/ superscript two = superscript digit two = squared ] +[template cubed[]'''³'''] [/ superscript three = superscript digit three = cubed ] +[template macron[]'''¯'''] [/ macron = spacing macron = overline = APL overbar ] +[template deg[]'''°'''] [/ degree sign ] +[template plusmn[]'''±'''] [/ plus-minus sign = plus-or-minus sign ] +[template micro[]'''µ'''] [/ micro sign ] +[template cedil[]'''¸'''] [/ cedilla = spacing cedilla ] +[template ordm[]'''º'''] [/ masculine ordinal indicator ] +[template ordf[]'''ª'''] [/ feminine ordinal indicator ] +[template laquo[]'''«'''] [/ left-pointing double angle quotation mark = left pointing guillemet ] +[template raquo[]'''»'''] [/ right-pointing double angle quotation mark = right pointing guillemet ] + +[/ +Copyright 2007, 2010 Paul A. Bristow. +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt). +] + diff --git a/doc/index.idx b/doc/index.idx new file mode 100644 index 00000000..629072a4 --- /dev/null +++ b/doc/index.idx @@ -0,0 +1,18 @@ +# Copyright 2011 John Maddock. Distributed under the Boost +# Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Rewrite the class scanner to accept declarations, not just definitions, +# as the docs don't include full definitions. +# +!define-scanner class_name "^[[:space:]]*(template[[:space:]]*<[^;:{]+>[[:space:]]*)?(class|struct)[[:space:]]*(\<\w+\>([[:blank:]]*\([^)]*\))?[[:space:]]*)*(\<\w*\>)[[:space:]]*(<[^;:{]+>)?[[:space:]]*(\{|:[^;\{()]*\{)" "(?:class|struct)[^;{]+\\<\5\\>\\s*[;{]" \5 + +!scan-path boost/multiprecision .*\.hpp true + + + + + + + + diff --git a/doc/multiprecision.qbk b/doc/multiprecision.qbk new file mode 100644 index 00000000..7cf97a16 --- /dev/null +++ b/doc/multiprecision.qbk @@ -0,0 +1,3472 @@ +[/ + Copyright 2011 John Maddock. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +] + +[library Boost.Multiprecision + [quickbook 1.5] + [copyright 2002-2012 John Maddock and Christopher Kormanyos] + [purpose Multiprecision Number library] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Maddock, John], [Kormanyos, Christopher]] + [/last-revision $Date: 2011-07-08 18:51:46 +0100 (Fri, 08 Jul 2011) $] +] + +[include html4_symbols.qbk] +[import ../example/gmp_snips.cpp] +[import ../example/mpfr_snips.cpp] +[import ../example/cpp_dec_float_snips.cpp] +[import ../example/tommath_snips.cpp] +[import ../example/cpp_int_snips.cpp] +[import ../example/random_snips.cpp] +[import ../example/safe_prime.cpp] +[import ../example/mixed_integer_arithmetic.cpp] + +[template mpfr[] [@http://www.mpfr.org MPFR]] +[template gmp[] [@http://gmplib.org GMP]] +[template mpf_class[] [@http://gmplib.org/manual/C_002b_002b-Interface-Floats.html#C_002b_002b-Interface-Floats mpf_class]] +[template mpfr_class[] [@http://math.berkeley.edu/~wilken/code/gmpfrxx/ mpfr_class]] +[template mpreal[] [@http://www.holoborodko.com/pavel/mpfr/ mpreal]] +[template mpir[] [@http://mpir.org/ MPIR]] +[template tommath[] [@http://libtom.org/?page=features&newsitems=5&whatfile=ltm libtommath]] + +[template super[x]''''''[x]''''''] +[template sub[x]''''''[x]''''''] + +[template equation[name] ''' + + + + + + +'''] + +[def __cpp_int [link boost_multiprecision.tut.ints.cpp_int cpp_int]] +[def __gmp_int [link boost_multiprecision.tut.ints.gmp_int gmp_int]] +[def __tom_int [link boost_multiprecision.tut.ints.tom_int tom_int]] +[def __gmp_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]] +[def __mpf_float [link boost_multiprecision.tut.floats.gmp_float gmp_float]] +[def __mpfr_float_backend [link boost_multiprecision.tut.floats.mpfr_float mpfr_float]] +[def __cpp_dec_float [link boost_multiprecision.tut.floats.cpp_dec_float cpp_dec_float]] +[def __gmp_rational [link boost_multiprecision.tut.rational.gmp_rational gmp_rational]] +[def __cpp_rational [link boost_multiprecision.tut.rational.cpp_rational cpp_rational]] +[def __tommath_rational [link boost_multiprecision.tut.rational.tommath_rational tommath_rational]] + +[section:intro Introduction] + +The Multiprecision Library provides ['User-defined] integer, rational and floating-point C++ types which +try to emulate as closely as practicable the C++ built-in types, but provide for more range and +precision. Depending upon the number type, precision may be arbitrarily large (limited only by available memory), +fixed at compile time values, for example 50 decimal +digits, or a variable controlled at run-time by member functions. The types are +expression-template-enabled for better performance than naive user-defined types. + +The Multiprecision library comes in two distinct parts: + +* An expression-template-enabled front-end `number` +that handles all the operator overloading, expression evaluation optimization, and code reduction. +* A selection of back-ends that implement the actual arithmetic operations, and need conform only to the +reduced interface requirements of the front-end. + +Separation of front-end and back-end allows use of highly refined, but restricted license libraries +where possible, but provides Boost license alternatives for users who must have a portable +unconstrained license. Which is to say some back-ends rely on 3rd party libraries, but a header-only Boost license version is always +available (if somewhat slower). + +Should you just wish to cut to the chase and use a fully Boost-licensed number type, then skip to +__cpp_int for multiprecision integers, __cpp_dec_float for multiprecision floating point types +and __cpp_rational for rational types. + +The library is often used via one of the predefined typedefs: for example if you wanted an [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] +integer type using [gmp] as the underlying implementation then you could use: + + #include // Defines the wrappers around the GMP library's types + + boost::multiprecision::mpz_int myint; // Arbitrary precision integer type. + +Alternatively, you can compose your own multiprecision type, by combining `number` with one of the +predefined back-end types. For example, suppose you wanted a 300 decimal digit floating-point type +based on the [mpfr] library. In this case, there's no predefined typedef with that level of precision, +so instead we compose our own: + + #include // Defines the Backend type that wraps MPFR + + namespace mp = boost::multiprecision; // Reduce the typing a bit later... + + typedef mp::number > my_float; + + my_float a, b, c; // These variables have 300 decimal digits precision + +We can repeat the above example, but with the expression templates disabled (for faster compile times, but slower runtimes) +by passing a second template argument to `number`: + + #include // Defines the Backend type that wraps MPFR + + namespace mp = boost::multiprecision; // Reduce the typing a bit later... + + typedef mp::number, et_off> my_float; + + my_float a, b, c; // These variables have 300 decimal digits precision + +We can also mix arithmetic operations between different types, provided there is an unambiguous implicit conversion from one +type to the other: + + #include + + namespace mp = boost::multiprecision; // Reduce the typing a bit later... + + mp::int128_t a(3), b(4); + mp::int512_t c(50), d; + + d = c * a; // OK, result of mixed arithmetic is an int512_t + +Conversions are also allowed: + + d = a; // OK, widening conversion. + d = a * b; // OK, can convert from an expression template too. + +However conversions that are inherently lossy are either declared explicit or else forbidden altogether: + + d = 3.14; // Error implicit conversion from float not allowed. + d = static_cast(3.14); // OK explicit construction is allowed + +Mixed arithmetic will fail if the conversion is either ambiguous or explicit: + + number, et_off> a(2); + number, et_on> b(3); + + b = a * b; // Error, implicit conversion could go either way. + b = a * 3.14; // Error, no operator overload if the conversion would be explicit. + +[h4 Move Semantics] + +On compilers that support rvalue-references, class `number` is move-enabled if the underlying backend is. + +In addition the non-expression template operator overloads (see below) are move aware and have overloads +that look something like: + + template + number operator + (number&& a, const number& b) + { + return std::move(a += b); + } + +These operator overloads ensure that many expressions can be evaluated without actually generating any temporaries. +However, there are still many simple expressions such as: + + a = b * c; + +Which don't noticeably benefit from move support. Therefore, optimal performance comes from having both +move-support, and expression templates enabled. + +Note that while "moved-from" objects are left in a sane state, they have an unspecified value, and the only permitted +operations on them are destruction or the assignment of a new value. Any other operation should be considered +a programming error and all of our backends will trigger an assertion if any other operation is attempted. This behavior +allows for optimal performance on move-construction (i.e. no allocation required, we just take ownership of the existing +object's internal state), while maintaining usability in the standard library containers. + +[h4 Expression Templates] + +Class `number` is expression-template-enabled: that means that rather than having a multiplication +operator that looks like this: + + template + number operator * (const number& a, const number& b) + { + number result(a); + result *= b; + return result; + } + +Instead the operator looks more like this: + + template + ``['unmentionable-type]`` operator * (const number& a, const number& b); + +Where the "unmentionable" return type is an implementation detail that, rather than containing the result +of the multiplication, contains instructions on how to compute the result. In effect it's just a pair +of references to the arguments of the function, plus some compile-time information that stores what the operation +is. + +The great advantage of this method is the ['elimination of temporaries]: for example the "naive" implementation +of `operator*` above, requires one temporary for computing the result, and at least another one to return it. It's true +that sometimes this overhead can be reduced by using move-semantics, but it can't be eliminated completely. For example, +lets suppose we're evaluating a polynomial via Horner's method, something like this: + + T a[7] = { /* some values */ }; + //.... + y = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]; + +If type `T` is a `number`, then this expression is evaluated ['without creating a single temporary value]. In contrast, +if we were using the [mpfr_class] C++ wrapper for [mpfr] - then this expression would result in no less than 11 +temporaries (this is true even though [mpfr_class] does use expression templates to reduce the number of temporaries somewhat). Had +we used an even simpler wrapper around [mpfr] like [mpreal] things would have been even worse and no less that 24 temporaries +are created for this simple expression (note - we actually measure the number of memory allocations performed rather than +the number of temporaries directly, note also that the [mpf_class] wrapper that will be supplied with GMP-5.1 reduces the number of +temporaries to pretty much zero). Note that if we compile with expression templates disabled and rvalue-reference support +on, then actually still have no wasted memory allocations as even though temporaries are created, their contents are moved +rather than copied. +[footnote The actual number generated will depend on the compiler, how well it optimises the code, and whether it supports +rvalue references. The number of 11 temporaries was generated with Visual C++ 10] + +[important +Expression templates can radically reorder the operations in an expression, for example: + + a = (b * c) * a; + +Will get transformed into: + + a *= c; + a *= b; + +If this is likely to be an issue for a particular application, then they should be disabled. +] + +This library also extends expression template support to standard library functions like `abs` or `sin` with `number` +arguments. This means that an expression such as: + + y = abs(x); + +can be evaluated without a single temporary being calculated. Even expressions like: + + y = sin(x); + +get this treatment, so that variable 'y' is used as "working storage" within the implementation of `sin`, +thus reducing the number of temporaries used by one. Of course, should you write: + + x = sin(x); + +Then we clearly can't use `x` as working storage during the calculation, so then a temporary variable +is created in this case. + +Given the comments above, you might be forgiven for thinking that expression-templates are some kind of universal-panacea: +sadly though, all tricks like this have their downsides. For one thing, expression template libraries +like this one, tend to be slower to compile than their simpler cousins, they're also harder to debug +(should you actually want to step through our code!), and rely on compiler optimizations being turned +on to give really good performance. Also, since the return type from expressions involving `number`s +is an "unmentionable implementation detail", you have to be careful to cast the result of an expression +to the actual number type when passing an expression to a template function. For example, given: + + template + void my_proc(const T&); + +Then calling: + + my_proc(a+b); + +Will very likely result in obscure error messages inside the body of `my_proc` - since we've passed it +an expression template type, and not a number type. Instead we probably need: + + my_proc(my_number_type(a+b)); + +Having said that, these situations don't occur that often - or indeed not at all for non-template functions. +In addition, all the functions in the Boost.Math library will automatically convert expression-template arguments +to the underlying number type without you having to do anything, so: + + mpfr_float_100 a(20), delta(0.125); + boost::math::gamma_p(a, a + delta); + +Will work just fine, with the `a + delta` expression template argument getting converted to an `mpfr_float_100` +internally by the Boost.Math library. + +One other potential pitfall that's only possible in C++11: you should never store an expression template using: + + auto my_expression = a + b - c; + +unless you're absolutely sure that the lifetimes of `a`, `b` and `c` will outlive that of `my_expression`. + +And finally... the performance improvements from an expression template library like this are often not as +dramatic as the reduction in number of temporaries would suggest. For example if we compare this library with +[mpfr_class] and [mpreal], with all three using the underlying [mpfr] library at 50 decimal digits precision then +we see the following typical results for polynomial execution: + +[table Evaluation of Order 6 Polynomial. +[[Library] [Relative Time] [Relative number of memory allocations]] +[[number] [1.0 (0.00957s)] [1.0 (2996 total)]] +[[[mpfr_class]] [1.1 (0.0102s)] [4.3 (12976 total)]] +[[[mpreal]] [1.6 (0.0151s)] [9.3 (27947 total)]] +] + +As you can see, the execution time increases a lot more slowly than the number of memory allocations. There are +a number of reasons for this: + +* The cost of extended-precision multiplication and division is so great, that the times taken for these tend to +swamp everything else. +* The cost of an in-place multiplication (using `operator*=`) tends to be more than an out-of-place +`operator*` (typically `operator *=` has to create a temporary workspace to carry out the multiplication, where +as `operator*` can use the target variable as workspace). Since the expression templates carry out their +magic by converting out-of-place operators to in-place ones, we necessarily take this hit. Even so the +transformation is more efficient than creating the extra temporary variable, just not by as much as +one would hope. + +Finally, note that `number` takes a second template argument, which, when set to `et_off` disables all +the expression template machinery. The result is much faster to compile, but slower at runtime. + +We'll conclude this section by providing some more performance comparisons between these three libraries, +again, all are using [mpfr] to carry out the underlying arithmetic, and all are operating at the same precision +(50 decimal digits): + +[table Evaluation of Boost.Math's Bessel function test data +[[Library] [Relative Time] [Relative Number of Memory Allocations]] +[[mpfr_float_50] [1.0 (5.78s)] [1.0 (1611963)]] +[[number, et_off>[br](but with rvalue reference support)] + [1.1 (6.29s)] [2.64 (4260868)]] +[[[mpfr_class]] [1.1 (6.28s)] [2.45 (3948316)]] +[[[mpreal]] [1.65 (9.54s)] [8.21 (13226029)]] +] + +[table Evaluation of Boost.Math's Non-Central T distribution test data +[[Library][Relative Time][Relative Number of Memory Allocations]] +[[number] [1.0 (263s)][1.0 (127710873)]] +[[number, et_off>[br](but with rvalue reference support)] + [1.0 (260s)][1.2 (156797871)]] +[[[mpfr_class]] [1.1 (287s)][2.1 (268336640)]] +[[[mpreal]] [1.5 (389s)][3.6 (466960653)]] +] + +The above results were generated on Win32 compiling with Visual C++ 2010, all optimizations on (/Ox), +with MPFR 3.0 and MPIR 2.3.0. + +[endsect] + +[section:tut Tutorial] + +In order to use this library you need to make two choices: what kind of number do I want, and +which back-end do I want to perform the actual arithmetic? + +[section:ints Integer Types] + +The following back-ends provide integer arithmetic: + +[table +[[Backend Type][Header][Radix][Dependencies][Pros][Cons]] +[[`cpp_int`][boost/multiprecision/cpp_int.hpp][2][None] + [Very versatile, Boost licensed, all C++ integer type which support both [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] and fixed precision integer types.][Slower than [gmp], though typically not as slow as [tommath]]] +[[`gmp_int`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] +[[`tom_int`][boost/multiprecision/tommath.hpp][2][[tommath]][Public domain back-end with no licence restrictions.][Slower than [gmp].]] +] + +[section:cpp_int cpp_int] + +`#include ` + + namespace boost{ namespace multiprecision{ + + typedef unspecified-type limb_type; + + enum cpp_integer_type { signed_magnitude, unsigned_magnitude }; + enum cpp_int_check_type { checked, unchecked }; + + template > + class cpp_int_backend; + // + // Expression templates default to et_off if there is no allocator: + // + template + struct expression_template_default > + { static const expression_template_option value = et_off; }; + + typedef number > cpp_int; // arbitrary precision integer + typedef rational_adapter > cpp_rational_backend; + typedef number cpp_rational; // arbitrary precision rational number + + // Fixed precision unsigned types: + typedef number > uint128_t; + typedef number > uint256_t; + typedef number > uint512_t; + typedef number > uint1024_t; + + // Fixed precision signed types: + typedef number > int128_t; + typedef number > int256_t; + typedef number > int512_t; + typedef number > int1024_t; + + // Over again, but with checking enabled this time: + typedef number > checked_cpp_int; + typedef rational_adapter > checked_cpp_rational_backend; + typedef number checked_cpp_rational; + + // Checked fixed precision unsigned types: + typedef number > checked_uint128_t; + typedef number > checked_uint256_t; + typedef number > checked_uint512_t; + typedef number > checked_uint1024_t; + + // Fixed precision signed types: + typedef number > checked_int128_t; + typedef number > checked_int256_t; + typedef number > checked_int512_t; + typedef number > checked_int1024_t; + + }} // namespaces + +The `cpp_int_backend` type is normally used via one of the convenience typedefs given above. + +This back-end is the "Swiss Army Knife" of integer types as it can represent both fixed and +[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] +integer types, and both signed and unsigned types. There are five template arguments: + +[variablelist +[[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory + allocation. When zero, this field is determined automatically based on how many bits can be stored + in union with the dynamic storage header: setting a larger value may improve performance as larger integer + values will be stored internally before memory allocation is required.]] +[[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type. + When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic + memory allocation will ever be performed: in this situation the Allocator parameter should be set to + type `void`. Note that this parameter should not be used simply to prevent large memory + allocations, not only is that role better performed by the allocator, but fixed precision + integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]] +[[SignType][Determines whether the resulting type is signed or not. Note that for +[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types + this parameter must be `signed_magnitude`. For fixed precision + types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]] +[[Checked][This parameter has two values: `checked` or `unchecked`. See below.]] +[[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]] +] + +When the template parameter Checked is set to `checked` then the result is a ['checked-integer], checked +and unchecked integers have the following properties: + +[table +[[Condition][Checked-Integer][Unchecked-Integer]] +[[Numeric overflow in fixed precision arithmetic][Throws a `std::overflow_error`.][Performs arithmetic modulo 2[super MaxBits]]] +[[Constructing an integer from a value that can not be represented in the target type][Throws a `std::range_error`.] +[Converts the value modulo 2[super MaxBits], signed to unsigned conversions extract the last MaxBits bits of the +2's complement representation of the input value.]] +[[Unsigned subtraction yielding a negative value.][Throws a `std::range_error`.][Yields the value that would +result from treating the unsigned type as a 2's complement signed type.]] +[[Attempting a bitwise operation on a negative value.][Throws a `std::range_error`][Yields the value, but not the bit pattern, +that would result from performing the operation on a 2's complement integer type.]] +] + +Things you should know when using this type: + +* Default constructed `cpp_int_backend`s have the value zero. +* Division by zero results in a `std::overflow_error` being thrown. +* Construction from a string that contains invalid non-numeric characters results in a `std::runtime_error` being thrown. +* Since the precision of `cpp_int_backend` is necessarily limited when the allocator parameter is void, +care should be taken to avoid numeric overflow when using this type +unless you actually want modulo-arithmetic behavior. +* The type uses a sign-magnitude representation internally, so type `int128_t` has 128-bits of precision plus an extra sign bit. +In this respect the behaviour of these types differs from built-in 2's complement types. In might be tempting to use a +127-bit type instead, and indeed this does work, but behaviour is still slightly different from a 2's complement built-in type +as the min and max values are identical (apart from the sign), where as they differ by one for a true 2's complement type. +That said it should be noted that there's no requirement for built-in types to be 2's complement either - it's simply that this +is the most common format by far. +* Attempting to print negative values as either an Octal or Hexadecimal string results in a `std::runtime_error` being thrown, +this is a direct consequence of the sign-magnitude representation. +* The fixed precision types `[checked_][u]intXXX_t` have expression template support turned off - it seems to make little +difference to the performance of these types either way - so we may as well have the faster compile times by turning +the feature off. +* Unsigned types support subtraction - the result is "as if" a 2's complement operation had been performed as long as they are not + ['checked-integers] (see above). + In other words they behave pretty much as a built in integer type would in this situation. So for example if we were using + `uint128_t` then `uint128_t(1)-4` would result in the value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD` + of type `uint128_t`. However, had this operation been performed on `checked_uint128_t` then a `std::range_error` would have + been thrown. +* Unary negation of unsigned types results in a compiler error (static assertion). +* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. +* When used at fixed precision, the size of this type is always one machine word larger than you would expect for an N-bit integer: +the extra word stores both the sign, and how many machine words in the integer are actually in use. +The latter is an optimisation for larger fixed precision integers, so that a 1024-bit integer has almost the same performance +characterists as a 128-bit integer, rather than being 4 times slower for addition and 16 times slower for multiplication + (assuming the values involved would always fit in 128 bits). +Typically this means you can use +an integer type wide enough for the "worst case senario" with only minor performance degradation even if most of the time +the arithmetic could in fact be done with a narrower type. +* When used at fixed precision and MaxBits is smaller than the number of bits in the largest native integer type, then +internally `cpp_int_backend` switches to a "trivial" implementation where it is just a thin wrapper around a single +integer. Note that it will still be slightly slower than a bare native integer, as it emulates a +signed-magnitude representation rather than simply using the platforms native sign representation: this ensures +there is no step change in behavior as a cpp_int grows in size. + + +[h5 Example:] + +[cpp_int_eg] + +[endsect] + +[section:gmp_int gmp_int] + +`#include ` + + namespace boost{ namespace multiprecision{ + + class gmp_int; + + typedef number mpz_int; + + }} // namespaces + +The `gmp_int` back-end is used via the typedef `boost::multiprecision::mpz_int`. It acts as a thin wrapper around the [gmp] `mpz_t` +to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision. + +As well as the usual conversions from arithmetic and string types, type `mpz_int` is copy constructible and assignable from: + +* The [gmp] native types: `mpf_t`, `mpz_t`, `mpq_t`. +* Instances of `number` that are wrappers around those types: `number >`, `number`. + +It's also possible to access the underlying `mpz_t` via the `data()` member function of `gmp_int`. + +Things you should know when using this type: + +* No changes are made to the GMP library's global settings - so you can safely mix this type with +existing code that uses [gmp]. +* Default constructed `gmp_int`s have the value zero (this is GMP's default behavior). +* Formatted IO for this type does not support octal or hexadecimal notation for negative values, +as a result performing formatted output on this type when the argument is negative and either of the flags +`std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted +as a valid integer. +* Division by zero results in a `std::overflow_error` being thrown. +* Although this type is a wrapper around [gmp] it will work equally well with [mpir]. Indeed use of [mpir] +is recommended on Win32. +* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. + +[h5 Example:] + +[mpz_eg] + +[endsect] + +[section:tom_int tom_int] + +`#include ` + + namespace boost{ namespace multiprecision{ + + class tommath_int; + + typedef number tom_int; + + }} // namespaces + +The `tommath_int` back-end is used via the typedef `boost::multiprecision::tom_int`. It acts as a thin wrapper around the [tommath] `tom_int` +to provide an integer type that is a drop-in replacement for the native C++ integer types, but with unlimited precision. + +Things you should know when using this type: + +* Default constructed objects have the value zero (this is [tommath]'s default behavior). +* Although `tom_int` is mostly a drop in replacement for the builtin integer types, it should be noted that it is a +rather strange beast as it's a signed type that is not a 2's complement type. As a result the bitwise operations +`| & ^` will throw a `std::runtime_error` exception if either of the arguments is negative. Similarly the complement +operator`~` is deliberately not implemented for this type. +* Formatted IO for this type does not support octal or hexadecimal notation for negative values, +as a result performing formatted output on this type when the argument is negative and either of the flags +`std::ios_base::oct` or `std::ios_base::hex` are set, will result in a `std::runtime_error` will be thrown. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted +as a valid integer. +* Division by zero results in a `std::overflow_error` being thrown. + +[h5 Example:] + +[tommath_eg] + +[endsect] + +[section:egs Examples] + +[import ../example/integer_examples.cpp] + +[section:factorials Factorials] +[FAC1] +[endsect] + +[section:bitops Bit Operations] +[BITOPS] +[endsect] + +[endsect] + +[endsect] + +[section:floats Floating Point Numbers] + +The following back-ends provide floating point arithmetic: + +[table +[[Backend Type][Header][Radix][Dependencies][Pros][Cons]] +[[`cpp_dec_float`][boost/multiprecision/cpp_dec_float.hpp][10][None][Header only, all C++ implementation. Boost licence.][Approximately 2x slower than the [mpfr] or [gmp] libraries.]] +[[`mpf_float`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] +[[`mpfr_float`][boost/multiprecision/mpfr.hpp][2][[gmp] and [mpfr]][Very fast and efficient back-end, with its own standard library implementation.][Dependency on GNU licensed [gmp] and [mpfr] libraries.]] +] + +[section:cpp_dec_float cpp_dec_float] + +`#include ` + + namespace boost{ namespace multiprecision{ + + template + class cpp_dec_float; + + typedef number > cpp_dec_float_50; + typedef number > cpp_dec_float_100; + + }} // namespaces + +The `cpp_dec_float` back-end is used in conjunction with `number`: It acts as an entirely C++ (header only and dependency free) +floating-point number type that is a drop-in replacement for the native C++ floating-point types, but with +much greater precision. + +Type `cpp_dec_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter. +The typedefs `cpp_dec_float_50` and `cpp_dec_float_100` provide arithmetic types at 50 and 100 decimal digits precision +respectively. Optionally, you can specify an integer type to use for the exponent, this defaults to a 32-bit integer type +which is more than large enough for the vast majority of use cases, but larger types such as `long long` can also be specified +if you need a truely huge exponent range. + +Normally `cpp_dec_float` allocates no memory: all of the space required for its digits are allocated +directly within the class. As a result care should be taken not to use the class with too high a digit count +as stack space requirements can grow out of control. If that represents a problem then providing an allocator +as the final template parameter causes `cpp_dec_float` to dynamically allocate the memory it needs: this +significantly reduces the size of `cpp_dec_float` and increases the viable upper limit on the number of digits +at the expense of performance. However, please bear in mind that arithmetic operations rapidly become ['very] expensive +as the digit count grows: the current implementation really isn't optimized or designed for large digit counts. + +There is full standard library and `numeric_limits` support available for this type. + +Things you should know when using this type: + +* Default constructed `cpp_dec_float`s have a value of zero. +* The radix of this type is 10. As a result it can behave subtly differently from base-2 types. +* The type has a number of internal guard digits over and above those specified in the template argument. +Normally these should not be visible to the user. +* The type supports both infinities and NaN's. An infinity is generated whenever the result would overflow, +and a NaN is generated for any mathematically undefined operation. +* There is a `std::numeric_limits` specialisation for this type. +* Any `number` instantiated on this type, is convertible to any other `number` instantiated on this type - +for example you can convert from `number >` to `number >`. +Narrowing conversions are truncating and `explicit`. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted +as a valid floating point number. +* The actual precision of a `cpp_dec_float` is always slightly higher than the number of digits specified in +the template parameter, actually how much higher is an implementation detail but is always at least 8 decimal +digits. +* Operations involving `cpp_dec_float` are always truncating. However, note that since their are guard digits +in effect, in practice this has no real impact on accuracy for most use cases. + +[h5 cpp_dec_float example:] + +[cpp_dec_float_eg] + +[endsect] + +[section:gmp_float gmp_float] + +`#include ` + + namespace boost{ namespace multiprecision{ + + template + class gmp_float; + + typedef number > mpf_float_50; + typedef number > mpf_float_100; + typedef number > mpf_float_500; + typedef number > mpf_float_1000; + typedef number > mpf_float; + + }} // namespaces + +The `gmp_float` back-end is used in conjunction with `number` : it acts as a thin wrapper around the [gmp] `mpf_t` +to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with +much greater precision. + +Type `gmp_float` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or +at variable precision by setting the template argument to zero. The typedefs mpf_float_50, mpf_float_100, +mpf_float_500, mpf_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision +respectively. The typedef mpf_float provides a variable precision type whose precision can be controlled via the +`number`s member functions. + +[note This type only provides standard library and `numeric_limits` support when the precision is fixed at compile time.] + +As well as the usual conversions from arithmetic and string types, instances of `number >` are +copy constructible and assignable from: + +* The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`. +* The `number` wrappers around those types: `number >`, `number`, `number`. + +It's also possible to access the underlying `mpf_t` via the `data()` member function of `gmp_float`. + +Things you should know when using this type: + +* Default constructed `gmp_float`s have the value zero (this is the [gmp] library's default behavior). +* No changes are made to the [gmp] library's global settings, so this type can be safely mixed with +existing [gmp] code. +* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. +* It is not possible to round-trip objects of this type to and from a string and get back +exactly the same value. This appears to be a limitation of [gmp]. +* Since the underlying [gmp] types have no notion of infinities or NaN's, care should be taken +to avoid numeric overflow or division by zero. That latter will result in a std::overflow_error being thrown, +while generating excessively large exponents may result in instability of the underlying [gmp] +library (in testing, converting a number with an excessively large or small exponent +to a string caused [gmp] to segfault). +* This type can equally be used with [mpir] as the underlying implementation - indeed that is +the recommended option on Win32. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted +as a valid floating point number. +* Division by zero results in a `std::overflow_error` being thrown. + +[h5 [gmp] example:] + +[mpf_eg] + +[endsect] + +[section:mpfr_float mpfr_float] + +`#include ` + + namespace boost{ namespace multiprecision{ + + enum mpfr_allocation_type + { + allocate_stack, + allocate_dynamic + }; + + template + class mpfr_float_backend; + + typedef number > mpfr_float_50; + typedef number > mpfr_float_100; + typedef number > mpfr_float_500; + typedef number > mpfr_float_1000; + typedef number > mpfr_float; + + typedef number > static_mpfr_float_50; + typedef number > static_mpfr_float_100; + + }} // namespaces + +The `mpfr_float_backend` type is used in conjunction with `number`: It acts as a thin wrapper around the [mpfr] `mpfr_t` +to provide an real-number type that is a drop-in replacement for the native C++ floating-point types, but with +much greater precision. + +Type `mpfr_float_backend` can be used at fixed precision by specifying a non-zero `Digits10` template parameter, or +at variable precision by setting the template argument to zero. The typedefs mpfr_float_50, mpfr_float_100, +mpfr_float_500, mpfr_float_1000 provide arithmetic types at 50, 100, 500 and 1000 decimal digits precision +respectively. The typedef mpfr_float provides a variable precision type whose precision can be controlled via the +`number`s member functions. + +In addition the second template parameter lets you choose between dynamic allocation (the default, +and uses MPFR's normal allocation routines), +or stack allocation (where all the memory required for the underlying data types is stored +within `mpfr_float_backend`). The latter option can result in significantly faster code, at the +expense of growing the size of `mpfr_float_backend`. It can only be used at fixed precision, and +should only be used for lower digit counts. Note that we can not guarentee that using `allocate_stack` +won't cause any calls to mpfr's allocation routines, as mpfr may call these inside it's own code. +The following table gives an idea of the performance tradeoff's at 50 decimal digits +precision[footnote Compiled with VC++10 and /Ox, with MPFR-3.0.0 and MPIR-2.3.0]: + +[table +[[Type][Bessel function evaluation, relative times]] +[[`number, et_on>`][1.0 (5.5s)]] +[[`number, et_off>`][1.05 (5.8s)]] +[[`number, et_on>`][1.05 (5.8s)]] +[[`number, et_off>`][1.16 (6.4s)]] +] + +[note This type only provides `numeric_limits` support when the precision is fixed at compile time.] + +As well as the usual conversions from arithmetic and string types, instances of `number >` are +copy constructible and assignable from: + +* The [gmp] native types `mpf_t`, `mpz_t`, `mpq_t`. +* The [mpfr] native type `mpfr_t`. +* The `number` wrappers around those types: `number >`, `number >`, `number`, `number`. + +It's also possible to access the underlying `mpf_t` via the data() member function of `gmp_float`. + +Things you should know when using this type: + +* A default constructed `mpfr_float_backend` is set to a NaN (this is the default [mpfr] behavior). +* All operations use round to nearest. +* No changes are made to [gmp] or [mpfr] global settings, so this type can coexist with existing +[mpfr] or [gmp] code. +* The code can equally use [mpir] in place of [gmp] - indeed that is the preferred option on Win32. +* This backend supports rvalue-references and is move-aware, making instantiations of `number` on this backend move aware. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be interpreted +as a valid floating point number. +* Division by zero results in an infinity. + +[h5 [mpfr] example:] + +[mpfr_eg] + +[endsect] + +[section:fp_eg Examples] + +[import ../example/floating_point_examples.cpp] + +[section:aos Area of Circle] + +[AOS1] +[AOS2] +[AOS3] + +[endsect] + +[section:jel Defining a Lambda Function.] + +[JEL] + +[endsect] + +[section:nd Calculating a Derivative] + +[ND1] +[ND2] +[ND3] + +[endsect] + +[section:gi Calculating an Integral] + +[GI1] +[GI2] + +[endsect] + +[section:poly_eg Polynomial Evaluation] + +[POLY] + +[endsect] + +[endsect] + +[endsect] + +[section:rational Rational Number Types] + +The following back-ends provide rational number arithmetic: + +[table +[[Backend Type][Header][Radix][Dependencies][Pros][Cons]] +[[`cpp_rational`][boost/multiprecision/cpp_int.hpp][2][None][An all C++ Boost-licensed implementation.][Slower than [gmp].]] +[[`gmp_rational`][boost/multiprecision/gmp.hpp][2][[gmp]][Very fast and efficient back-end.][Dependency on GNU licensed [gmp] library.]] +[[`tommath_rational`][boost/multiprecision/tommath.hpp][2][[tommath]][All C/C++ implementation that's Boost Software Licence compatible.][Slower than [gmp].]] +[[`rational_adapter`][boost/multiprecision/rational_adapter.hpp][N/A][none][All C++ adapter that allows any integer back-end type to be used as a rational type.][Requires an underlying integer back-end type.]] +[[`boost::rational`][boost/rational.hpp][N/A][None][A C++ rational number type that can used with any `number` integer type.][The expression templates used by `number` end up being "hidden" inside `boost::rational`: performance may well suffer as a result.]] +] + +[section:cpp_rational cpp_rational] + +`#include ` + + namespace boost{ namespace multiprecision{ + + typedef rational_adapter > cpp_rational_backend; + + typedef number cpp_rational; + + }} // namespaces + +The `cpp_rational_backend` type is used via the typedef `boost::multiprecision::cpp_rational`. It provides +a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. + +As well as the usual conversions from arithmetic and string types, instances of `cpp_rational` are copy constructible +and assignable from type `cpp_int`. + +There is also a two argument constructor that accepts a numerator and denominator: both of type `cpp_int`. + +There are also non-member functions: + + cpp_int numerator(const cpp_rational&); + cpp_int denominator(const cpp_rational&); + +which return the numerator and denominator of the number. + +Things you should know when using this type: + +* Default constructed `cpp_rational`s have the value zero. +* Division by zero results in a `std::overflow_error` being thrown. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be +interpreted as a valid rational number. + +[h5 Example:] + +[cpp_rational_eg] + +[endsect] + +[section:gmp_rational gmp_rational] + +`#include ` + + namespace boost{ namespace multiprecision{ + + class gmp_rational; + + typedef number mpq_rational; + + }} // namespaces + +The `gmp_rational` back-end is used via the typedef `boost::multiprecision::mpq_rational`. It acts as a thin wrapper around the [gmp] `mpq_t` +to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. + +As well as the usual conversions from arithmetic and string types, instances of `number` are copy constructible +and assignable from: + +* The [gmp] native types: `mpz_t`, `mpq_t`. +* `number`. + +There is also a two-argument constructor that accepts a numerator and denominator (both of type `number`). + +There are also non-member functions: + + mpz_int numerator(const mpq_rational&); + mpz_int denominator(const mpq_rational&); + +which return the numerator and denominator of the number. + +It's also possible to access the underlying `mpq_t` via the `data()` member function of `mpq_rational`. + +Things you should know when using this type: + +* Default constructed `mpq_rational`s have the value zero (this is the [gmp] default behavior). +* Division by zero results in a `std::overflow_error` being thrown. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be +interpreted as a valid rational number. +* No changes are made to the [gmp] library's global settings, so this type can coexist with existing +[gmp] code. +* The code can equally be used with [mpir] as the underlying library - indeed that is the preferred option on Win32. + +[h5 Example:] + +[mpq_eg] + +[endsect] + +[section:tommath_rational tommath_rational] + +`#include ` + + namespace boost{ namespace multiprecision{ + + typedef rational_adpater tommath_rational; + typedef number tom_rational; + + }} // namespaces + +The `tommath_rational` back-end is used via the typedef `boost::multiprecision::tom_rational`. It acts as a thin wrapper around +`boost::rational` +to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. + +The advantage of using this type rather than `boost::rational` directly, is that it is expression-template enabled, +greatly reducing the number of temporaries created in complex expressions. + +There are also non-member functions: + + tom_int numerator(const tom_rational&); + tom_int denominator(const tom_rational&); + +which return the numerator and denominator of the number. + +Things you should know when using this type: + +* Default constructed `tom_rational`s have the value zero (this the inherited Boost.Rational behavior). +* Division by zero results in a `std::overflow_error` being thrown. +* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be +interpreted as a valid rational number. +* No changes are made to [tommath]'s global state, so this type can safely coexist with other [tommath] code. +* Performance of this type has been found to be pretty poor - this need further investigation - but it appears that Boost.Rational +needs some improvement in this area. + +[h5 Example:] + +[mp_rat_eg] + +[endsect] + +[section:br Use With Boost.Rational] + +All of the integer types in this library can be used as template arguments to `boost::rational`. + +Note that using the library in this way largely negates the effect of the expression templates in `number`. + +[endsect] + +[section:rational_adapter rational_adapter] + + namespace boost{ namespace multiprecision{ + + template + class rational_adpater; + + }} + +The class template `rational_adapter` is a back-end for `number` which converts any existing integer back-end +into a rational-number back-end. + +So for example, given an integer back-end type `MyIntegerBackend`, the use would be something like: + + typedef number MyInt; + typedef number > MyRational; + + MyRational r = 2; + r /= 3; + MyInt i = numerator(r); + assert(i == 2); + +[endsect] + +[endsect] + +[section:conversions Constructing and Interconverting Between Number Types] + +All of the number types that are based on `number` have certain conversion rules in common. +In particular: + +* Any number type can be constructed (or assigned) from any builtin arithmetic type, as long + as the conversion isn't lossy (for example float to int conversion): + + cpp_dec_float_50 df(0.5); // OK construction from double + cpp_int i(450); // OK constructs from signed int + cpp_int j = 3.14; // Error, lossy conversion. + +* A number can be explicitly constructed from an arithmetic type, even when the conversion is lossy: + + cpp_int i(3.14); // OK explicit conversion + i = static_cast(3.14) // OK explicit conversion + i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above + i = 3.14; // Error, no implicit assignment operator for lossy conversion. + cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion. + +* A `number` can be converted to any built in type, via the `convert_to` member function: + + mpz_int z(2); + int i = z.template convert_to(); // sets i to 2 + +Additional conversions may be supported by particular backends. + +* A `number` can be converted to any built in type, via an explicit conversion operator: +this functionality is only available on compilers supporting C++11's explicit conversion syntax. + + mpz_int z(2); + int i = z; // Error, implicit conversion not allowed. + int j = static_cast(z); // OK explicit conversion. + +* Any number type can be ['explicitly] constructed (or assigned) from a `const char*` or a `std::string`: + + // pi to 50 places from a string: + cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510"); + // Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly: + cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000"); + // Invalid input always results in a std::runtime_error being thrown: + i = static_cast("3.14"); + // implicit conversions from strings are not allowed: + i = "23"; // Error, no assignment operator for implicit conversion from string + // assign member function, avoids having to create a temporary via a static_cast: + i.assign("23"); // OK + +* Any number type will interoperate with the builtin types in arithmetic expressions as long as the conversions +are not lossy: + + // pi to 50 places from a string: + cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; + // Multiply by 2 - using an integer literal here is usually more efficient + // than constructing a temporary: + df *= 2; + + // You can't mix integer types with floats though: + cpp_int i = 2; + i *= 3.14; // Error, no *= operator will be found. + +* Any number type can be streamed to and from the C++ iostreams: + + + cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; + // Now print at full precision: + std::cout << std::setprecision(std::numeric_limits::max_digits10) + << df << std::endl + cpp_int i = 1; + i <<= 256; + // Now print in hex format with prefix: + std::cout << std::hex << std::showbase << i << std::endl; + +* Interconversions between number types of the same family are allowed and are implicit conversions if no +loss of precision is involved, and explicit if it is: + + int128_t i128 = 0; + int266_t i256 = i128; // OK implicit widening conversion + i128_t = i256; // Error, no assignment operator found, narrowing conversion is explict + i128_t = static_cast(i256); // OK, explicit narrowing conversion + + mpz_int z = 0; + mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit + + mpf_float_50 f50 = 2; + f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision. + f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required. + +* Some interconversions between number types are completely generic, and are always available, albeit the conversions are always ['explicit]: + + cpp_int cppi(2); + // We can always convert between numbers of the same category - + // int to int, rational to rational, or float to float, so this is OK + // as long as we use an explicit conversion: + mpz_int z(cppi); + // We can always promote from int to rational, int to float, or rational to float: + cpp_rational cppr(cppi); // OK, int to rational + cpp_dec_float_50 df(cppi); // OK, int to float + df = static_cast(cppr); // OK, explicit rational to float conversion + // However narrowing and/or implicit conversions always fail: + cppi = df; // Compiler error, conversion not allowed + +* Other interconversions may be allowed as special cases, whenever the backend allows it: + + mpf_t m; // Native GMP type. + mpf_init_set_ui(m, 0); // set to a value; + mpf_float i(m); // copies the value of the native type. + +More information on what additional types a backend supports conversions from are given in the tutorial for each backend. +The converting constructor will be implict if the backend's converting constructor is also implicit, and explicit if the +backends converting constructor is also explicit. + +[endsect] + +[section:random Generating Random Numbers] + +Random numbers are generated in conjunction with Boost.Random. However, since Boost.Random is unaware +of [@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] numbers, it's necessary to include the header: + + #include + +In order to act as a bridge between the two libraries. + +Integers with /N/ random bits are generated using `independent_bits_engine`: + +[random_eg1] + +Alternatively we can generate integers in a given range using `uniform_int_distribution`, this will +invoke the underlying engine multiple times to build up the required number of bits in the result: + +[random_eg2] + +Floating point values in \[0,1) are generated using `uniform_01`, the trick here is to ensure +that the underlying generator produces as many random bits as there are digits in the floating +point type. As above `independent_bits_engine` can be used for this purpose, note that we also have to +convert decimal digits (in the floating point type) to bits (in the random number generator): + +[random_eg3] + +Finally, we can modify the above example to produce numbers distributed according to some distribution: + +[random_eg4] + +[endsect] + +[section:primetest Primality Testing] + +The library implements a Miller-Rabin test for primality: + + #include + + template + bool miller_rabin_test(const number& n, unsigned trials, Engine& gen); + + template + bool miller_rabin_test(const number& n, unsigned trials); + +These functions perform a Miller-Rabin test for primality, if the result is `false` then /n/ is definitely composite, +while if the result is `true` then /n/ is prime with probability ['0.25^trials]. The algorithm used performs some +trial divisions to exclude small prime factors, does one Fermat test to exclude many more composites, and then +uses the Miller-Rabin algorithm straight out of +Knuth Vol 2, which recommends 25 trials for a pretty strong likelihood that /n/ is prime. + +The third optional argument is for a Uniform Random Number Generator from Boost.Random. When not provided the `mt19937` +generator is used. Note that when producing random primes then you should probably use a different random number generator +to produce candidate prime numbers for testing, than is used internally by `miller_rabin_test` for determining +whether the value is prime. It also helps of course to seed the generators with some source of randomness. + +The following example searches for a prime `p` for which `(p-1)/2` is also probably prime: + +[safe_prime] + +[endsect] + +[section:lits Literal Types and `constexpr` Support] + +There is limited support for `constexpr` in the library, currently the `number` front end supports `constexpr` +on default construction and all forwarding constructors, but not on any of the non-member operators. So if +some type `B` is a literal type, then `number` is also a literal type, and you will be able to +compile-time-construct such a type from any literal that `B` is compile-time-constructible from. +However, you will not be able to perform compile-time arithmetic on such types. + +Currently the only backend type provided by the library that is also a literal type are instantiations +of `cpp_int_backend` where the Allocator parameter is type `void`, and the Checked parameter is +`boost::multiprecision::unchecked`. + +For example: + + using namespace boost::multiprecision; + + constexpr int128_t i = 0; // OK, fixed precision int128_t has no allocator. + constexpr uint1024_t j = 0xFFFFFFFF00000000uLL; // OK, fixed precision uint1024_t has no allocator. + + constexpr checked_uint128_t k = -1; // Error, checked type is not a literal type as we need runtime error checking. + constexpr cpp_int l = 2; // Error, type is not a literal as it performs memory management. + +[endsect] + +[section:rounding Rounding Rules for Conversions] + +As a general rule, all conversions between unrelated types are performed using basic arithmetic operations, therefore +conversions are either exact, or follow the same rounding rules as arithmetic for the type in question. + +The following table summarises the situation for conversions from native types: + +[table +[[Backend][Rounding Rules]] +[[__cpp_int][Conversions from integer types are exact if the target has sufficient precision, otherwise they + truncate to the first 2^MaxBits bits (modulo arithmetic). Conversions from floating point types + are truncating to the nearest integer.]] +[[__gmp_int][Conversions are performed by the GMP library except for conversion from `long double` which is truncating.]] +[[__tom_int][Conversions from floating point types are truncating, all others are performed by libtommath and are exact.]] +[[__gmp_float][Conversions are performed by the GMP library except for conversion from `long double` which should be exact + provided the target type has as much precision as a `long double`.]] +[[__mpfr_float_backend][All conversions are performed by the underlying MPFR library.]] +[[__cpp_dec_float][All conversions are performed using basic arithmetic operations and are truncating.]] +[[__gmp_rational][See __gmp_int]] +[[__cpp_rational][See __cpp_int]] +[[__tommath_rational][See __tom_int]] +] + +[endsect] + +[section:mixed Mixed Precision Arithmetic] + +Mixed precision arithmetic is fully supported by the library, there are two different forms: + +* Where the operands are of different precision. +* Where the operands are of the same precision, but yield a higher precision result. + +[h4 Mixing Operands of Differing Precision] + +If the arguments to a binary operator are of different precision, then the operation is allowed +as long as there is an unambiguous implicit conversion from one argument type to the other. +In all cases the arithmetic is performed "as if" the lower precision type is promoted to the +higher precision type before applying the operator. However, particular backends may optimise +this and avoid actually creating a temporary if they are able to do so. + +For example: + + mpfr_float_50 a(2), b; + mpfr_float_100 c(3), d; + static_mpfr_float_50 e(5), f; + mpz_int i(20); + + d = a * c; // OK, result of operand is an mpfr_float_100. + b = a * c; // Error, can't convert the result to an mpfr_float_50 as it will lose digits. + f = a * e; // Error, operator is ambiguous, result could be of either type. + f = e * i; // OK, unambiguous conversion from mpz_int to static_mpfr_float_50 + +[h4 Operands of the Same Precision] + +Sometimes you want to apply an operator to two arguments of the same precision in +such a way as to obtain a result of higher precision. The most common situation +occurs with fixed precision integers, where you want to multiply two N-bit numbers +to obtain a 2N-bit result. This is supported in this library by the following +free functions: + + template + ResultType& add(ResultType& result, const Source1& a, const Source2& b); + + template + ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); + + template + ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); + +These functions apply the named operator to the arguments ['a] and ['b] and store the +result in ['result], returning ['result]. In all cases they behave "as if" +arguments ['a] and ['b] were first promoted to type `ResultType` before applying the +operator, though particular backends may well avoid that step by way of an optimization. + +The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2` +may be either instances of class `number` or native integer types. The latter is an optimization +that allows arithmetic to be performed on native integer types producing an extended precision result. + +For example: + +[mixed_eg] + +Produces the output: + +[mixed_output] + +[h4 Backends With Optimized Mixed Precision Arithmetic] + +The following backends have at least some direct support for mixed precision arithmetic, +and therefore avoid creating unnecessary temporaries when using the interfaces above. +Therefore when using these types it's more efficient to use mixed precision arithmetic, +than it is to explicitly cast the operands to the result type: + +__mpfr_float_backend, __mpf_float, __cpp_int. + +[endsect] + +[endsect] + +[section:ref Reference] + +[section:number number] + +[h4 Synopsis] + + namespace boost{ namespace multiprecision{ + + enum expression_template_option { et_on = 1, et_off = 0 }; + + template struct expression_template_default + { static const expression_template_option value = et_on; }; + + template ::value> + class number + { + number(); + number(see-below); + number& operator=(see-below); + number& assign(see-below); + + // Member operators + number& operator+=(const ``['see-below]``&); + number& operator-=(const ``['see-below]``&); + number& operator*=(const ``['see-below]``&); + number& operator/=(const ``['see-below]``&); + number& operator++(); + number& operator--(); + number operator++(int); + number operator--(int); + + number& operator%=(const ``['see-below]``&); + number& operator&=(const ``['see-below]``&); + number& operator|=(const ``['see-below]``&); + number& operator^=(const ``['see-below]``&); + number& operator<<=(const ``['integer-type]``&); + number& operator>>=(const ``['integer-type]``&); + + // Use in Boolean context: + operator ``['convertible-to-bool-type]``()const; + // swap: + void swap(number& other); + // Sign: + bool is_zero()const; + int sign()const; + // string conversion: + std::string str()const; + // Generic conversion mechanism + template + T convert_to()const; + template + explicit operator T ()const; + // precision control: + static unsigned default_precision(); + static void default_precision(unsigned digits10); + unsigned precision()const; + void precision(unsigned digits10); + // Comparison: + int compare(const number& o)const; + template + typename enable_if >, int>::type + compare(const V& o)const; + // Access to the underlying implementation: + Backend& backend(); + const Backend& backend()const; + }; + + // Non member operators: + ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&); + // Integer only operations: + ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&); + ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&); + // Comparison operators: + bool operator==(const ``['see-below]``&, const ``['see-below]``&); + bool operator!=(const ``['see-below]``&, const ``['see-below]``&); + bool operator< (const ``['see-below]``&, const ``['see-below]``&); + bool operator> (const ``['see-below]``&, const ``['see-below]``&); + bool operator<=(const ``['see-below]``&, const ``['see-below]``&); + bool operator>=(const ``['see-below]``&, const ``['see-below]``&); + + // Swap: + template + void swap(number& a, number& b); + + // iostream support: + template + std::ostream& operator << (std::ostream& os, const number& r); + std::ostream& operator << (std::ostream& os, const ``['unmentionable-expression-template-type]``& r); + template + std::istream& operator >> (std::istream& is, number& r); + + // Arithmetic with a higher precision result: + template + ResultType& add(ResultType& result, const Source1& a, const Source2& b); + template + ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); + template + ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); + + // Non-member function standard library support: + ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` lround (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` llround(const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&); + + ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, int); + ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, int*); + ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + + // Traits support: + template + struct component_type; + template + struct number_category; + template + struct is_number; + template + struct is_number_expression; + + // Integer specific functions: + ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``&, unsigned); + ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m); + template + void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y, + number& q, number& r); + template + Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val); + unsigned lsb(const ``['number-or-expression-template-type]``& x); + template + bool bit_test(const number& val, unsigned index); + template + number& bit_set(number& val, unsigned index); + template + number& bit_unset(number& val, unsigned index); + template + number& bit_flip(number& val, unsigned index); + template + bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen); + bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials); + + // Rational number support: + typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); + + }} // namespaces + + namespace boost{ namespace math{ + + // Boost.Math interoperability functions: + int fpclassify (const ``['number-or-expression-template-type]``&, int); + bool isfinite (const ``['number-or-expression-template-type]``&, int); + bool isnan (const ``['number-or-expression-template-type]``&, int); + bool isinf (const ``['number-or-expression-template-type]``&, int); + bool isnormal (const ``['number-or-expression-template-type]``&, int); + + }} // namespaces + + // numeric_limits support: + namespace std{ + + template + struct numeric_limits > + { + /* Usual members here */ + }; + + } + +[h4 Description] + + enum expression_template_option { et_on = 1, et_off = 0 }; + +This enumerated type is used to specify whether expression templates are turned on (et_on) or turned off (et_off). + + template struct expression_template_default + { static const expression_template_option value = et_on; }; + +This traits class specifies the default expression template option to be used with a particular Backend type. +It defaults to `et_on`. + + template ::value> + class number; + +Class `number` has two template arguments: + +[variablelist +[[Backend][The actual arithmetic back-end that does all the work.]] +[[ExpressionTemplates][A Boolean value: when `et_on`, then expression templates are enabled, otherwise when set to `et_off` they are disabled. + The default for this parameter is computed via the traits class `expression_template_default` whose member `value` defaults to `et_on` unless + the the traits class is specialized for a particular backend.]] +] + + number(); + number(see-below); + number& operator=(see-below); + number& assign(see-below); + +Type `number` is default constructible, and both copy constructible and assignable from: + +* Itself. +* An expression template which is the result of one of the arithmetic operators. +* Any builtin arithmetic type, as long as the result would not be lossy (for example float to integer conversion). +* Any type that the Backend is implicitly constructible or assignable from. +* An rvalue reference to another `number`. Move-semantics are used for construction if the backend also +supports rvalue reference construction. In the case of assignment, move semantics are always supported +when the argument is an rvalue reference irrespective of the backend. +* Any type in the same family, as long as no loss of precision is involved. For example from `int128_t` to `int256_t`, +or `cpp_dec_float_50` to `cpp_dec_float_100`. + +Type `number` is explicitly constructible from: + +* Any type mentioned above. +* A `std::string` or any type which is convertible to `const char*`. +* Any arithmetic type (including those that would result in lossy conversions). +* Any type in the same family, including those that result in loss of precision. +* Any type that the Backend is explicitly constructible from. +* Any pair of types for which a generic interconversion exists: that is from integer to integer, integer +to rational, integer to float, rational to rational, rational to float, or float to float. + +The assign member function is available for any type for which an explicit converting constructor exists. +It is intended to be used where a temporary generated from an explicit assignment would be expensive, for example: + + mpfr_float_50 f50; + mpfr_float_100 f100; + + f50 = static_cast(f100); // explicit cast create a temporary + f50.assign(f100); // explicit call to assign create no temporary + +In addition, if the type has multiple components (for example rational or complex number types), then there is a +two argument constructor: + + number(arg1, arg2); + +Where the two args must either be arithmetic types, or types that are convertible to the two components of `this`. + + number& operator+=(const ``['see-below]``&); + number& operator-=(const ``['see-below]``&); + number& operator*=(const ``['see-below]``&); + number& operator/=(const ``['see-below]``&); + number& operator++(); + number& operator--(); + number operator++(int); + number operator--(int); + // Integer only operations: + number& operator%=(const ``['see-below]``&); + number& operator&=(const ``['see-below]``&); + number& operator|=(const ``['see-below]``&); + number& operator^=(const ``['see-below]``&); + number& operator<<=(const ``['integer-type]``&); + number& operator>>=(const ``['integer-type]``&); + +These operators all take their usual arithmetic meanings. + +The arguments to these operators is either: + +* Another `number`. +* An expression template derived from `number`. +* Any type implicitly convertible to `number`, including some other instance of class `number`. + +For the left and right shift operations, the argument must be a builtin +integer type with a positive value (negative values result in a `std::runtime_error` being thrown). + + operator ``['convertible-to-bool-type]``()const; + +Returns an ['unmentionable-type] that is usable in Boolean contexts (this allows `number` to be used in any +Boolean context - if statements, conditional statements, or as an argument to a logical operator - without +type `number` being convertible to type `bool`. + +This operator also enables the use of `number` with any of the following operators: +`!`, `||`, `&&` and `?:`. + + void swap(number& other); + +Swaps `*this` with `other`. + + bool is_zero()const; + +Returns `true` is `*this` is zero, otherwise `false`. + + int sign()const; + +Returns a value less than zero if `*this` is negative, a value greater than zero if `*this` is positive, and zero +if `*this` is zero. + + std::string str(unsigned precision, bool scientific = true)const; + +Returns the number formatted as a string, with at least /precision/ digits, and in scientific format +if /scientific/ is true. + + template + T convert_to()const; + + template + explicit operator T ()const; + +Provides a generic conversion mechanism to convert `*this` to type `T`. Type `T` may be any arithmetic type. +Optionally other types may also be supported by specific `Backend` types. + + + static unsigned default_precision(); + static void default_precision(unsigned digits10); + unsigned precision()const; + void precision(unsigned digits10); + +These functions are only available if the Backend template parameter supports runtime changes to precision. They get and set +the default precision and the precision of `*this` respectively. + + int compare(const number& o)const; + template + typename enable_if >, int>::type + compare(const V& other)const; + +Returns: + +* A value less that 0 for `*this < other` +* A value greater that 0 for `*this > other` +* Zero for `*this == other` + + Backend& backend(); + const Backend& backend()const; + +Returns the underlying back-end instance used by `*this`. + +[h4 Non-member operators] + + // Non member operators: + ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator+(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator-(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator*(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator/(const ``['see-below]``&, const ``['see-below]``&); + // Integer only operations: + ``['unmentionable-expression-template-type]`` operator%(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator&(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator|(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator^(const ``['see-below]``&, const ``['see-below]``&); + ``['unmentionable-expression-template-type]`` operator<<(const ``['see-below]``&, const ``['integer-type]``&); + ``['unmentionable-expression-template-type]`` operator>>(const ``['see-below]``&, const ``['integer-type]``&); + // Comparison operators: + bool operator==(const ``['see-below]``&, const ``['see-below]``&); + bool operator!=(const ``['see-below]``&, const ``['see-below]``&); + bool operator< (const ``['see-below]``&, const ``['see-below]``&); + bool operator> (const ``['see-below]``&, const ``['see-below]``&); + bool operator<=(const ``['see-below]``&, const ``['see-below]``&); + bool operator>=(const ``['see-below]``&, const ``['see-below]``&); + +These operators all take their usual arithmetic meanings. + +The arguments to these functions must contain at least one of the following: + +* A `number`. +* An expression template type derived from `number`. +* Any type for which `number` has an implicit constructor - for example a builtin arithmetic type. + +The return type of these operators is either: + +* An ['unmentionable-type] expression template type when `ExpressionTemplates` is `true`. +* Type `number` when `ExpressionTemplates` is `false`. +* Type `bool` if the operator is a comparison operator. + +Finally note that the second argument to the left and right shift operations must be a builtin integer type, +and that the argument must be positive (negative arguments result in a `std::runtime_error` being thrown). + +[h4 swap] + + template + void swap(number& a, number& b); + +Swaps `a` and `b`. + +[h4 Iostream Support] + + template + std::ostream& operator << (std::ostream& os, const number& r); + template + std::ostream& operator << (std::ostream& os, const unmentionable-expression-template& r); + template + inline std::istream& operator >> (std::istream& is, number& r) + +These operators provided formatted input-output operations on `number` types, and expression templates derived from them. + +It's down to the back-end type to actually implement string conversion. However, the back-ends provided with +this library support all of the iostream formatting flags, field width and precision settings. + +[h4 Arithmetic with a higher precision result] + + template + ResultType& add(ResultType& result, const Source1& a, const Source2& b); + + template + ResultType& subtract(ResultType& result, const Source1& a, const Source2& b); + + template + ResultType& multiply(ResultType& result, const Source1& a, const Source2& b); + +These functions apply the named operator to the arguments ['a] and ['b] and store the +result in ['result], returning ['result]. In all cases they behave "as if" +arguments ['a] and ['b] were first promoted to type `ResultType` before applying the +operator, though particular backends may well avoid that step by way of an optimization. + +The type `ResultType` must be an instance of class `number`, and the types `Source1` and `Source2` +may be either instances of class `number` or native integer types. The latter is an optimization +that allows arithmetic to be performed on native integer types producing an extended precision result. + +[h4 Non-member standard library function support] + + ``['unmentionable-expression-template-type]`` abs (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` fabs (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sqrt (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` floor (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` ceil (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` trunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` itrunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` ltrunc (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` lltrunc(const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` round (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` iround (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` lround (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` llround(const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` exp (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` log (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` log10 (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` cos (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sin (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` tan (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` acos (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` asin (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` atan (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` cosh (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` sinh (const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` tanh (const ``['number-or-expression-template-type]``&); + + ``['unmentionable-expression-template-type]`` ldexp (const ``['number-or-expression-template-type]``&, int); + ``['unmentionable-expression-template-type]`` frexp (const ``['number-or-expression-template-type]``&, int*); + ``['unmentionable-expression-template-type]`` pow (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` fmod (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + ``['unmentionable-expression-template-type]`` atan2 (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&); + +These functions all behave exactly as their standard library C++11 counterparts do: their argument is either an instance of `number` or +an expression template derived from it; If the argument is of type `number` then that is also the return type, +otherwise the return type is an expression template. + +These functions are normally implemented by the Backend type. However, default versions are provided for Backend types that +don't have native support for these functions. Please note however, that this default support requires the precision of the type +to be a compile time constant - this means for example that the [gmp] MPF Backend will not work with these functions when that type is +used at variable precision. + +Also note that with the exception of `abs` that these functions can only be used with floating-point Backend types (if any other types +such as fixed precision or complex types are added to the library later, then these functions may be extended to support those number types). + +The precision of these functions is generally deterimined by the backend implementation. For example the precision +of these functions when used with __mpfr_float_backend is determined entirely by [mpfr]. When these functions use our own +implementations, the accuracy of the transcendal functions is generally a few epsilon. Note however, that the trigonmetrical +functions incur the usual accuracy loss when reducing arguments by large multiples of [pi]. Also note that both __mpf_float +and __cpp_dec_float have a number of guard digits beyond their stated precision, so the error rates listed for these +are in some sense artificially low. + +The following table shows the error rates we observe for these functions with various backend types, functions not listed +here are exact (tested on Win32 with VC++10, MPFR-3.0.0, MPIR-2.1.1): + +[table +[[Function][mpfr_float_50][mpf_float_50][cpp_dec_float_50]] +[[sqrt][1eps][0eps][0eps]] +[[exp][1eps][0eps][0eps]] +[[log][1eps][0eps][0eps]] +[[log10][1eps][0eps][0eps]] +[[cos][700eps][0eps][0eps]] +[[sin][1eps][0eps][0eps]] +[[tan][0eps][0eps][0eps]] +[[acos][0eps][0eps][0eps]] +[[asin][0eps][0eps][0eps]] +[[atan][1eps][0eps][0eps]] +[[cosh][1045eps[footnote It's likely that the inherent error in the input values to our test cases are to blame here.]][0eps][0eps]] +[[sinh][2eps][0eps][0eps]] +[[tanh][1eps][0eps][0eps]] +[[pow][0eps][4eps][3eps]] +[[atan2][1eps][0eps][0eps]] +] +[h4 Traits Class Support] + + template + struct component_type; + +If this is a type with multiple components (for example rational or complex types), then this trait has a single member +`type` that is the type of those components. + + template + struct number_category; + +A traits class that inherits from `mpl::int_` where `N` is one of the enumerated values `number_kind_integer`, `number_kind_floating_point`, +`number_kind_rational`, `number_kind_fixed_point`, or `number_kind_unknown`. This traits class is specialized for any type that has +`std::numeric_limits` support as well as for classes in this library: which means it can be used for generic code that must work +with built in arithmetic types as well as multiprecision ones. + + template + struct is_number; + +A traits class that inherits from `mpl::true_` if T is an instance of `number<>`, otherwise from `mpl::false_`. + + template + struct is_number_expression; + +A traits class that inherits from `mpl::true_` if T is an expression template type derived from `number<>`, otherwise from `mpl::false_`. + + + +[h4 Integer functions] + +In addition to functioning with types from this library, these functions are also overloaded for built in integer +types if you include ``. Further, when used with fixed precision types (whether +built in integers or multiprecision ones), the functions will promote to a wider type internally when the algorithm +requires it. Versions overloaded for built in integer types return that integer type rather than an expression +template. + + ``['unmentionable-expression-template-type]`` pow(const ``['number-or-expression-template-type]``& b, unsigned p); + +Returns ['b[super p]] as an expression template. Note that this function should be used with extreme care as the result can grow so +large as to take "effectively forever" to compute, or else simply run the host machine out of memory. This is the one function in +this category that is not overloaded for built in integer types, further, it's probably not a good idea to use it with +fixed precision `cpp_int`'s either. + + ``['unmentionable-expression-template-type]`` powm(const ``['number-or-expression-template-type]``& b, const ``['number-or-expression-template-type]``& p, const ``['number-or-expression-template-type]``& m); + +Returns ['b[super p] mod m] as an expression template. Fixed precision types are promoted internally to ensure accuracy. + + template + void divide_qr(const ``['number-or-expression-template-type]``& x, const ``['number-or-expression-template-type]``& y, + number& q, number& r); + +Divides x by y and returns both the quotient and remainder. After the call `q = x / y` and `r = x % y`. + + template + Integer integer_modulus(const ``['number-or-expression-template-type]``& x, Integer val); + +Returns the absolute value of `x % val`. + + unsigned lsb(const ``['number-or-expression-template-type]``& x); + +Returns the index of the least significant bit that is set to 1. + +Throws a `std::range_error` if the argument is <= 0. + + template + bool bit_test(const number& val, unsigned index); + +Returns `true` if the bit at /index/ in /val/ is set. + + template + number& bit_set(number& val, unsigned index); + +Sets the bit at /index/ in /val/, and returns /val/. + + template + number& bit_unset(number& val, unsigned index); + +Unsets the bit at /index/ in /val/, and returns /val/. + + template + number& bit_flip(number& val, unsigned index); + +Flips the bit at /index/ in /val/, and returns /val/. + + template + bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials, Engine& gen); + bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials); + +Tests to see if the number /n/ is probably prime - the test excludes the vast majority of composite numbers +by excluding small prime factors and performing a single Fermat test. Then performs /trials/ Miller-Rabin +tests. Returns `false` if /n/ is definitely composite, or `true` if /n/ is probably prime with the +probability of it being composite less than 0.25^trials. Fixed precision types are promoted internally +to ensure accuracy. + +[h4 Rational Number Functions] + + typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); + +These functions return the numerator and denominator of a rational number respectively. + +[h4 Boost.Math Interoperability Support] + + namespace boost{ namespace math{ + + int fpclassify (const ``['number-or-expression-template-type]``&, int); + bool isfinite (const ``['number-or-expression-template-type]``&, int); + bool isnan (const ``['number-or-expression-template-type]``&, int); + bool isinf (const ``['number-or-expression-template-type]``&, int); + bool isnormal (const ``['number-or-expression-template-type]``&, int); + + }} // namespaces + +These floating-point classification functions behave exactly as their Boost.Math equivalents. + +Other Boost.Math functions and templates may also be +specialized or overloaded to ensure interoperability. + +[h4 std::numeric_limits support] + + namespace std{ + + template + struct numeric_limits > + { + /* Usual members here */ + }; + + } + +Class template `std::numeric_limits` is specialized for all instantiations of `number` whose precision is known at compile time, plus those +types whose precision is unlimited (though it is much less useful in those cases). It is not specialized for types +whose precision can vary at compile time (such as `mpf_float`). + +[endsect] + +[section:cpp_int_ref cpp_int] + + namespace boost{ namespace multiprecision{ + + typedef unspecified-type limb_type; + + enum cpp_integer_type { signed_magnitude, unsigned_magnitude }; + enum cpp_int_check_type { checked, unchecked }; + + template > + class cpp_int_backend; + // + // Expression templates default to et_off if there is no allocator: + // + template + struct expression_template_default > + { static const expression_template_option value = et_off; }; + + typedef number > cpp_int; // arbitrary precision integer + typedef rational_adapter > cpp_rational_backend; + typedef number cpp_rational; // arbitrary precision rational number + + // Fixed precision unsigned types: + typedef number > uint128_t; + typedef number > uint256_t; + typedef number > uint512_t; + typedef number > uint1024_t; + + // Fixed precision signed types: + typedef number > int128_t; + typedef number > int256_t; + typedef number > int512_t; + typedef number > int1024_t; + + // Over again, but with checking enabled this time: + typedef number > checked_cpp_int; + typedef rational_adapter > checked_cpp_rational_backend; + typedef number checked_cpp_rational; + + // Checked fixed precision unsigned types: + typedef number > checked_uint128_t; + typedef number > checked_uint256_t; + typedef number > checked_uint512_t; + typedef number > checked_uint1024_t; + + // Fixed precision signed types: + typedef number > checked_int128_t; + typedef number > checked_int256_t; + typedef number > checked_int512_t; + typedef number > checked_int1024_t; + + }} // namespaces + +Class template `cpp_int_backend` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The template arguments are: + +[variablelist +[[MinBits][Determines the number of Bits to store directly within the object before resorting to dynamic memory + allocation. When zero, this field is determined automatically based on how many bits can be stored + in union with the dynamic storage header: setting a larger value may improve performance as larger integer + values will be stored internally before memory allocation is required.]] +[[MaxBits][Determines the maximum number of bits to be stored in the type: resulting in a fixed precision type. + When this value is the same as MinBits, then the Allocator parameter is ignored, as no dynamic + memory allocation will ever be performed: in this situation the Allocator parameter should be set to + type `void`. Note that this parameter should not be used simply to prevent large memory + allocations, not only is that role better performed by the allocator, but fixed precision + integers have a tendency to allocate all of MaxBits of storage more often than one would expect.]] +[[SignType][Determines whether the resulting type is signed or not. Note that for +[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision] types + this parameter must be `signed_magnitude`. For fixed precision + types then this type may be either `signed_magnitude` or `unsigned_magnitude`.]] +[[Checked][This parameter has two values: `checked` or `unchecked`. See the [link boost_multiprecision.tut.ints.cpp_int tutorial] for more information.]] +[[Allocator][The allocator to use for dynamic memory allocation, or type `void` if MaxBits == MinBits.]] +] + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.ints.cpp_int tutorial]. + +[endsect] + +[section:gmp_int_ref gmp_int] + + namespace boost{ namespace multiprecision{ + + class gmp_int; + + typedef number mpz_int; + + }} // namespaces + +Class template `gmp_int` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.ints.gmp_int tutorial]. + +[endsect] + +[section:tom_int_ref tom_int] + + namespace boost{ namespace multiprecision{ + + class tommath_int; + + typedef number tom_int; + + }} // namespaces + +Class template `tommath_int` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.ints.tom_int tutorial]. + +[endsect] + +[section:mpf_ref gmp_float] + + namespace boost{ namespace multiprecision{ + + template + class gmp_float; + + typedef number > mpf_float_50; + typedef number > mpf_float_100; + typedef number > mpf_float_500; + typedef number > mpf_float_1000; + typedef number > mpf_float; + + }} // namespaces + +Class template `gmp_float` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type +should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision` +and `number::precision`. Note that this type does not in any way change the GMP library's global state (for example +it does not change the default precision of the mpf_t data type), therefore you can safely mix this type with existing +code that uses GMP, and also mix `gmp_float`s of differing precision. + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.floats.gmp_float tutorial]. + +[endsect] + +[section:mpfr_ref mpfr_float_backend] + + namespace boost{ namespace multiprecision{ + + template + class mpfr_float_backend; + + typedef number > mpfr_float_50; + typedef number > mpfr_float_100; + typedef number > mpfr_float_500; + typedef number > mpfr_float_1000; + typedef number > mpfr_float; + + }} // namespaces + +Class template `mpfr_float_backend` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type +should support. When this parameter is zero, then the precision can be set at runtime via `number::default_precision` +and `number::precision`. Note that this type does not in any way change the GMP or MPFR library's global state (for example +it does not change the default precision of the mpfr_t data type), therefore you can safely mix this type with existing +code that uses GMP or MPFR, and also mix `mpfr_float_backend`s of differing precision. + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.floats.mpfr_float tutorial]. + +[endsect] + +[section:cpp_dec_ref cpp_dec_float] + + namespace boost{ namespace multiprecision{ + + template + class cpp_dec_float; + + typedef number > cpp_dec_float_50; + typedef number > cpp_dec_float_100; + + }} // namespaces + +Class template `cpp_dec_float` fulfills all of the requirements for a [link boost_multiprecision.ref.backendconc Backend] type. +Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject +to change. + +The class takes a single template parameter - `Digits10` - which is the number of decimal digits precision the type +should support. Note that this type does not ever perform any dynamic memory allocation, as a result the `Digits10` +template argument should not be set too high or the class's size will grow unreasonably large. + +The type of `number_category >::type` is `mpl::int_`. + +More information on this type can be found in the [link boost_multiprecision.tut.floats.cpp_dec_float tutorial]. + +[endsect] + +[section:internals Internal Support Code] + +There are some traits classes which authors of new backends should be aware of: + + namespace boost{ namespace multiprecision{ namespace detail{ + + template + struct is_explicitly_convertible; + + }}} + +Inherits from `boost::integral_constant` if type `From` has an explicit conversion from `To`. + +For compilers that support C++11 SFINAE-expressions this trait should "just work". Otherwise it inherits +from `boost::is_convertible::type`, and will need to be specialised for Backends that have +constructors marked as `explicit`. + + template + struct is_lossy_conversion + { + static const bool value = see below; + }; + +Member `value` is true if the conversion from `From` to `To` would result in a loss of precision, and `false` otherwise. + +The default version of this trait simply checks whether the ['kind] of conversion (for example from a floating point to an integer type) +is inherently lossy. Note that if either of the types `From` or `To` are of an unknown number category (because `number_category` is not +specialised for that type) then this trait will be `true`. + + template + struct is_restricted_conversion + { + static const bool value = see below; + }; + +Member `value` is `true` if `From` is only explicitly convertible to `To` and not implicitly convertible, or +if `is_lossy_conversion::value` is `true`. Otherwise `false`. + +Note that while this trait is the ultimate arbiter of which constructors are marked as `explicit` in class `number`, +authors of backend types should generally specialise one of the traits above, rather than this one directly. + + template + is_signed_number; + template + is_unsigned_number; + +These two traits inherit from either `mpl::true_` or `mpl::false_`, by default types are assumed to be signed unless +`is_unsigned_number` is specialized for that type. + +[endsect] + +[section:backendconc Backend Requirements] + +The requirements on the `Backend` template argument to `number` are split up into +sections: compulsory and optional. + +Compulsory requirements have no default implementation in the library, therefore if the feature +they implement is to be supported at all, then they must be implemented by the backend. + +Optional requirements have default implementations that are called if the backend doesn't provide +it's own. Typically the backend will implement these to improve performance. + +In the following tables, type B is the `Backend` template argument to `number`, `b` and `b2` are +a variables of type B, `cb`, `cb2` and `cb3` are constant variables of type `const B`, +`rb` is a variable of type `B&&`, `a` and `a2` are variables of Arithmetic type, +`s` is a variable of type `const char*`, `ui` is a variable of type `unsigned`, `bb` is a variable of type `bool`, +`pa` is a variable of type pointer-to-arithmetic-type, `exp` is a variable of type `B::exp_type`, +`pexp` is a variable of type `B::exp_type*`, `i` is a variable of type `int`, `pi` pointer to a variable of type `int`, +B2 is another type that meets these requirements, b2 is a variable +of type B2. + +[table Compulsory Requirements on the Backend type. +[[Expression][Return Type][Comments][Throws]] +[[`B::signed_types`][`mpl::list`][A list of signed integral types that can be assigned to type B. The types shall be + listed in order of size, smallest first, and shall terminate in the type that is `std::intmax_t`.][[space]]] +[[`B::unsigned_types`][`mpl::list`][A list of unsigned integral types that can be assigned to type B. The types shall be + listed in order of size, smallest first, and shall terminate in the type that is `std::uintmax_t`.][[space]]] +[[`B::float_types`][`mpl::list`][A list of floating-point types that can be assigned to type B.The types shall be + listed in order of size, smallest first, and shall terminate in type `long double`.][[space]]] +[[`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]]] +[[`B()`][ ][Default constructor.][[space]]] +[[`B(cb)`][ ][Copy Constructor.][[space]]] +[[`b = b`][`B&`][Assignment operator.][[space]]] +[[`b = a`][`B&`][Assignment from an Arithmetic type. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] +[[`b = s`][`B&`][Assignment from a string.][Throws a `std::runtime_error` if the string could not be interpretted as a valid number.]] +[[`b.swap(b)`][`void`][Swaps the contents of its arguments.][`noexcept`]] +[[`cb.str(ui, bb)`][`std::string`][Returns the string representation of `b` with `ui` digits and in scientific format if `bb` is `true`. + If `ui` is zero, then returns as many digits as are required to reconstruct the original value.][[space]]] +[[`b.negate()`][`void`][Negates `b`.][[space]]] +[[`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 + if `cb == cb2`.][`noexcept`]] +[[`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 + if `cb == a`. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] +[[`eval_add(b, cb)`][`void`][Adds `cb` to `b`.][[space]]] +[[`eval_subtract(b, cb)`][`void`][Subtracts `cb` from `b`.][[space]]] +[[`eval_multiply(b, cb)`][`void`][Multiplies `b` by `cb`.][[space]]] +[[`eval_divide(b, cb)`][`void`][Divides `b` by `cb`.] + [`std::overflow_error` if cb has the value zero, and `std::numeric_limits >::has_infinity == false`]] +[[`eval_modulus(b, cb)`][`void`][Computes `b %= cb`, only required when `B` is an integer type.] + [`std::overflow_error` if cb has the value zero.]] +[[`eval_bitwise_and(b, cb)`][`void`][Computes `b &= cb`, only required when `B` is an integer type.][[space]]] +[[`eval_bitwise_or(b, cb)`][`void`][Computes `b |= cb`, only required when `B` is an integer type.][[space]]] +[[`eval_bitwise_xor(b, cb)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type.][[space]]] +[[`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]]] +[[`eval_left_shift(b, ui)`][`void`][Computes `b <<= ui`, only required when `B` is an integer type.][[space]]] +[[`eval_right_shift(b, ui)`][`void`][Computes `b >>= ui`, only required when `B` is an integer type.][[space]]] +[[`eval_convert_to(pa, cb)`][`void`][Converts `cb` to the type of `*pa` and store the result in `*pa`. Type `B` shall support + conversion to at least types `std::intmax_t`, `std::uintmax_t` and `long long`. + Conversion to other arithmetic types can then be synthesised using other operations. + Conversions to other types are entirely optional.][[space]]] +[[`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]]] +[[`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]]] +[[`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.] + [`std::runtime_error` if the exponent of cb is too large to be stored in an `int`.]] +[[`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]]] +[[`eval_floor(b, cb)`][`void`][Stores the floor of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] +[[`eval_ceil(b, cb)`][`void`][Stores the ceiling of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] +[[`eval_sqrt(b, cb)`][`void`][Stores the square root of `cb` in `b`, only required when `B` is a floating-point type.][[space]]] +[[`boost::multiprecision::number_category::type`][`mpl::int_`][`N` is one of the values `number_kind_integer`, `number_kind_floating_point`, `number_kind_rational` or `number_kind_fixed_point`. + Defaults to `number_kind_floating_point`.][[space]]] +] + +[table Optional Requirements on the Backend Type +[[Expression][Returns][Comments][Throws]] + +[[['Construct and assign:]]] +[[`B(rb)`][`B`][Move constructor. Afterwards variable `rb` shall be in sane state, albeit with unspecified value. + Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]] +[[`b = rb`][`B&`][Move-assign. Afterwards variable `rb` shall be in sane state, albeit with unspecified value. + Only destruction and assignment to the moved-from variable `rb` need be supported after the operation.][`noexcept`]] +[[`B(a)`][`B`][Direct construction from an arithmetic type. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, this operation is simulated using default-construction followed by assignment.][[space]]] +[[`B(b2)`][`B`][Copy constructor from a different back-end type. When not provided, a generic interconversion routine is used. + This constructor may be `explicit` if the corresponding frontend constructor should also be `explicit`.][[space]]] +[[`b = b2`][`b&`][Assignment operator from a different back-end type. When not provided, a generic interconversion routine is used.][[space]]] +[[`assign_components(b, a, a)`][`void`][Assigns to `b` the two components in the following arguments. + Only applies to rational and complex number types. + When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]] +[[`assign_components(b, b2, b2)`][`void`][Assigns to `b` the two components in the following arguments. + Only applies to rational and complex number types. + When not provided, arithmetic operations are used to synthesise the result from the two values.][[space]]] + +[[['Comparisons:]]] +[[`eval_eq(cb, cb2)`][`bool`][Returns `true` if `cb` and `cb2` are equal in value. + When not provided, the default implementation returns `cb.compare(cb2) == 0`.][`noexcept`]] +[[`eval_eq(cb, a)`][`bool`][Returns `true` if `cb` and `a` are equal in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, return the equivalent of `eval_eq(cb, B(a))`.][[space]]] +[[`eval_eq(a, cb)`][`bool`][Returns `true` if `cb` and `a` are equal in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version returns `eval_eq(cb, a)`.][[space]]] +[[`eval_lt(cb, cb2)`][`bool`][Returns `true` if `cb` is less than `cb2` in value. + When not provided, the default implementation returns `cb.compare(cb2) < 0`.][`noexcept`]] +[[`eval_lt(cb, a)`][`bool`][Returns `true` if `cb` is less than `a` in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default implementation returns `eval_lt(cb, B(a))`.][[space]]] +[[`eval_lt(a, cb)`][`bool`][Returns `true` if `a` is less than `cb` in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default implementation returns `eval_gt(cb, a)`.][[space]]] +[[`eval_gt(cb, cb2)`][`bool`][Returns `true` if `cb` is greater than `cb2` in value. + When not provided, the default implementation returns `cb.compare(cb2) > 0`.][`noexcept`]] +[[`eval_gt(cb, a)`][`bool`][Returns `true` if `cb` is greater than `a` in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default implementation returns `eval_gt(cb, B(a))`.][[space]]] +[[`eval_gt(a, cb)`][`bool`][Returns `true` if `a` is greater than `cb` in value. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default implementation returns `eval_lt(cb, a)`.][[space]]] +[[`eval_is_zero(cb)`][`bool`][Returns `true` if `cb` is zero, otherwise `false`. The default version of this function + returns `cb.compare(ui_type(0)) == 0`, where `ui_type` is `ui_type` is + `typename mpl::front::type`.][[space]]] +[[`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. + The default version of this function + returns `cb.compare(ui_type(0))`, where `ui_type` is `ui_type` is + `typename mpl::front::type`.][[space]]] + +[[['Basic arithmetic:]]] +[[`eval_add(b, a)`][`void`][Adds `a` to `b`. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_add(b, B(a))`][[space]]] +[[`eval_add(b, cb, cb2)`][`void`][Add `cb` to `cb2` and stores the result in `b`. + When not provided, does the equivalent of `b = cb; eval_add(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_add(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_add(b, cb, a)`.][[space]]] +[[`eval_subtract(b, a)`][`void`][Subtracts `a` from `b`. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_subtract(b, B(a))`][[space]]] +[[`eval_subtract(b, cb, cb2)`][`void`][Subtracts `cb2` from `cb` and stores the result in `b`. + When not provided, does the equivalent of `b = cb; eval_subtract(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_subtract(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_subtract(b, cb, a); b.negate();`.][[space]]] +[[`eval_multiply(b, a)`][`void`][Multiplies `b` by `a`. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_multiply(b, B(a))`][[space]]] +[[`eval_multiply(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and stores the result in `b`. + When not provided, does the equivalent of `b = cb; eval_multiply(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_multiply(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_multiply(b, cb, a)`.][[space]]] +[[`eval_multiply_add(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and adds the result to `b`. + When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by + `eval_add(b, t)`.][[space]]] +[[`eval_multiply_add(b, cb, a)`][`void`][Multiplies `a` by `cb` and adds the result to `b`. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by + `eval_add(b, t)`.][[space]]] +[[`eval_multiply_add(b, a, cb)`][`void`][Multiplies `a` by `cb` and adds the result to `b`. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided does the equivalent of `eval_multiply_add(b, cb, a)`.][[space]]] +[[`eval_multiply_subtract(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and subtracts the result from `b`. + When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, cb2)` followed by + `eval_subtract(b, t)`.][[space]]] +[[`eval_multiply_subtract(b, cb, a)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided does the equivalent of creating a temporary `B t` and `eval_multiply(t, cb, a)` followed by + `eval_subtract(b, t)`.][[space]]] +[[`eval_multiply_subtract(b, a, cb)`][`void`][Multiplies `a` by `cb` and subtracts the result from `b`. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided does the equivalent of `eval_multiply_subtract(b, cb, a)`.][[space]]] +[[`eval_multiply_add(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and adds the result to `cb3` storing the result in `b`. + When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by + `eval_add(b, cb3)`. + For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of + `cb`, `cb2` and `cb3` with any type type listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] +[[`eval_multiply_subtract(b, cb, cb2, cb3)`][`void`][Multiplies `cb` by `cb2` and subtracts from the result `cb3` storing the result in `b`. + When not provided does the equivalent of `eval_multiply(b, cb, cb2)` followed by + `eval_subtract(b, cb3)`. + For brevity, only a version showing all arguments of type `B` is shown here, but you can replace up to any 2 of + `cb`, `cb2` and `cb3` with any type type listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`.][[space]]] +[[`eval_divide(b, a)`][`void`][Divides `b` by `a`. The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_divide(b, B(a))`] + [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits >::has_infinity == false`]] +[[`eval_divide(b, cb, cb2)`][`void`][Divides `cb` by `cb2` and stores the result in `b`. + When not provided, does the equivalent of `b = cb; eval_divide(b, cb2)`.] + [`std::overflow_error` if `cb2` has the value zero, and `std::numeric_limits >::has_infinity == false`]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_divide(b, cb, B(a))`.] + [`std::overflow_error` if `a` has the value zero, and `std::numeric_limits >::has_infinity == false`]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_divide(b, B(a), cb)`.] + [`std::overflow_error` if cb has the value zero, and `std::numeric_limits >::has_infinity == false`]] +[[`eval_increment(b)`][void][Increments the value of `b` by one. + When not provided, does the equivalent of `eval_add(b, static_cast(1u))`. + Where `ui_type` is `typename mpl::front::type`.][[space]]] +[[`eval_decrement(b)`][void][Decrements the value of `b` by one. + When not provided, does the equivalent of `eval_subtract(b, static_cast(1u))`. + Where `ui_type` is `typename mpl::front::type`.][[space]]] + +[[['Integer specific operations:]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_modulus(b, B(a))`] + [`std::overflow_error` if `a` has the value zero.]] +[[`eval_modulus(b, cb, cb2)`][`void`][Computes `cb % cb2` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_modulus(b, cb2)`.] + [`std::overflow_error` if `a` has the value zero.]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_modulus(b, cb, B(a))`.] + [`std::overflow_error` if `a` has the value zero.]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_modulus(b, B(a), cb)`.] + [`std::overflow_error` if `a` has the value zero.]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_bitwise_and(b, B(a))`][[space]]] +[[`eval_bitwise_and(b, cb, cb2)`][`void`][Computes `cb & cb2` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_bitwise_and(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_and(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_and(b, cb, a)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_bitwise_or(b, B(a))`][[space]]] +[[`eval_bitwise_or(b, cb, cb2)`][`void`][Computes `cb | cb2` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_bitwise_or(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_or(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_or(b, cb, a)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, the default version calls `eval_bitwise_xor(b, B(a))`][[space]]] +[[`eval_bitwise_xor(b, cb, cb2)`][`void`][Computes `cb ^ cb2` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_bitwise_xor(b, cb2)`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_xor(b, cb, B(a))`.][[space]]] +[[`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 + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + When not provided, does the equivalent of `eval_bitwise_xor(b, cb, a)`.][[space]]] +[[`eval_left_shift(b, cb, ui)`][`void`][Computes `cb << ui` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_left_shift(b, a);`.][[space]]] +[[`eval_right_shift(b, cb, ui)`][`void`][Computes `cb >> ui` and stores the result in `b`, only required when `B` is an integer type. + When not provided, does the equivalent of `b = cb; eval_right_shift(b, a);`.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.] + [`std::overflow_error` if `a` has the value zero.]] +[[`eval_integer_modulus(cb, ui)`][`unsigned`][Returns the result of `cb % ui`. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.] + [`std::overflow_error` if `a` has the value zero.]] +[[`eval_lsb(cb)`][`unsigned`][Returns the index of the least significant bit that is set. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_bit_test(cb, ui)`][`bool`][Returns true if `cb` has bit `ui` set. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_bit_set(b, ui)`][`void`][Sets the bit at index `ui` in `b`. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_bit_unset(b, ui)`][`void`][Unsets the bit at index `ui` in `b`. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_bit_flip(b, ui)`][`void`][Flips the bit at index `ui` in `b`. Only required when `B` is an integer type. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + The default version of this function calls `eval_gcd(b, cb, B(a))`.][[space]]] +[[`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. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + The default version of this function calls `eval_lcm(b, cb, B(a))`.][[space]]] +[[`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. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + The default version of this function calls `eval_gcd(b, cb, a)`.][[space]]] +[[`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. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types` or `B::float_types`. + The default version of this function calls `eval_lcm(b, cb, a)`.][[space]]] +[[`eval_powm(b, cb, cb2, cb3)`][`void`][Sets `b` to the result of ['(cb^cb2)%cb3]. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_powm(b, cb, cb2, a)`][`void`][Sets `b` to the result of ['(cb^cb2)%a]. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types`. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_powm(b, cb, a, cb2)`][`void`][Sets `b` to the result of ['(cb^a)%cb2]. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types`. + The default version of this function is synthesised from other operations above.][[space]]] +[[`eval_powm(b, cb, a, a2)`][`void`][Sets `b` to the result of ['(cb^a)%a2]. + The type of `a` shall be listed in one of the type lists + `B::signed_types`, `B::unsigned_types`. + The default version of this function is synthesised from other operations above.][[space]]] + +[[['Sign manipulation:]]] +[[`eval_abs(b, cb)`][`void`][Set `b` to the absolute value of `cb`. + The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if + `eval_get_sign(cb) < 0`.][[space]]] +[[`eval_fabs(b, cb)`][`void`][Set `b` to the absolute value of `cb`. + The default version of this functions assigns `cb` to `b`, and then calls `b.negate()` if + `eval_get_sign(cb) < 0`.][[space]]] + +[[['Floating point functions:]]] +[[`eval_fpclassify(cb)`][`int`][Returns one of the same values returned by `std::fpclassify`. Only required when `B` is an floating-point type. + The default version of this function will only test for zero `cb`.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +[[`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. + The default version of this function is synthesised from other operations above.][[space]]] +] + +When the tables above place no ['throws] requirements on an operation, then it is up to each type modelling this concept to +decide when or whether throwing an exception is desirable. However, thrown exceptions should always either be the type, or +inherit from the type `std::runtime_error`. For example, a floating point type might choose to throw `std::overflow_error` +whenever the result of an operation would be infinite, and `std::underflow_error` whenever it would round to zero. + +[note +The non-member functions are all named with an "eval_" prefix to avoid conflicts with template classes of the same name - +in point of fact this naming convention shouldn't be necessary, but rather works around some compiler bugs.] + +[endsect] + +[section:headers Header File Structure] + +[table Top level headers +[[Header][Contains]] +[[cpp_int.hpp][The `cpp_int` backend type.]] +[[gmp.hpp][Defines all [gmp] related backends.]] +[[miller_rabin.hpp][Miller Rabin primality testing code.]] +[[number.hpp][Defines the `number` backend, is included by all the backend headers.]] +[[mpfr.hpp][Defines the mpfr_float_backend backend.]] +[[random.hpp][Defines code to interoperate with Boost.Random.]] +[[rational_adapter.hpp][Defines the `rational_adapter` backend.]] +[[cpp_dec_float.hpp][Defines the `cpp_dec_float` backend.]] +[[tommath.hpp][Defines the `tommath_int` backend.]] +[[concepts/number_archetypes.hpp][Defines a backend concept architypes for testing use.]] +] + +[table Implementation Headers] +[[Header][Contains]] +[[cpp_int/add.hpp][Add and subtract operators for `cpp_int_backend`.]] +[[cpp_int/bitwise.hpp][Bitwise operators for `cpp_int_backend`.]] +[[cpp_int/checked.hpp][Helper functions for checked arithmetic for `cpp_int_backend`.]] +[[cpp_int/comparison.hpp][Comparison operators for `cpp_int_backend`.]] +[[cpp_int/cpp_int_config.hpp][Basic setup and configuration for `cpp_int_backend`.]] +[[cpp_int/divide.hpp][Division and modulus operators for `cpp_int_backend`.]] +[[cpp_int/limits.hpp][`numeric_limits` support for `cpp_int_backend`.]] +[[cpp_int/misc.hpp][Miscellaneous operators for `cpp_int_backend`.]] +[[cpp_int/multiply.hpp][Multiply operators for `cpp_int_backend`.]] +[[detail/big_lanczos.hpp][Lanczos support for Boost.Math integration.]] +[[detail/default_ops.hpp][Default versions of the optional backend non-member functions.]] +[[detail/generic_interconvert.hpp][Generic interconversion routines.]] +[[detail/number_base.hpp][All the expression template code, metaprogramming, and operator overloads for `number`.]] +[[detail/no_et_ops.hpp][The non-expression template operators.]] +[[defail/functions/constants.hpp][Defines constants used by the floating point functions.]] +[[detail/functions/pow.hpp][Defines default versions of the power and exponential related floating point functions.]] +[[detail/functions/trig.hpp][Defines default versions of the trigonometric related floating point functions.]] +] + +[endsect] + +[endsect] + +[section:perf Performance Comparison] + +[section:overhead The Overhead in the Number Class Wrapper] + +Using a simple [@../../performance/arithmetic_backend.hpp backend class] that wraps any built in arithmetic type +we can measure the overhead involved in wrapping a type inside the `number` frontend, and the effect that turning +on expression templates has. The following table compares the performance between `double` and a `double` wrapped +inside class `number`: + +[table +[[Type][Bessel Function Evaluation][Non-Central T Evaluation]] +[[`double`] [[*1.0 (0.016s)]] [[*1.0] (0.46s)]] +[[`number, et_off>`] [1.2 (0.019s)] [[*1.0](0.46s)]] +[[`number, et_on>`] [1.2 (0.019s)] [1.7 (0.79s)]] +] + +As you can see whether there is an overhead, and how large it is depends on the actual situation, +but the overhead is in any cases small. Expression templates generally add a greater overhead the +more complex the expression becomes due to the logic of figuring out how to best unpack and evaluate +the expression, but of course this is also the situation where you save more temporaries. For a +"trivial" backend like this, saving temporaries has no benefit, but for larger types it becomes +a bigger win. + +The following table compares arithmetic using either `long long` or `number >` +for the [@../../performance/voronoi_perfromance.cpp voronoi-diagram builder test]: + +[table +[[Type][Relative time]] +[[`long long`][[*1.0](0.0823s)]] +[[`number, et_off>`][1.05 (0.0875s)]] +] + +This test involves mainly creating a lot of temporaries and performing a small amount of arithmetic on them, +with very little difference in performance between the native and "wrapped" types. + +[endsect] + +[section:realworld Floating Point Real World Tests] + +These tests test the total time taken to execute all of Boost.Math's test cases for these functions. +In each case the best performing library gets a relative score of 1, with the total execution time +given in brackets. The first three libraries listed are the various floating point types provided +by this library, while for comparison, two popular C++ front-ends to [mpfr] ([mpfr_class] and [mpreal]) +are also shown. + +Test code was compiled with Microsoft Visual Studio 2010 with all optimisations +turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit +Windows Vista machine. + +[table Bessel Function Performance +[[Library][50 Decimal Digits][100 Decimal Digits]] +[[mpfr_float] [1.2 (5.78s)] [1.2 (9.56s)]] +[[static_mpfr_float] [1.1 (5.47s)] [1.1 (9.09s)]] +[[mpf_float] [[*1.0] (4.82s)] [[*1.0](8.07s)]] +[[cpp_dec_float] [1.8 (8.54s)] [2.6 (20.66s)]] +[[[mpfr_class]] [1.3 (6.28s)] [1.2(10.06s)]] +[[[mpreal]] [2.0 (9.54s)] [1.7 (14.08s)]] +] + +[table Non-Central T Distribution Performance +[[Library][50 Decimal Digits]] +[[mpfr_float] [1.3 (263.27s)]] +[[static_mpfr_float] [1.2 (232.88s)]] +[[mpf_float] [[*1.0] (195.73s)]] +[[cpp_dec_float] [1.9 (366.38s)]] +[[[mpfr_class]] [1.5 (286.94s)]] +[[[mpreal]] [2.0 (388.70s)]] +] + +[endsect] + +[section:int_real_world Integer Real World Tests] + +Test code was compiled with Microsoft Visual Studio 2010 with all optimisations +turned on (/Ox), and used MPIR-2.3.0 and [tommath]-0.42.0. The tests were run on 32-bit +Windows Vista machine. + +The first set of [@../../performance/voronoi_performance.cpp tests] measure the times taken to +execute the multiprecision part of the Voronoi-diagram builder from Boost.Polygon. The tests +mainly create a large number of temporaries "just in case" multiprecision arithmetic is required, +for comparison, also included in the tests is Boost.Polygon's own partial-multiprecision integer +type which was custom written for this specific task: + +[table +[[Integer Type][Relative Performance (Actual time in parenthesis)]] +[[polygon::detail::extended_int][1(0.138831s)]] +[[int256_t][1.19247(0.165551s)]] +[[int512_t][1.23301(0.17118s)]] +[[int1024_t][1.21463(0.168628s)]] +[[checked_int256_t][1.31711(0.182855s)]] +[[checked_int512_t][1.57413(0.218538s)]] +[[checked_int1024_t][1.36992(0.190187s)]] +[[cpp_int][1.63244(0.226632s)]] +[[mpz_int][5.42511(0.753172s)]] +[[tom_int][29.0793(4.03709s)]] +] + +Note how for this use case, any dynamic allocation is a performance killer. + +The next [@../../performance/miller_rabin_performance.cpp tests] measure the time taken to generate 1000 128-bit +random numbers and test for primality using the Miller Rabin test. This is primarily a test of modular-exponentiation +since that is the rate limiting step: + +[table +[[Integer Type][Relative Performance (Actual time in parenthesis)]] +[[cpp_int][5.25827(0.379597s)]] +[[cpp_int (no Expression templates)][5.15675(0.372268s)]] +[[cpp_int (128-bit cache)][5.10882(0.368808s)]] +[[cpp_int (256-bit cache)][5.50623(0.397497s)]] +[[cpp_int (512-bit cache)][4.82257(0.348144s)]] +[[cpp_int (1024-bit cache)][5.00053(0.360991s)]] +[[int1024_t][4.37589(0.315897s)]] +[[checked_int1024_t][4.52396(0.326587s)]] +[[mpz_int][1(0.0721905s)]] +[[mpz_int (no Expression templates)][1.0248(0.0739806s)]] +[[tom_int][2.60673(0.188181s)]] +[[tom_int (no Expression templates)][2.64997(0.191303s)]] +] + +It's interesting to note that expression templates have little effect here - perhaps because the actual expressions involved +are relatively trivial in this case - so the time taken for multiplication and division tends to dominate. Also note +how increasing the internal cache size used by `cpp_int` is quite effective in this case in cutting out memory allocations +altogether - cutting about a third off the total runtime. Finally the much quicker times from GMP and tommath are down to their +much better modular-exponentiation algorithms (GMP's is about 5x faster). That's an issue which needs to be addressed +in a future release for __cpp_int. + +[endsect] + +[section:float_performance Float Algorithm Perfomance] + +Note that these tests are carefully designed to test performance of the underlying algorithms +and not memory allocation or variable copying. As usual, performance results should be taken +with a healthy dose of scepticism, and real-world performance may vary widely depending upon the +specifics of the program. In each table relative times are given first, with the best performer +given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 +operations. + +Test code was compiled with Microsoft Visual Studio 2010 with all optimisations +turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit +Windows Vista machine. + +[table Operator + +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0575156s)][[*1] (0.0740086s)][[*1] (0.219073s)]] +[[gmp_float][2.45065 (0.14095s)][2.01398 (0.149052s)][1.09608 (0.240122s)]] +[[mpfr_float][2.6001 (0.149546s)][2.12079 (0.156957s)][1.09078 (0.23896s)]] +] +[table Operator +(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.46115 (0.0855392s)][2.60353 (0.114398s)][3.62562 (0.264905s)]] +[[gmp_float][[*1] (0.0585424s)][[*1] (0.0439398s)][[*1] (0.0730648s)]] +[[mpfr_float][2.40441 (0.14076s)][3.2877 (0.144461s)][2.40379 (0.175632s)]] +] +[table Operator +(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.118146s)][[*1] (0.144714s)][[*1] (0.315639s)]] +[[gmp_float][4.5555 (0.538213s)][3.83096 (0.554395s)][1.95079 (0.615745s)]] +[[mpfr_float][5.74477 (0.678719s)][4.85295 (0.702291s)][2.70354 (0.853342s)]] +] +[table Operator +=(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.101188s)][[*1] (0.122394s)][[*1] (0.251975s)]] +[[gmp_float][5.199 (0.526079s)][4.39327 (0.537712s)][2.42151 (0.610159s)]] +[[mpfr_float][6.08318 (0.615547s)][5.18525 (0.634645s)][3.1022 (0.781677s)]] +] +[table Operator - +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0895163s)][[*1] (0.129248s)][1.5088 (0.374512s)]] +[[gmp_float][1.72566 (0.154474s)][1.22567 (0.158415s)][[*1] (0.248219s)]] +[[mpfr_float][1.83764 (0.164499s)][1.34284 (0.173559s)][1.00226 (0.248781s)]] +] +[table Operator -(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.105285s)][[*1] (0.142741s)][[*1] (0.278718s)]] +[[gmp_float][2.34437 (0.246828s)][1.28814 (0.183871s)][1.00731 (0.280754s)]] +[[mpfr_float][2.8032 (0.295136s)][2.09178 (0.298582s)][1.25213 (0.34899s)]] +] +[table Operator -(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.13719s)][[*1] (0.184428s)][[*1] (0.344212s)]] +[[gmp_float][4.0804 (0.559791s)][3.06776 (0.565781s)][2.07736 (0.715053s)]] +[[mpfr_float][5.10114 (0.699828s)][3.88684 (0.716843s)][2.50074 (0.860784s)]] +] +[table Operator -=(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.100984s)][[*1] (0.123148s)][[*1] (0.246181s)]] +[[gmp_float][5.68353 (0.573944s)][4.68636 (0.577116s)][2.6958 (0.663655s)]] +[[mpfr_float][6.19738 (0.625834s)][5.18544 (0.638577s)][3.18738 (0.784673s)]] +] +[table Operator * +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.03667 (0.284251s)][1.30576 (0.536527s)][1.44686 (4.81057s)]] +[[gmp_float][[*1] (0.274196s)][[*1] (0.410891s)][[*1] (3.32484s)]] +[[mpfr_float][1.24537 (0.341477s)][1.15785 (0.475749s)][1.1796 (3.92199s)]] +] +[table Operator *(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][3.97453 (0.240262s)][9.91222 (0.463473s)][50.7926 (4.36527s)]] +[[gmp_float][[*1] (0.0604505s)][[*1] (0.0467577s)][[*1] (0.0859431s)]] +[[mpfr_float][2.56974 (0.155342s)][3.56312 (0.166603s)][3.22964 (0.277565s)]] +] +[table Operator *(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.331877s)][1.01058 (0.586122s)][6.688 (4.7931s)]] +[[gmp_float][1.72433 (0.572266s)][[*1] (0.579987s)][[*1] (0.716672s)]] +[[mpfr_float][2.5553 (0.848047s)][1.74987 (1.0149s)][1.80403 (1.2929s)]] +] +[table Operator *=(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.321397s)][1.00772 (0.574887s)][6.65946 (4.7468s)]] +[[gmp_float][1.77419 (0.570218s)][[*1] (0.570482s)][[*1] (0.712791s)]] +[[mpfr_float][2.62172 (0.842611s)][1.77691 (1.01369s)][1.77511 (1.26528s)]] +] +[table Operator / +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.96096 (4.00777s)][4.53244 (7.86435s)][6.11936 (51.5509s)]] +[[gmp_float][[*1] (1.35354s)][[*1] (1.73512s)][[*1] (8.42422s)]] +[[mpfr_float][1.30002 (1.75963s)][1.39045 (2.41261s)][1.66762 (14.0484s)]] +] +[table Operator /(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][8.60726 (1.8181s)][15.4122 (3.67479s)][34.5119 (24.729s)]] +[[gmp_float][1.24394 (0.262756s)][[*1] (0.238433s)][[*1] (0.716536s)]] +[[mpfr_float][[*1] (0.211229s)][1.12178 (0.26747s)][1.02237 (0.732562s)]] +] +[table Operator /(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.10976 (1.97569s)][3.73601 (3.9133s)][11.3085 (25.4533s)]] +[[gmp_float][[*1] (0.936452s)][[*1] (1.04746s)][[*1] (2.25081s)]] +[[mpfr_float][1.3423 (1.257s)][1.51575 (1.58768s)][3.31513 (7.46175s)]] +] +[table Operator /=(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.17401 (1.96883s)][3.79591 (3.8965s)][11.2328 (25.2606s)]] +[[gmp_float][[*1] (0.905621s)][[*1] (1.0265s)][[*1] (2.24882s)]] +[[mpfr_float][1.37953 (1.24933s)][1.53073 (1.57129s)][3.30546 (7.43339s)]] +] +[table Operator construct +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.00929804s)][[*1] (0.0268321s)][[*1] (0.0310685s)]] +[[gmp_float][30.8781 (0.287106s)][7.59969 (0.203916s)][6.51873 (0.202527s)]] +[[mpfr_float][23.5296 (0.218779s)][8.11058 (0.217624s)][7.16325 (0.222552s)]] +] +[table Operator construct(unsigned) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0603971s)][[*1] (0.0735485s)][[*1] (0.116464s)]] +[[gmp_float][3.91573 (0.236498s)][2.88171 (0.211945s)][1.81075 (0.210887s)]] +[[mpfr_float][4.90052 (0.295977s)][4.01118 (0.295017s)][2.62005 (0.305141s)]] +] +[table Operator construct(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0610288s)][[*1] (0.0759005s)][[*1] (0.118511s)]] +[[gmp_float][8.26247 (0.504249s)][6.69042 (0.507806s)][4.32819 (0.51294s)]] +[[mpfr_float][10.1593 (0.620013s)][8.45884 (0.64203s)][5.51472 (0.653557s)]] +] +[table Operator str +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.95848 (0.0223061s)][3.33461 (0.033471s)][3.0159 (0.132732s)]] +[[gmp_float][[*1] (0.00753971s)][[*1] (0.0100374s)][[*1] (0.0440106s)]] +[[mpfr_float][1.25424 (0.00945658s)][1.24943 (0.012541s)][1.09428 (0.0481601s)]] +] + +[endsect] + +[section:integer_performance Integer Algorithm Perfomance] + +Note that these tests are carefully designed to test performance of the underlying algorithms +and not memory allocation or variable copying. As usual, performance results should be taken +with a healthy dose of scepticism, and real-world performance may vary widely depending upon the +specifics of the program. In each table relative times are given first, with the best performer +given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 +operations. + +Test code was compiled with Microsoft Visual Studio 2010 with all optimisations +turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit +Windows Vista machine. + +Linux x86_64 results are broadly similar, except that libtommath performs much better there. + +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.22306 (0.0279933s)][1.15878 (0.038341s)][1.24006 (0.0562258s)][1.32055 (0.0925091s)]] +[[cpp_int(fixed)][1.56093 (0.0357264s)][1.71757 (0.05683s)][1.66497 (0.0754916s)][1.70376 (0.119354s)]] +[[gmp_int][1.98788 (0.0454986s)][1.37882 (0.0456216s)][1.14898 (0.0520959s)][[*1] (0.0700532s)]] +[[tommath_int][[*1] (0.022888s)][[*1] (0.0330875s)][[*1] (0.0453411s)][1.07021 (0.074972s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0162581s)][[*1] (0.0196602s)][[*1] (0.0305476s)][[*1] (0.0421105s)]] +[[cpp_int(fixed)][1.3852 (0.0225207s)][1.84835 (0.036339s)][1.6111 (0.0492153s)][1.63014 (0.068646s)]] +[[gmp_int][1.95525 (0.0317886s)][2.2217 (0.0436791s)][2.21508 (0.0676653s)][2.58759 (0.108965s)]] +[[tommath_int][13.603 (0.221158s)][11.5797 (0.227659s)][7.86674 (0.24031s)][6.36923 (0.268212s)]] +] +[table Operator +(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0269712s)][[*1] (0.0296213s)][[*1] (0.0380242s)][[*1] (0.045841s)]] +[[cpp_int(fixed)][1.38342 (0.0373126s)][1.51165 (0.0447769s)][1.54533 (0.05876s)][1.3971 (0.0640443s)]] +[[gmp_int][26.7163 (0.72057s)][24.0631 (0.712781s)][19.6009 (0.745307s)][17.6547 (0.809308s)]] +[[tommath_int][19.7493 (0.532664s)][18.2944 (0.541905s)][14.9127 (0.567043s)][12.9059 (0.591619s)]] +] +[table Operator +=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.16166 (0.020334s)][1.15312 (0.0204789s)][1.21086 (0.0216179s)][1.28088 (0.0229569s)]] +[[cpp_int(fixed)][[*1] (0.0175043s)][[*1] (0.0177595s)][[*1] (0.0178534s)][[*1] (0.0179228s)]] +[[gmp_int][39.0852 (0.684159s)][38.7246 (0.68773s)][38.2555 (0.68299s)][37.6736 (0.675217s)]] +[[tommath_int][30.5872 (0.535408s)][29.371 (0.521614s)][30.3387 (0.541648s)][31.8346 (0.570565s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.12975 (0.0308979s)][[*1] (0.0392305s)][1.05392 (0.0543957s)][1.18166 (0.0860767s)]] +[[cpp_int(fixed)][1.36853 (0.0374283s)][1.45987 (0.0572717s)][1.44606 (0.0746349s)][1.55935 (0.11359s)]] +[[gmp_int][1.53173 (0.0418917s)][1.17956 (0.0462749s)][1.13609 (0.0586365s)][[*1] (0.0728442s)]] +[[tommath_int][[*1] (0.0273493s)][1.07293 (0.0420917s)][[*1] (0.0516126s)][1.0985 (0.0800191s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0146171s)][[*1] (0.0172176s)][[*1] (0.023655s)][[*1] (0.0313105s)]] +[[cpp_int(fixed)][1.49086 (0.021792s)][1.94917 (0.03356s)][1.89657 (0.0448632s)][1.82658 (0.057191s)]] +[[gmp_int][2.16301 (0.0316169s)][2.55059 (0.0439151s)][2.67983 (0.0633913s)][3.27949 (0.102682s)]] +[[tommath_int][14.0691 (0.20565s)][12.527 (0.215684s)][9.43355 (0.22315s)][7.64671 (0.239422s)]] +] +[table Operator -(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0265242s)][[*1] (0.0295275s)][[*1] (0.0377737s)][[*1] (0.0450106s)]] +[[cpp_int(fixed)][1.2627 (0.033492s)][1.47472 (0.0435449s)][1.47468 (0.055704s)][1.40667 (0.0633151s)]] +[[gmp_int][26.0595 (0.691208s)][23.3957 (0.690817s)][18.9344 (0.715223s)][16.9593 (0.763349s)]] +[[tommath_int][19.26 (0.510855s)][17.6236 (0.52038s)][13.9134 (0.52556s)][12.2359 (0.550746s)]] +] +[table Operator -=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.28589 (0.0210146s)][1.3505 (0.0222463s)][1.34427 (0.0237863s)][1.22787 (0.0230902s)]] +[[cpp_int(fixed)][[*1] (0.0163425s)][[*1] (0.0164727s)][[*1] (0.0176946s)][[*1] (0.0188051s)]] +[[gmp_int][41.0201 (0.670371s)][41.4726 (0.683165s)][37.9503 (0.671514s)][35.6021 (0.669502s)]] +[[tommath_int][32.6952 (0.534322s)][31.4882 (0.518695s)][29.3988 (0.5202s)][29.1175 (0.547558s)]] +] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.13172 (0.0766099s)][1.59509 (0.20993s)][1.40998 (0.70643s)][1.70758 (2.66895s)]] +[[cpp_int(fixed)][[*1] (0.067693s)][1.27132 (0.167319s)][[*1] (0.50102s)][[*1] (1.563s)]] +[[gmp_int][1.01718 (0.0688559s)][[*1] (0.13161s)][1.13221 (0.567258s)][1.02292 (1.59883s)]] +[[tommath_int][1.6793 (0.113677s)][2.66959 (0.351345s)][2.01091 (1.00751s)][2.05812 (3.21684s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0228822s)][1.19988 (0.0332404s)][1.13882 (0.0416226s)][1.2711 (0.0665655s)]] +[[cpp_int(fixed)][1.33157 (0.0304692s)][1.6546 (0.0458376s)][1.72684 (0.063114s)][1.83178 (0.0959269s)]] +[[gmp_int][1.00858 (0.0230786s)][[*1] (0.0277032s)][[*1] (0.0365488s)][[*1] (0.0523682s)]] +[[tommath_int][10.8491 (0.248252s)][9.88511 (0.273849s)][8.95509 (0.327298s)][8.04172 (0.421131s)]] +] +[table Operator *(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0574926s)][[*1] (0.0876613s)][[*1] (0.146194s)][[*1] (0.258556s)]] +[[cpp_int(fixed)][1.12247 (0.0645337s)][1.24471 (0.109113s)][1.19748 (0.175065s)][1.17442 (0.303653s)]] +[[gmp_int][12.271 (0.705488s)][8.23054 (0.7215s)][5.28668 (0.772883s)][3.09816 (0.801047s)]] +[[tommath_int][10.2751 (0.590743s)][7.36707 (0.645807s)][4.88979 (0.71486s)][3.43724 (0.888719s)]] +] +[table Operator *=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][114.922 (7.57662s)][70.5882 (7.61458s)][44.3157 (7.67791s)][26.2881 (7.81595s)]] +[[cpp_int(fixed)][[*1] (0.0659286s)][[*1] (0.107873s)][[*1] (0.173255s)][[*1] (0.297319s)]] +[[gmp_int][47.9828 (3.16344s)][29.4972 (3.18196s)][18.1719 (3.14838s)][10.6941 (3.17956s)]] +[[tommath_int][284.199 (18.7368s)][173.129 (18.676s)][109.052 (18.8938s)][64.5866 (19.2028s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.71618 (0.616086s)][2.09988 (0.737246s)][1.65898 (0.94343s)][1.49441 (1.44418s)]] +[[cpp_int(fixed)][[*1] (0.226821s)][[*1] (0.35109s)][[*1] (0.56868s)][[*1] (0.966385s)]] +[[gmp_int][3.82134 (0.866761s)][2.75998 (0.969001s)][1.93226 (1.09884s)][1.34132 (1.29623s)]] +[[tommath_int][13.2978 (3.01622s)][11.3314 (3.97833s)][9.94138 (5.65347s)][13.3423 (12.8938s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][4.15094 (0.23911s)][3.57962 (0.356615s)][3.11624 (0.578256s)][2.82967 (1.00414s)]] +[[cpp_int(fixed)][2.42806 (0.139865s)][2.54164 (0.253208s)][2.43025 (0.450962s)][2.37209 (0.841768s)]] +[[gmp_int][[*1] (0.0576038s)][[*1] (0.0996238s)][[*1] (0.185562s)][[*1] (0.354863s)]] +[[tommath_int][36.3133 (2.09179s)][28.2731 (2.81668s)][21.8589 (4.05618s)][25.8061 (9.15762s)]] +] +[table Operator /(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.53953 (0.716927s)][1.40156 (1.65075s)][2.59584 (3.57744s)][4.58524 (8.3789s)]] +[[cpp_int(fixed)][[*1] (0.465679s)][1.09556 (1.29034s)][2.2858 (3.15016s)][4.40115 (8.0425s)]] +[[gmp_int][2.25405 (1.04967s)][[*1] (1.17779s)][[*1] (1.37814s)][[*1] (1.82736s)]] +[[tommath_int][5.03884 (2.34648s)][2.63459 (3.103s)][3.67287 (5.06174s)][6.77479 (12.38s)]] +] +[table Operator /=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.78744 (0.0586752s)][1.74065 (0.0616578s)][1.66814 (0.0740436s)][1.36231 (0.126362s)]] +[[cpp_int(fixed)][[*1] (0.0328264s)][[*1] (0.0354222s)][[*1] (0.0443871s)][[*1] (0.0927553s)]] +[[gmp_int][21.2392 (0.697207s)][19.3517 (0.68548s)][15.2936 (0.678837s)][7.37138 (0.683734s)]] +[[tommath_int][32.8142 (1.07717s)][30.5556 (1.08235s)][24.7236 (1.09741s)][12.4072 (1.15084s)]] +] +[table Operator % +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.86833 (0.37472s)][1.43076 (0.491332s)][1.30757 (0.708055s)][1.2528 (1.15842s)]] +[[cpp_int(fixed)][[*1] (0.200565s)][[*1] (0.343407s)][[*1] (0.541503s)][[*1] (0.924662s)]] +[[gmp_int][3.22603 (0.647027s)][2.08249 (0.715143s)][1.5148 (0.82027s)][1.09519 (1.01268s)]] +[[tommath_int][15.4642 (3.10158s)][11.5534 (3.9675s)][10.5164 (5.69467s)][13.8962 (12.8493s)]] +] +[table Operator %(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.80079 (0.106617s)][1.96413 (0.207216s)][2.09096 (0.395682s)][2.14767 (0.776873s)]] +[[cpp_int(fixed)][1.73532 (0.10274s)][1.92036 (0.202599s)][2.02172 (0.382579s)][2.07328 (0.749963s)]] +[[gmp_int][[*1] (0.0592053s)][[*1] (0.1055s)][[*1] (0.189234s)][[*1] (0.361727s)]] +[[tommath_int][35.6993 (2.11359s)][25.3086 (2.67007s)][21.2701 (4.02504s)][25.8662 (9.3565s)]] +] +[table Operator construct +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.17135 (0.00274853s)][[*1] (0.00275161s)][[*1] (0.00275161s)][[*1] (0.00344359s)]] +[[cpp_int(fixed)][[*1] (0.00234646s)][1.54518 (0.00425173s)][2.2494 (0.00618947s)][1.73247 (0.00596591s)]] +[[gmp_int][85.6802 (0.201045s)][72.6635 (0.199941s)][78.1286 (0.214979s)][58.3553 (0.200952s)]] +[[tommath_int][87.9831 (0.206449s)][74.8522 (0.205964s)][74.8918 (0.206073s)][63.4572 (0.218521s)]] +] +[table Operator construct(unsigned) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.43934 (0.00268554s)][[*1] (0.00286887s)][[*1] (0.00283465s)][[*1] (0.00290638s)]] +[[cpp_int(fixed)][[*1] (0.00186581s)][1.7597 (0.00504834s)][2.07419 (0.00587959s)][1.89871 (0.00551837s)]] +[[gmp_int][125.861 (0.234832s)][72.7068 (0.208586s)][75.5147 (0.214058s)][71.2679 (0.207131s)]] +[[tommath_int][240.568 (0.448854s)][155.552 (0.446257s)][157.598 (0.446734s)][160.728 (0.467137s)]] +] +[table Operator construct(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.3528 (0.00771495s)][1.61678 (0.00717424s)][1.12087 (0.00715985s)][1.2104 (0.0078878s)]] +[[cpp_int(fixed)][[*1] (0.00327905s)][[*1] (0.00443737s)][[*1] (0.00638775s)][[*1] (0.00651668s)]] +[[gmp_int][222.775 (0.730489s)][165.447 (0.734148s)][114.708 (0.732725s)][112.162 (0.730926s)]] +[[tommath_int][215.962 (0.70815s)][157.945 (0.700858s)][109.582 (0.699985s)][111.909 (0.729275s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.46938 (0.00196575s)][1.37205 (0.00331355s)][1.5689 (0.00862952s)][1.57176 (0.0237239s)]] +[[cpp_int(fixed)][[*1] (0.00133781s)][[*1] (0.00241504s)][[*1] (0.00550035s)][1.20619 (0.0182059s)]] +[[gmp_int][1.65482 (0.00221383s)][1.38972 (0.00335622s)][1.13845 (0.0062619s)][[*1] (0.0150938s)]] +[[tommath_int][13.9845 (0.0187087s)][18.3179 (0.0442384s)][23.3489 (0.128427s)][25.3273 (0.382285s)]] +] +[table Operator gcd +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.03241 (5.06795s)][1.89904 (11.3002s)][1.99735 (27.4027s)][2.20708 (73.7574s)]] +[[cpp_int(fixed)][1.67874 (4.18605s)][1.70044 (10.1184s)][1.96475 (26.9554s)][2.28347 (76.31s)]] +[[gmp_int][[*1] (2.49357s)][[*1] (5.95047s)][[*1] (13.7195s)][[*1] (33.4185s)]] +[[tommath_int][5.01832 (12.5135s)][4.41659 (26.2808s)][4.08042 (55.9814s)][3.97901 (132.972s)]] +] +[table Operator & +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.00344 (0.0315529s)][[*1] (0.0426295s)][[*1] (0.0543214s)][1.06624 (0.0835064s)]] +[[cpp_int(fixed)][[*1] (0.0314446s)][1.0808 (0.046074s)][1.06116 (0.0576436s)][[*1] (0.0783186s)]] +[[gmp_int][1.78372 (0.0560885s)][1.58661 (0.0676363s)][1.5738 (0.0854908s)][1.83409 (0.143644s)]] +[[tommath_int][4.08054 (0.128311s)][3.50852 (0.149567s)][2.88826 (0.156894s)][4.45879 (0.349206s)]] +] +[table Operator &(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0367605s)][[*1] (0.0485394s)][[*1] (0.0650023s)][[*1] (0.099751s)]] +[[cpp_int(fixed)][1.00324 (0.0368795s)][1.06734 (0.0518081s)][1.05192 (0.0683771s)][1.05296 (0.105034s)]] +[[gmp_int][4.00058 (0.147063s)][3.02928 (0.147039s)][2.22221 (0.144449s)][1.45749 (0.145386s)]] +[[tommath_int][8.83732 (0.324864s)][6.95191 (0.337442s)][5.42556 (0.352674s)][6.10829 (0.609309s)]] +] +[table Operator | +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0312723s)][[*1] (0.0428385s)][[*1] (0.0528083s)][[*1] (0.0827344s)]] +[[cpp_int(fixed)][1.0311 (0.0322449s)][1.20267 (0.0515207s)][1.27028 (0.0670814s)][1.19432 (0.0988112s)]] +[[gmp_int][1.55273 (0.0485576s)][1.4656 (0.0627839s)][1.66721 (0.0880424s)][1.67004 (0.13817s)]] +[[tommath_int][4.15311 (0.129877s)][3.39008 (0.145226s)][2.88739 (0.152478s)][4.20575 (0.34796s)]] +] +[table Operator |(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.01685 (0.030066s)][[*1] (0.0360965s)][[*1] (0.0402109s)][[*1] (0.0527074s)]] +[[cpp_int(fixed)][[*1] (0.0295677s)][1.50234 (0.0542292s)][1.52609 (0.0613656s)][1.37526 (0.0724863s)]] +[[gmp_int][4.84414 (0.14323s)][3.99297 (0.144132s)][3.85375 (0.154963s)][2.91129 (0.153447s)]] +[[tommath_int][10.8218 (0.319975s)][9.05203 (0.326747s)][8.32597 (0.334795s)][10.948 (0.577039s)]] +] +[table Operator ^ +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0311003s)][[*1] (0.0430909s)][[*1] (0.0530915s)][[*1] (0.0842599s)]] +[[cpp_int(fixed)][1.04721 (0.0325686s)][1.18557 (0.0510874s)][1.25714 (0.0667433s)][1.14462 (0.0964459s)]] +[[gmp_int][1.59277 (0.0495356s)][1.47967 (0.0637601s)][1.73243 (0.0919772s)][1.68499 (0.141977s)]] +[[tommath_int][4.17425 (0.12982s)][3.41013 (0.146946s)][2.8988 (0.153902s)][4.17074 (0.351426s)]] +] +[table Operator ^(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0290428s)][[*1] (0.0360261s)][[*1] (0.0409722s)][[*1] (0.0541785s)]] +[[cpp_int(fixed)][1.01484 (0.0294736s)][1.4898 (0.0536716s)][1.34782 (0.0552234s)][1.35054 (0.0731703s)]] +[[gmp_int][4.94574 (0.143638s)][4.05569 (0.146111s)][3.65257 (0.149654s)][2.89039 (0.156597s)]] +[[tommath_int][10.8939 (0.316389s)][9.21322 (0.331916s)][8.17995 (0.335151s)][10.6902 (0.579178s)]] +] +[table Operator << +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0253777s)][1.04239 (0.034484s)][[*1] (0.0420979s)][[*1] (0.0623485s)]] +[[cpp_int(fixed)][1.05039 (0.0266563s)][1.40679 (0.0465388s)][1.34077 (0.0564434s)][1.20319 (0.0750171s)]] +[[gmp_int][1.0359 (0.0262888s)][[*1] (0.0330815s)][1.1625 (0.0489388s)][1.16511 (0.0726428s)]] +[[tommath_int][1.65904 (0.0421025s)][2.11201 (0.0698686s)][2.36727 (0.0996572s)][2.701 (0.168403s)]] +] +[table Operator >> +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0221035s)][1.0337 (0.0313761s)][1.03419 (0.0355718s)][1.20366 (0.0453508s)]] +[[cpp_int(fixed)][1.1036 (0.0243933s)][1.12323 (0.0340936s)][1.40181 (0.0482162s)][1.69985 (0.0640463s)]] +[[gmp_int][1.30456 (0.0288354s)][[*1] (0.0303532s)][[*1] (0.0343958s)][[*1] (0.0376776s)]] +[[tommath_int][10.5766 (0.233779s)][9.0959 (0.27609s)][8.6249 (0.29666s)][13.6818 (0.515498s)]] +] + +[endsect] + +[section:rational_performance Rational Type Perfomance] + +Note that these tests are carefully designed to test performance of the underlying algorithms +and not memory allocation or variable copying. As usual, performance results should be taken +with a healthy dose of scepticism, and real-world performance may vary widely depending upon the +specifics of the program. In each table relative times are given first, with the best performer +given a score of 1. Total actual times are given in brackets, measured in seconds for 500000 +operations. + +Test code was compiled with Microsoft Visual Studio 2010 with all optimisations +turned on (/Ox), and used MPIR-2.3.0 and [mpfr]-3.0.0. The tests were run on 32-bit +Windows Vista machine. + +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.89417 (18.4116s)][6.87256 (47.4698s)][6.65008 (107.715s)][6.53801 (256.244s)]] +[[mpq_rational][[*1] (3.1237s)][[*1] (6.90715s)][[*1] (16.1975s)][[*1] (39.1929s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][3.62367 (2.46488s)][4.18291 (2.94603s)][4.726 (3.74866s)][6.1388 (5.56817s)]] +[[mpq_rational][[*1] (0.680215s)][[*1] (0.704303s)][[*1] (0.7932s)][[*1] (0.907046s)]] +] +[table Operator +(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.1527 (2.6378s)][1.31751 (3.09863s)][1.58996 (4.00714s)][2.15642 (5.75702s)]] +[[mpq_rational][[*1] (2.28837s)][[*1] (2.35189s)][[*1] (2.52028s)][[*1] (2.66971s)]] +] +[table Operator +=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.18436 (2.7059s)][1.32279 (3.11099s)][1.61398 (4.05389s)][2.20048 (5.84623s)]] +[[mpq_rational][[*1] (2.2847s)][[*1] (2.35183s)][[*1] (2.51174s)][[*1] (2.6568s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.81893 (18.3457s)][6.82209 (47.1928s)][6.64143 (107.498s)][6.51362 (255.137s)]] +[[mpq_rational][[*1] (3.15277s)][[*1] (6.91765s)][[*1] (16.1859s)][[*1] (39.1698s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][3.72441 (2.48756s)][4.27663 (2.98713s)][4.62109 (3.72114s)][6.17605 (5.56503s)]] +[[mpq_rational][[*1] (0.667908s)][[*1] (0.698479s)][[*1] (0.805252s)][[*1] (0.901066s)]] +] +[table Operator -(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.15627 (2.63239s)][1.32096 (3.12092s)][1.61044 (4.00106s)][2.19378 (5.7644s)]] +[[mpq_rational][[*1] (2.27663s)][[*1] (2.36262s)][[*1] (2.48445s)][[*1] (2.62761s)]] +] +[table Operator -=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.1984 (2.73444s)][1.34141 (3.15698s)][1.64159 (4.06997s)][2.23017 (5.88108s)]] +[[mpq_rational][[*1] (2.28174s)][[*1] (2.35348s)][[*1] (2.47929s)][[*1] (2.63706s)]] +] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.4306 (32.5882s)][6.91805 (89.9436s)][6.94556 (207.307s)][6.88704 (492.151s)]] +[[mpq_rational][[*1] (6.00084s)][[*1] (13.0013s)][[*1] (29.8475s)][[*1] (71.4604s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][2.12892 (2.51376s)][2.47245 (3.07841s)][2.86832 (3.93619s)][3.94086 (6.02565s)]] +[[mpq_rational][[*1] (1.18077s)][[*1] (1.24508s)][[*1] (1.3723s)][[*1] (1.52902s)]] +] +[table Operator *(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.32254 (5.43565s)][1.56078 (6.73163s)][1.97701 (9.32522s)][2.85404 (15.1573s)]] +[[mpq_rational][[*1] (4.11002s)][[*1] (4.313s)][[*1] (4.71682s)][[*1] (5.31082s)]] +] +[table Operator *=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][6.29806 (58.1188s)][6.30556 (59.5076s)][6.3385 (62.1007s)][6.55345 (67.6905s)]] +[[mpq_rational][[*1] (9.22804s)][[*1] (9.43733s)][[*1] (9.79739s)][[*1] (10.329s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][4.4269 (66.8031s)][6.40103 (173.527s)][6.32347 (348.193s)][6.61148 (824.063s)]] +[[mpq_rational][[*1] (15.0903s)][[*1] (27.1093s)][[*1] (55.0637s)][[*1] (124.641s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.78772 (2.50984s)][2.10623 (3.10606s)][2.46986 (3.99358s)][3.37428 (5.96678s)]] +[[mpq_rational][[*1] (1.40393s)][[*1] (1.4747s)][[*1] (1.61693s)][[*1] (1.76831s)]] +] +[table Operator /(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.29695 (5.45454s)][1.55248 (6.85353s)][1.93237 (9.28765s)][2.75211 (14.8541s)]] +[[mpq_rational][[*1] (4.20568s)][[*1] (4.41458s)][[*1] (4.80635s)][[*1] (5.39734s)]] +] +[table Operator /=(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][6.19401 (58.4278s)][6.20135 (59.643s)][6.21327 (62.0338s)][6.40576 (67.6778s)]] +[[mpq_rational][[*1] (9.43295s)][[*1] (9.61774s)][[*1] (9.98407s)][[*1] (10.5652s)]] +] +[table Operator construct +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.00978288s)][[*1] (0.0100574s)][[*1] (0.0101393s)][[*1] (0.0101847s)]] +[[mpq_rational][39.1516 (0.383015s)][38.3523 (0.385725s)][37.5812 (0.381048s)][37.6007 (0.382953s)]] +] +[table Operator construct(unsigned) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.0548151s)][[*1] (0.0557542s)][[*1] (0.055825s)][[*1] (0.0552808s)]] +[[mpq_rational][7.21073 (0.395257s)][7.1016 (0.395944s)][7.02046 (0.391917s)][7.16881 (0.396297s)]] +] +[table Operator construct(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.0605156s)][[*1] (0.0616657s)][[*1] (0.0592056s)][[*1] (0.0603081s)]] +[[mpq_rational][35.1604 (2.12775s)][34.7575 (2.14335s)][35.7232 (2.11502s)][35.0437 (2.11342s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.48898 (0.0208949s)][8.49668 (0.0546688s)][10.107 (0.121897s)][10.5339 (0.310584s)]] +[[mpq_rational][[*1] (0.0038067s)][[*1] (0.00643413s)][[*1] (0.0120606s)][[*1] (0.0294843s)]] +] + +[endsect] + +[endsect] + +[section:map Roadmap] + +[section:hist History] + +[h4 Post review changes] + +* Non-expression template operators further optimised with rvalue reference support. +* Many functions made `constexp`. +* Differentiate between explicit and implicit conversions in the number constructor. +* Removed "mp_" prefix from types. +* Allowed mixed precision arithmetic. +* Changed ExpressionTemplates parameter to class `number` to use enumerated values rather than true/false. +* Changed ExpressionTemplate parameter default value to use a traits class so that the default value depends on the backend used. +* Added support for fused-multiply-add/subtract with GMP support. +* Tweaked expression template unpacking to use fewer temporaries when the LHS also appears in the RHS. +* Refactored `cpp_int_backend` based on review comments with new template parameter structure. +* Added additional template parameter to `mpfr_float_backend` to allow stack-based allocation. +* Added section on mixed precision arithmetic, and added support for operations yielding a higher precision result +than either of the arguments. +* Added overloads of integer-specific functions for built in integer types. + +[h4 Pre-review history] + +*2011-2012, John Maddock adds an expression template enabled front end to Christopher's code, +and adds support for other backends. +* 2011, Christopher Kormanyos publishes the decimal floating point code under the Boost +Software Licence. The code is published as: [@http://doi.acm.org/10.1145/1916461.1916469 +"Algorithm 910: A Portable C++ Multiple-Precision +System for Special-Function Calculations"], in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, +2011. +* 2002-2011, Christopher Kormanyos develops the all C++ decimal arithmetic floating point +code. + +[endsect] + +[section:todo TODO] + + + +More a list of what ['could] be done, rather than what ['should] be done (which may be a much smaller list!). + +* Add back-end support for libdecNumber. +* Add an adapter back-end for complex number types. +* Add a back-end for MPFR interval arithmetic. +* Add better multiplication routines (Karatsuba, FFT etc) to cpp_int_backend. +* Add assembly level routines to cpp_int_backend. +* Add an all C++ binary floating point type. +* Can ring types (exact floating point types) be supported? The answer should be yes, but someone needs to write it, +the hard part is IO and binary-decimal convertion. +* Should there be a choice of rounding mode (probably MPFR specific)? +* We can reuse temporaries in multiple subtrees (temporary caching). +* cpp_dec_float should round to nearest. +* A 2's complement fixed precision int that uses exactly N bits and no more. + +Things requested in review: + +* The performances of mp_number, false>respect to +float and mp_number, false> and int should be +given to show the cost of using the generic interface (Mostly done, just need to update docs to the latest results). +* Should we provide min/max overloads for expression templates? (Not done - we can't overload functions declared in the std namespace :-( ). +* The rounding applied when converting must be documented (Done). +* Document why we don't abstract out addition/multiplication algorithms etc. (done - FAQ) +* Document why we don't use proto (compile times) (Done). +* We can reuse temporaries in multiple subtrees (temporary caching) Moved to TODO list. +* Emphasise in the docs that ET's may reorder operations (done 2012/10/31). +* Document what happens to small fixed precision cpp_int's (done 2012/10/31). +* The use of bool in template parameters could be improved by the use of +an enum class which will be more explicit. E.g `enum class expression_template {disabled, enabled}; +enum class sign {unsigned, signed};` (Partly done 2012/09/15, done 2012/10/31). +* Each back-end should document the requirements it satisfies (not currently scheduled for inclusion: it's +deliberately an implementation detail, and "optional" requirements are optimisations which can't be detected +by the user). Not done: this is an implementation detail, the exact list of requirements satisfied is purely +an optimimization, not something the user can detect. +* A backend for an overflow aware integers (done 2012/10/31). +* IIUC convert_to is used to emulate in c++98 compilers C++11 explicit +conversions. Could the explicit conversion operator be added on +compilers supporting it? (Done 2012/09/15). +* The front-end should make the differences between implicit and explicit +construction (Done 2012/09/15). +* The tutorial should add more examples concerning implicit or explicit +conversions. (Done 2012/09/15). +* The documentation must explain how move semantics helps in this domain +and what the backend needs to do to profit from this optimization. (Done 2012/09/15). +* The documentation should contain Throws specification on the mp_number +and backend requirements operations. (Done 2012/09/15). +* The library interface should use the noexcept (BOOST_NOEXCEPT, ...) +facilities (Done 2012/09/15). +* It is unfortunate that the generic mp_number front end can not make use +contexpr as not all the backends can ensure this (done - we can go quite a way). +* literals: The library doesn't provide some kind of literals. I think that the +mp_number class should provide a way to create literals if the backend +is able to. (Done 2012/09/15). +* The ExpresionTemplate parameter could be defaulted to a traits class for more sensible defaults (done 2012/09/20). +* 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). + + + +[h4 Pre-Review Comments] + +* Make fixed precision orthogonal to Allocator type in cpp_int. Possible solution - add an additional MaxBits +template argument that defaults to 0 (meaning keep going till no more space/memory). Done. +* Can ring types (exact floating point types) be supported? The answer should be yes, but someone needs to write it (Moved to TODO list). +* Should there be a choice of rounding mode (probably MPFR specific)? Moved to TODO list. +* Make the exponent type for cpp_dec_float a templare parameter, maybe include support for big-integer exponents. +Open question - what should be the default - int32_t or int64_t? (done 2012/09/06) +* Document the size requirements of fixed precision ints (done 2012/09/15). +* Document std lib function accuracy (done 2012/09/15). +* Be a bit clearer on the effects of sign-magnitude representation of cpp_int - min == -max etc - done. +* Document cpp_dec_float precision, rounding, and exponent size (done 2012/09/06). +* Can we be clearer in the docs that mixed arithmetic doesn't work (no longer applicable as of 2012/09/06)? +* Document round functions behaviour better (they behave as in C++11) (added note 2012/09/06). +* Document limits on size of cpp_dec_float (done 2012/09/06). +* Add support for fused multiply add (and subtract). GMP mpz_t could use this (done 2012/09/20). + +[endsect] + +[section:faq FAQ] + +[variablelist +[[Why do I get compiler errors when passing a `number` to a template function?] + [Most likely you are actually passing an expression template type to the function and + template-argument-deduction deduces the "wrong" type. Try casting the arguments + involving expressions to the actual number type, or as a last resort turning off + expression template support in the number type you are using.]] +[[When is expression template support a performance gain?] + [As a general rule, expression template support adds a small runtime overhead + creating and unpacking the expression templates, but greatly reduces the number of + temporaries created. So it's most effective in improving performance when the cost + of creating a temporary is high: for example when creating a temporary involves a memory + allocation. It is least effective (and may even be a dis-optimisation) when temporaries + are cheap: for example if the number type is basically a thin wrapper around a native + arithmetic type. In addition, since the library makes extensive use of thin inline wrapper + functions, turning on compiler optimization is essential to achieving high performance.]] +[[Do expression templates reorder operations?] + [Yes they do, sometimes quite radically so, if this is a concern then they should be turned + off for the number type you are using.]] +[[I can't construct my number type from ['some other type], but the docs indicate that the conversion should be allowed, what's up?] + [Some conversions are ['explicit], that includes construction from a string, or constructing from any type + that may result in loss of precision (for example constructing an integer type from a float).]] +[[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`?] + [Bitwise operations on negative values (or indeed any signed integer type) are unspecified by the standard. As a result + any attempt to carry out a bitwise operation on a negative checked-integer will result in a `std::range_error` being thrown.]] +[[Why do I get compiler errors when trying to use the complement operator?] + [Use of the complement operator on signed types is problematic as the result is unspecified by the standard, and is further + complicated by the fact that most extended precision integer types use a sign-magnitude representation rather than the 2's + complement one favored by most native integer types. As a result the complement operator is deliberately disabled for + 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.]] +[[Why can't I negate an unsigned type?] + [The unary negation operator is deliberately disabled for unsigned integer types as its use would almost always be a programming error.]] +[[Why doesn't the library use proto?] + [A very early version of the library did use proto, but compile times became too slow + for the library to be usable. Since the library only required a tiny fraction of what + proto has to offer anyway, a lightweight expression template mechanism was used instead. + Compile times are still too slow...]] +[[Why not abstract out addition/multiplication algorithms?] + [This was deamed not to be practical: these algorithms are intimately + tied to the actual data representation used.]] +] + +[endsect] + +[section:ack Acknowledgements] + +This library would not have happened without: + +* Christopher Kormanyos' C++ decimal number code. +* Paul Bristow for patiently testing, and commenting on the library. +* All the folks at GMP, MPFR and libtommath, for providing the "guts" that makes this library work. +* [@http://www-cs-faculty.stanford.edu/~uno/taocp.html "The Art Of Computer Programming"], +Donald E. Knuth, Volume 2: Seminumerical Algorithms, Third Edition +(Reading, Massachusetts: Addison-Wesley, 1997), xiv+762pp. ISBN 0-201-89684-2 + +[endsect] + +[endsect] + +[section:indexes Indexes] + +[include ../../../../../trunk/tools/auto_index/include/auto_index_helpers.qbk] +[named_index function_name Function Index] +[named_index class_name Class Index] +[named_index typedef_name Typedef Index] +[index] + +[endsect] + diff --git a/example/cpp_dec_float_snips.cpp b/example/cpp_dec_float_snips.cpp new file mode 100644 index 00000000..012ad0ec --- /dev/null +++ b/example/cpp_dec_float_snips.cpp @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include + +void t1() +{ + //[cpp_dec_float_eg + //=#include + + using namespace boost::multiprecision; + + // Operations at fixed precision and full numeric_limits support: + cpp_dec_float_100 b = 2; + std::cout << std::numeric_limits::digits << std::endl; + // Note that digits10 is the same as digits, since we're base 10! : + std::cout << std::numeric_limits::digits10 << std::endl; + // We can use any C++ std lib function, lets print all the digits as well: + std::cout << std::setprecision(std::numeric_limits::max_digits10) + << log(b) << std::endl; // print log(2) + // We can also use any function from Boost.Math: + std::cout << boost::math::tgamma(b) << std::endl; + // These even work when the argument is an expression template: + std::cout << boost::math::tgamma(b * b) << std::endl; + // And since we have an extended exponent range we can generate some really large + // numbers here (4.0238726007709377354370243e+2564): + std::cout << boost::math::tgamma(cpp_dec_float_100(1000)) << std::endl; + //] +} + +int main() +{ + t1(); + return 0; +} + diff --git a/example/cpp_int_snips.cpp b/example/cpp_int_snips.cpp new file mode 100644 index 00000000..a2818740 --- /dev/null +++ b/example/cpp_int_snips.cpp @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include + +void t1() +{ + //[cpp_int_eg + //=#include + + using namespace boost::multiprecision; + + int128_t v = 1; + + // Do some fixed precision arithmetic: + for(unsigned i = 1; i <= 20; ++i) + v *= i; + + std::cout << v << std::endl; // prints 20! + + // Repeat at arbitrary precision: + cpp_int u = 1; + for(unsigned i = 1; i <= 100; ++i) + u *= i; + + std::cout << u << std::endl; // prints 100! + + //] +} + +void t3() +{ + //[cpp_rational_eg + //=#include + + using namespace boost::multiprecision; + + cpp_rational v = 1; + + // Do some arithmetic: + for(unsigned i = 1; i <= 1000; ++i) + v *= i; + v /= 10; + + std::cout << v << std::endl; // prints 1000! / 10 + std::cout << numerator(v) << std::endl; + std::cout << denominator(v) << std::endl; + + cpp_rational w(2, 3); // component wise constructor + std::cout << w << std::endl; // prints 2/3 + //] +} + + +int main() +{ + t1(); + t3(); + return 0; +} + diff --git a/example/floating_point_examples.cpp b/example/floating_point_examples.cpp new file mode 100644 index 00000000..2200b73d --- /dev/null +++ b/example/floating_point_examples.cpp @@ -0,0 +1,687 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include +#include +#include +#include + +//[AOS1 + +/*`Generic numeric programming employs templates to use the same code for different +floating-point types and functions. Consider the area of a circle a of radius r, given by + +[:['a = [pi] * r[super 2]]] + +The area of a circle can be computed in generic programming using Boost.Math +for the constant [pi] as shown below: + +*/ + +//=#include + +template +inline T area_of_a_circle(T r) +{ + using boost::math::constants::pi; + return pi() * r * r; +} + +/*` +It is possible to use `area_of_a_circle()` with built-in floating-point types as +well as floating-point types from Boost.Multiprecision. In particular, consider a +system with 4-byte single-precision float, 8-byte double-precision double and also the +`cpp_dec_float_50` data type from Boost.Multiprecision with 50 decimal digits +of precision. + +We can compute and print the approximate area of a circle with radius 123/100 for +`float`, `double` and `cpp_dec_float_50` with the program below. + +*/ + +//] + +//[AOS3 + +/*`In the next example we'll look at calling both standard library and Boost.Math functions from within generic code. +We'll also show how to cope with template arguments which are expression-templates rather than number types.*/ + +//] + +//[JEL + +/*` +In this example we'll show several implementations of the +[@http://mathworld.wolfram.com/LambdaFunction.html Jahnke and Emden Lambda function], +each implementation a little more sophisticated than the last. + +The Jahnke-Emden Lambda function is defined by the equation: + +[:['JahnkeEmden(v, z) = [Gamma](v+1) * J[sub v](z) / (z / 2)[super v]]] + +If we were to implement this at double precision using Boost.Math's facilities for the Gamma and Bessel +function calls it would look like this: + +*/ + +double JEL1(double v, double z) +{ + return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / std::pow(z / 2, v); +} + +/*` +Calling this function as: + + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL1(2.5, 0.5) << std::endl; + +Yields the output: + +[pre 9.822663964796047e-001] + +Now let's implement the function again, but this time using the multiprecision type +`cpp_dec_float_50` as the argument type: + +*/ + +boost::multiprecision::cpp_dec_float_50 + JEL2(boost::multiprecision::cpp_dec_float_50 v, boost::multiprecision::cpp_dec_float_50 z) +{ + return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / boost::multiprecision::pow(z / 2, v); +} + +/*` +The implementation is almost the same as before, but with one key difference - we can no longer call +`std::pow`, instead we must call the version inside the `boost::multiprecision` namespace. In point of +fact, we could have omitted the namespace prefix on the call to `pow` since the right overload would +have been found via [@http://en.wikipedia.org/wiki/Argument-dependent_name_lookup +argument dependent lookup] in any case. + +Note also that the first argument to `pow` along with the argument to `tgamma` in the above code +are actually expression templates. The `pow` and `tgamma` functions will handle these arguments +just fine. + +Here's an example of how the function may be called: + + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL2(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl; + +Which outputs: + +[pre 9.82266396479604757017335009796882833995903762577173e-01] + +Now that we've seen some non-template examples, lets repeat the code again, but this time as a template +that can be called either with a builtin type (`float`, `double` etc), or with a multiprecision type: + +*/ + +template +Float JEL3(Float v, Float z) +{ + using std::pow; + return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v); +} + +/*` + +Once again the code is almost the same as before, but the call to `pow` has changed yet again. +We need the call to resolve to either `std::pow` (when the argument is a builtin type), or +to `boost::multiprecision::pow` (when the argument is a multiprecision type). We do that by +making the call unqualified so that versions of `pow` defined in the same namespace as type +`Float` are found via argument dependent lookup, while the `using std::pow` directive makes +the standard library versions visible for builtin floating point types. + +Let's call the function with both `double` and multiprecision arguments: + + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL3(2.5, 0.5) << std::endl; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL3(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl; + +Which outputs: + +[pre +9.822663964796047e-001 +9.82266396479604757017335009796882833995903762577173e-01 +] + +Unfortunately there is a problem with this version: if we were to call it like this: + + boost::multiprecision::cpp_dec_float_50 v(2), z(0.5); + JEL3(v + 0.5, z); + +Then we would get a long and inscrutable error message from the compiler: the problem here is that the first +argument to `JEL3` is not a number type, but an expression template. We could obviously add a typecast to +fix the issue: + + JEL(cpp_dec_float_50(v + 0.5), z); + +However, if we want the function JEL to be truely reusable, then a better solution might be preferred. +To achieve this we can borrow some code from Boost.Math which calculates the return type of mixed-argument +functions, here's how the new code looks now: + +*/ + +template +typename boost::math::tools::promote_args::type + JEL4(Float1 v, Float2 z) +{ + using std::pow; + return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v); +} + +/*` + +As you can see the two arguments to the function are now separate template types, and +the return type is computed using the `promote_args` metafunction from Boost.Math. + +Now we can call: + + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL4(cpp_dec_float_100(2) + 0.5, cpp_dec_float_100(0.5)) << std::endl; + +And get 100 digits of output: + +[pre 9.8226639647960475701733500979688283399590376257717309069410413822165082248153638454147004236848917775e-01] + +As a bonus, we can now call the function not just with expression templates, but with other mixed types as well: +for example `float` and `double` or `int` and `double`, and the correct return type will be computed in each case. + +Note that while in this case we didn't have to change the body of the function, in the general case +any function like this which creates local variables internally would have to use `promote_args` +to work out what type those variables should be, for example: + + template + typename boost::math::tools::promote_args::type + JEL5(Float1 v, Float2 z) + { + using std::pow; + typedef typename boost::math::tools::promote_args::type variable_type; + variable_type t = pow(z / 2, v); + return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / t; + } + +*/ + +//] + +//[ND1 + +/*` +In this example we'll add even more power to generic numeric programming using not only different +floating-point types but also function objects as template parameters. Consider +some well-known central difference rules for numerically computing the first derivative +of a function ['f[prime](x)] with ['x [isin] [real]]: + +[equation floating_point_eg1] + +Where the difference terms ['m[sub n]] are given by: + +[equation floating_point_eg2] + +and ['dx] is the step-size of the derivative. + +The third formula in Equation 1 is a three-point central difference rule. It calculates +the first derivative of ['f[prime](x)] to ['O(dx[super 6])], where ['dx] is the given step-size. +For example, if +the step-size is 0.01 this derivative calculation has about 6 decimal digits of precision - +just about right for the 7 decimal digits of single-precision float. +Let's make a generic template subroutine using this three-point central difference +rule. In particular: +*/ + +template + value_type derivative(const value_type x, const value_type dx, function_type func) +{ + // Compute d/dx[func(*first)] using a three-point + // central difference rule of O(dx^6). + + const value_type dx1 = dx; + const value_type dx2 = dx1 * 2; + const value_type dx3 = dx1 * 3; + + const value_type m1 = (func(x + dx1) - func(x - dx1)) / 2; + const value_type m2 = (func(x + dx2) - func(x - dx2)) / 4; + const value_type m3 = (func(x + dx3) - func(x - dx3)) / 6; + + const value_type fifteen_m1 = 15 * m1; + const value_type six_m2 = 6 * m2; + const value_type ten_dx1 = 10 * dx1; + + return ((fifteen_m1 - six_m2) + m3) / ten_dx1; +} + +/*`The `derivative()` template function can be used to compute the first derivative +of any function to ['O(dx[super 6])]. For example, consider the first derivative of ['sin(x)] evaluated +at ['x = [pi]/3]. In other words, + +[equation floating_point_eg3] + +The code below computes the derivative in Equation 3 for float, double and boost's +multiple-precision type cpp_dec_float_50. +*/ + +//] + +//[GI1 + +/*` +Similar to the generic derivative example, we can calculate integrals in a similar manner: +*/ + +template +inline value_type integral(const value_type a, + const value_type b, + const value_type tol, + function_type func) +{ + unsigned n = 1U; + + value_type h = (b - a); + value_type I = (func(a) + func(b)) * (h / 2); + + for(unsigned k = 0U; k < 8U; k++) + { + h /= 2; + + value_type sum(0); + for(unsigned j = 1U; j <= n; j++) + { + sum += func(a + (value_type((j * 2) - 1) * h)); + } + + const value_type I0 = I; + I = (I / 2) + (h * sum); + + const value_type ratio = I0 / I; + const value_type delta = ratio - 1; + const value_type delta_abs = ((delta < 0) ? -delta : delta); + + if((k > 1U) && (delta_abs < tol)) + { + break; + } + + n *= 2U; + } + + return I; +} + +/*` +The following sample program shows how the function can be called, we begin +by defining a function object, which when integrated should yield the Bessel J +function: +*/ + +template +class cyl_bessel_j_integral_rep +{ +public: + cyl_bessel_j_integral_rep(const unsigned N, + const value_type& X) : n(N), x(X) { } + + value_type operator()(const value_type& t) const + { + // pi * Jn(x) = Int_0^pi [cos(x * sin(t) - n*t) dt] + return cos(x * sin(t) - (n * t)); + } + +private: + const unsigned n; + const value_type x; +}; + + +//] + +//[POLY + +/*` +In this example we'll look at polynomial evaluation, this is not only an important +use case, but it's one that `number` performs particularly well at because the +expression templates ['completely eliminate all temporaries] from a +[@http://en.wikipedia.org/wiki/Horner%27s_method Horner polynomial +evaluation scheme]. + +The following code evaluates `sin(x)` as a polynomial, accurate to at least 64 decimal places: + +*/ + +using boost::multiprecision::cpp_dec_float; +typedef boost::multiprecision::number > mp_type; + +mp_type mysin(const mp_type& x) +{ + // Approximation of sin(x * pi/2) for -1 <= x <= 1, using an order 63 polynomial. + static const std::array coefs = + {{ + mp_type("+1.5707963267948966192313216916397514420985846996875529104874722961539082031431044993140174126711"), //"), + mp_type("-0.64596409750624625365575656389794573337969351178927307696134454382929989411386887578263960484"), // ^3 + mp_type("+0.07969262624616704512050554949047802252091164235106119545663865720995702920146198554317279"), // ^5 + mp_type("-0.0046817541353186881006854639339534378594950280185010575749538605102665157913157426229824"), // ^7 + mp_type("+0.00016044118478735982187266087016347332970280754062061156858775174056686380286868007443"), // ^9 + mp_type("-3.598843235212085340458540018208389404888495232432127661083907575106196374913134E-6"), // ^11 + mp_type("+5.692172921967926811775255303592184372902829756054598109818158853197797542565E-8"), // ^13 + mp_type("-6.688035109811467232478226335783138689956270985704278659373558497256423498E-10"), // ^15 + mp_type("+6.066935731106195667101445665327140070166203261129845646380005577490472E-12"), // ^17 + mp_type("-4.377065467313742277184271313776319094862897030084226361576452003432E-14"), // ^19 + mp_type("+2.571422892860473866153865950420487369167895373255729246889168337E-16"), // ^21 + mp_type("-1.253899540535457665340073300390626396596970180355253776711660E-18"), // ^23 + mp_type("+5.15645517658028233395375998562329055050964428219501277474E-21"), // ^25 + mp_type("-1.812399312848887477410034071087545686586497030654642705E-23"), // ^27 + mp_type("+5.50728578652238583570585513920522536675023562254864E-26"), // ^29 + mp_type("-1.461148710664467988723468673933026649943084902958E-28"), // ^31 + mp_type("+3.41405297003316172502972039913417222912445427E-31"), // ^33 + mp_type("-7.07885550810745570069916712806856538290251E-34"), // ^35 + mp_type("+1.31128947968267628970845439024155655665E-36"), // ^37 + mp_type("-2.18318293181145698535113946654065918E-39"), // ^39 + mp_type("+3.28462680978498856345937578502923E-42"), // ^41 + mp_type("-4.48753699028101089490067137298E-45"), // ^43 + mp_type("+5.59219884208696457859353716E-48"), // ^45 + mp_type("-6.38214503973500471720565E-51"), // ^47 + mp_type("+6.69528558381794452556E-54"), // ^49 + mp_type("-6.47841373182350206E-57"), // ^51 + mp_type("+5.800016389666445E-60"), // ^53 + mp_type("-4.818507347289E-63"), // ^55 + mp_type("+3.724683686E-66"), // ^57 + mp_type("-2.6856479E-69"), // ^59 + mp_type("+1.81046E-72"), // ^61 + mp_type("-1.133E-75"), // ^63 + }}; + + const mp_type v = x * 2 / boost::math::constants::pi(); + const mp_type x2 = (v * v); + // + // Polynomial evaluation follows, if mp_type allocates memory then + // just one such allocation occurs - to initialize the variable "sum" - + // and no temporaries are created at all. + // + const mp_type sum = ((((((((((((((((((((((((((((((( + coefs[31U] + * x2 + coefs[30U]) + * x2 + coefs[29U]) + * x2 + coefs[28U]) + * x2 + coefs[27U]) + * x2 + coefs[26U]) + * x2 + coefs[25U]) + * x2 + coefs[24U]) + * x2 + coefs[23U]) + * x2 + coefs[22U]) + * x2 + coefs[21U]) + * x2 + coefs[20U]) + * x2 + coefs[19U]) + * x2 + coefs[18U]) + * x2 + coefs[17U]) + * x2 + coefs[16U]) + * x2 + coefs[15U]) + * x2 + coefs[14U]) + * x2 + coefs[13U]) + * x2 + coefs[12U]) + * x2 + coefs[11U]) + * x2 + coefs[10U]) + * x2 + coefs[9U]) + * x2 + coefs[8U]) + * x2 + coefs[7U]) + * x2 + coefs[6U]) + * x2 + coefs[5U]) + * x2 + coefs[4U]) + * x2 + coefs[3U]) + * x2 + coefs[2U]) + * x2 + coefs[1U]) + * x2 + coefs[0U]) + * v; + + return sum; +} + +/*` +Calling the function like so: + + mp_type pid4 = boost::math::constants::pi() / 4; + std::cout << std::setprecision(std::numeric_limits< ::mp_type>::digits10) << std::scientific; + std::cout << mysin(pid4) << std::endl; + +Yields the expected output: + +[pre 7.0710678118654752440084436210484903928483593768847403658833986900e-01] + +*/ + +//] + + +int main() +{ + using namespace boost::multiprecision; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL1(2.5, 0.5) << std::endl; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL2(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL3(2.5, 0.5) << std::endl; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL3(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl; + std::cout << std::scientific << std::setprecision(std::numeric_limits::digits10); + std::cout << JEL4(cpp_dec_float_100(2) + 0.5, cpp_dec_float_100(0.5)) << std::endl; + + //[AOS2 + +/*=#include +#include +#include + +using boost::multiprecision::cpp_dec_float_50; + +int main(int, char**) +{*/ + const float r_f(float(123) / 100); + const float a_f = area_of_a_circle(r_f); + + const double r_d(double(123) / 100); + const double a_d = area_of_a_circle(r_d); + + const cpp_dec_float_50 r_mp(cpp_dec_float_50(123) / 100); + const cpp_dec_float_50 a_mp = area_of_a_circle(r_mp); + + // 4.75292 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << a_f + << std::endl; + + // 4.752915525616 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << a_d + << std::endl; + + // 4.7529155256159981904701331745635599135018975843146 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << a_mp + << std::endl; +/*=}*/ + + //] + + //[ND2 +/*= +#include +#include +#include +#include + + +int main(int, char**) +{*/ + using boost::math::constants::pi; + using boost::multiprecision::cpp_dec_float_50; + // + // We'll pass a function pointer for the function object passed to derivative, + // the typecast is needed to select the correct overload of std::sin: + // + const float d_f = derivative( + pi() / 3, + 0.01F, + static_cast(std::sin) + ); + + const double d_d = derivative( + pi() / 3, + 0.001, + static_cast(std::sin) + ); + // + // In the cpp_dec_float_50 case, the sin function is multiply overloaded + // to handle expression templates etc. As a result it's hard to take its + // address without knowing about its implementation details. We'll use a + // C++11 lambda expression to capture the call. + // We also need a typecast on the first argument so we don't accidently pass + // an expression template to a template function: + // + const cpp_dec_float_50 d_mp = derivative( + cpp_dec_float_50(pi() / 3), + cpp_dec_float_50(1.0E-9), + [](const cpp_dec_float_50& x) -> cpp_dec_float_50 + { + return sin(x); + } + ); + + // 5.000029e-001 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << d_f + << std::endl; + + // 4.999999999998876e-001 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << d_d + << std::endl; + + // 4.99999999999999999999999999999999999999999999999999e-01 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << d_mp + << std::endl; +//=} + + /*` + The expected value of the derivative is 0.5. This central difference rule in this + example is ill-conditioned, meaning it suffers from slight loss of precision. With that + in mind, the results agree with the expected value of 0.5.*/ + + //] + + //[ND3 + + /*` + We can take this a step further and use our derivative function to compute + a partial derivative. For example if we take the incomplete gamma function + ['P(a, z)], and take the derivative with respect to /z/ at /(2,2)/ then we + can calculate the result as shown below, for good measure we'll compare with + the "correct" result obtained from a call to ['gamma_p_derivative], the results + agree to approximately 44 digits: + */ + + cpp_dec_float_50 gd = derivative( + cpp_dec_float_50(2), + cpp_dec_float_50(1.0E-9), + [](const cpp_dec_float_50& x) ->cpp_dec_float_50 + { + return boost::math::gamma_p(2, x); + } + ); + // 2.70670566473225383787998989944968806815263091819151e-01 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << gd + << std::endl; + // 2.70670566473225383787998989944968806815253190143120e-01 + std::cout << boost::math::gamma_p_derivative(cpp_dec_float_50(2), cpp_dec_float_50(2)) << std::endl; + //] + + //[GI2 + + /* The function can now be called as follows: */ +/*=int main(int, char**) +{*/ + using boost::math::constants::pi; + typedef boost::multiprecision::cpp_dec_float_50 mp_type; + + const float j2_f = + integral(0.0F, + pi(), + 0.01F, + cyl_bessel_j_integral_rep(2U, 1.23F)) / pi(); + + const double j2_d = + integral(0.0, + pi(), + 0.0001, + cyl_bessel_j_integral_rep(2U, 1.23)) / pi(); + + const mp_type j2_mp = + integral(mp_type(0), + pi(), + mp_type(1.0E-20), + cyl_bessel_j_integral_rep(2U, mp_type(123) / 100)) / pi(); + + // 0.166369 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << j2_f + << std::endl; + + // 0.166369383786814 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << j2_d + << std::endl; + + // 0.16636938378681407351267852431513159437103348245333 + std::cout + << std::setprecision(std::numeric_limits::digits10) + << j2_mp + << std::endl; + + // + // Print true value for comparison: + // 0.166369383786814073512678524315131594371033482453329 + std::cout << boost::math::cyl_bessel_j(2, mp_type(123) / 100) << std::endl; +//=} + + //] + + std::cout << std::setprecision(std::numeric_limits< ::mp_type>::digits10) << std::scientific; + std::cout << mysin(boost::math::constants::pi< ::mp_type>() / 4) << std::endl; + std::cout << boost::multiprecision::sin(boost::math::constants::pi< ::mp_type>() / 4) << std::endl; + + return 0; +} + +/* + +Program output: + +9.822663964796047e-001 +9.82266396479604757017335009796882833995903762577173e-01 +9.822663964796047e-001 +9.82266396479604757017335009796882833995903762577173e-01 +9.8226639647960475701733500979688283399590376257717309069410413822165082248153638454147004236848917775e-01 +4.752916e+000 +4.752915525615998e+000 +4.75291552561599819047013317456355991350189758431460e+00 +5.000029e-001 +4.999999999998876e-001 +4.99999999999999999999999999999999999999999999999999e-01 +2.70670566473225383787998989944968806815263091819151e-01 +2.70670566473225383787998989944968806815253190143120e-01 +7.0710678118654752440084436210484903928483593768847403658833986900e-01 +7.0710678118654752440084436210484903928483593768847403658833986900e-01 +*/ diff --git a/example/gmp_snips.cpp b/example/gmp_snips.cpp new file mode 100644 index 00000000..4ea36103 --- /dev/null +++ b/example/gmp_snips.cpp @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include + +void t1() +{ + //[mpz_eg + //=#include + + using namespace boost::multiprecision; + + mpz_int v = 1; + + // Do some arithmetic: + for(unsigned i = 1; i <= 1000; ++i) + v *= i; + + std::cout << v << std::endl; // prints 1000! + + // Access the underlying representation: + mpz_t z; + mpz_init(z); + mpz_set(z, v.backend().data()); + //] +} + +void t2() +{ + //[mpf_eg + //=#include + + using namespace boost::multiprecision; + + // Operations at variable precision and limited standard library support: + mpf_float a = 2; + mpf_float::default_precision(1000); + std::cout << mpf_float::default_precision() << std::endl; + std::cout << sqrt(a) << std::endl; // print root-2 + + // Operations at fixed precision and full standard library support: + mpf_float_100 b = 2; + std::cout << std::numeric_limits::digits << std::endl; + // We can use any C++ std lib function: + std::cout << log(b) << std::endl; // print log(2) + // We can also use any function from Boost.Math: + std::cout << boost::math::tgamma(b) << std::endl; + // These even work when the argument is an expression template: + std::cout << boost::math::tgamma(b * b) << std::endl; + + // Access the underlying representation: + mpf_t f; + mpf_init(f); + mpf_set(f, a.backend().data()); + //] +} + +void t3() +{ + //[mpq_eg + //=#include + + using namespace boost::multiprecision; + + mpq_rational v = 1; + + // Do some arithmetic: + for(unsigned i = 1; i <= 1000; ++i) + v *= i; + v /= 10; + + std::cout << v << std::endl; // prints 1000! / 10 + std::cout << numerator(v) << std::endl; + std::cout << denominator(v) << std::endl; + + mpq_rational w(2, 3); // component wise constructor + std::cout << w << std::endl; // prints 2/3 + + // Access the underlying data: + mpq_t q; + mpq_init(q); + mpq_set(q, v.backend().data()); + //] +} + +int main() +{ + t1(); + t2(); + t3(); + return 0; +} + diff --git a/example/integer_examples.cpp b/example/integer_examples.cpp new file mode 100644 index 00000000..0b2edbbd --- /dev/null +++ b/example/integer_examples.cpp @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include +#include + +//[FAC1 + +/*` +In this simple example, we'll write a routine to print out all of the factorials +which will fit into a 128-bit integer. At the end of the routine we do some +fancy iostream formatting of the results: +*/ +/*= +#include +#include +#include +#include +*/ + +void print_factorials() +{ + using boost::multiprecision::cpp_int; + // + // Print all the factorials that will fit inside a 128-bit integer. + // + // Begin by building a big table of factorials, once we know just how + // large the largest is, we'll be able to "pretty format" the results. + // + // Calculate the largest number that will fit inside 128 bits, we could + // also have used numeric_limits::max() for this value: + cpp_int limit = (cpp_int(1) << 128) - 1; + // + // Our table of values: + std::vector results; + // + // Initial values: + unsigned i = 1; + cpp_int factorial = 1; + // + // Cycle through the factorials till we reach the limit: + while(factorial < limit) + { + results.push_back(factorial); + ++i; + factorial *= i; + } + // + // Lets see how many digits the largest factorial was: + unsigned digits = results.back().str().size(); + // + // Now print them out, using right justification, while we're at it + // we'll indicate the limit of each integer type, so begin by defining + // the limits for 16, 32, 64 etc bit integers: + cpp_int limits[] = { + (cpp_int(1) << 16) - 1, + (cpp_int(1) << 32) - 1, + (cpp_int(1) << 64) - 1, + (cpp_int(1) << 128) - 1, + }; + std::string bit_counts[] = { "16", "32", "64", "128" }; + unsigned current_limit = 0; + for(unsigned j = 0; j < results.size(); ++j) + { + if(limits[current_limit] < results[j]) + { + std::string message = "Limit of " + bit_counts[current_limit] + " bit integers"; + std::cout << std::setfill('.') << std::setw(digits+1) << std::right << message << std::setfill(' ') << std::endl; + ++current_limit; + } + std::cout << std::setw(digits + 1) << std::right << results[j] << std::endl; + } +} + +/*` +The output from this routine is: +[template nul[]] [# fix for quickbook bug] +[pre [nul] + 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 +................Limit of 16 bit integers + 362880 + 3628800 + 39916800 + 479001600 +................Limit of 32 bit integers + 6227020800 + 87178291200 + 1307674368000 + 20922789888000 + 355687428096000 + 6402373705728000 + 121645100408832000 + 2432902008176640000 +................Limit of 64 bit integers + 51090942171709440000 + 1124000727777607680000 + 25852016738884976640000 + 620448401733239439360000 + 15511210043330985984000000 + 403291461126605635584000000 + 10888869450418352160768000000 + 304888344611713860501504000000 + 8841761993739701954543616000000 + 265252859812191058636308480000000 + 8222838654177922817725562880000000 + 263130836933693530167218012160000000 + 8683317618811886495518194401280000000 + 295232799039604140847618609643520000000 +] +*/ + +//] + +//[BITOPS + +/*` +In this example we'll show how individual bits within an integer may be manipulated, +we'll start with an often needed calculation of ['2[super n] - 1], which we could obviously +implement like this: +*/ + +using boost::multiprecision::cpp_int; + +cpp_int b1(unsigned n) +{ + cpp_int r(1); + return (r << n) - 1; +} + +/*` +Calling: + + std::cout << std::hex << std::showbase << b1(200) << std::endl; + +Yields as expected: + +[pre 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF] + +However, we could equally just set the n'th bit in the result, like this: +*/ + +cpp_int b2(unsigned n) +{ + cpp_int r(0); + return --bit_set(r, n); +} + +/*` +Note how the `bit_set` function sets the specified bit in its argument and then returns a reference to the result - +which we can then simply decrement. The result from a call to `b2` is the same as that to `b1`. + +We can equally test bits, so for example the n'th bit of the result returned from `b2` shouldn't be set +unless we increment it first: + + assert(!bit_test(b1(200), 200)); // OK + assert(bit_test(++b1(200), 200)); // OK + +And of course if we flip the n'th bit after increment, then we should get back to zero: + + assert(!bit_flip(++b1(200), 200)); // OK +*/ + +//] + +int main() +{ + print_factorials(); + + std::cout << std::hex << std::showbase << b1(200) << std::endl; + std::cout << std::hex << std::showbase << b2(200) << std::endl; + assert(!bit_test(b1(200), 200)); // OK + assert(bit_test(++b1(200), 200)); // OK + assert(!bit_flip(++b1(200), 200)); // OK + return 0; +} + +/* + +Program output: + + 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 +................Limit of 16 bit integers + 362880 + 3628800 + 39916800 + 479001600 +................Limit of 32 bit integers + 6227020800 + 87178291200 + 1307674368000 + 20922789888000 + 355687428096000 + 6402373705728000 + 121645100408832000 + 2432902008176640000 +................Limit of 64 bit integers + 51090942171709440000 + 1124000727777607680000 + 25852016738884976640000 + 620448401733239439360000 + 15511210043330985984000000 + 403291461126605635584000000 + 10888869450418352160768000000 + 304888344611713860501504000000 + 8841761993739701954543616000000 + 265252859812191058636308480000000 + 8222838654177922817725562880000000 + 263130836933693530167218012160000000 + 8683317618811886495518194401280000000 + 295232799039604140847618609643520000000 + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + */ \ No newline at end of file diff --git a/example/mixed_integer_arithmetic.cpp b/example/mixed_integer_arithmetic.cpp new file mode 100644 index 00000000..7348b474 --- /dev/null +++ b/example/mixed_integer_arithmetic.cpp @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include + +int main() +{ + //[mixed_eg + //=#include + + using namespace boost::multiprecision; + + boost::uint64_t i = (std::numeric_limits::max)(); + boost::uint64_t j = 1; + + uint128_t ui128; + uint256_t ui256; + // + // Start by performing arithmetic on 64-bit integers to yield 128-bit results: + // + std::cout << std::hex << std::showbase << i << std::endl; + std::cout << std::hex << std::showbase << add(ui128, i, j) << std::endl; + std::cout << std::hex << std::showbase << multiply(ui128, i, i) << std::endl; + // + // The try squaring a 128-bit integer to yield a 256-bit result: + // + ui128 = (std::numeric_limits::max)(); + std::cout << std::hex << std::showbase << multiply(ui256, ui128, ui128) << std::endl; + + //] + + return 0; +} + +/* + +Program output: + +//[mixed_output + +0xffffffffffffffff +0x10000000000000000 +0xFFFFFFFFFFFFFFFE0000000000000001 +0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000001 + +//] +*/ + diff --git a/example/mpfr_snips.cpp b/example/mpfr_snips.cpp new file mode 100644 index 00000000..dfecf5e9 --- /dev/null +++ b/example/mpfr_snips.cpp @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include + +void t1() +{ + //[mpfr_eg + //=#include + + using namespace boost::multiprecision; + + // Operations at variable precision and no numeric_limits support: + mpfr_float a = 2; + mpfr_float::default_precision(1000); + std::cout << mpfr_float::default_precision() << std::endl; + std::cout << sqrt(a) << std::endl; // print root-2 + + // Operations at fixed precision and full numeric_limits support: + mpfr_float_100 b = 2; + std::cout << std::numeric_limits::digits << std::endl; + // We can use any C++ std lib function: + std::cout << log(b) << std::endl; // print log(2) + // We can also use any function from Boost.Math: + std::cout << boost::math::tgamma(b) << std::endl; + // These even work when the argument is an expression template: + std::cout << boost::math::tgamma(b * b) << std::endl; + + // Access the underlying data: + mpfr_t r; + mpfr_init(r); + mpfr_set(r, b.backend().data(), GMP_RNDN); + //] +} + +int main() +{ + t1(); + return 0; +} + + + diff --git a/example/random_snips.cpp b/example/random_snips.cpp new file mode 100644 index 00000000..8880f06e --- /dev/null +++ b/example/random_snips.cpp @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include +#include +#include + +void t1() +{ + //[random_eg1 + //=#include + //=#include + + using namespace boost::multiprecision; + using namespace boost::random; + + // + // Declare our random number generator type, the underlying generator + // is the Mersenne twister mt19937 engine, and 256 bits are generated: + // + typedef independent_bits_engine generator_type; + generator_type gen; + // + // Generate some values: + // + std::cout << std::hex << std::showbase; + for(unsigned i = 0; i < 10; ++i) + std::cout << gen() << std::endl; + //] +} + +void t2() +{ + //[random_eg2 + //=#include + //=#include + + using namespace boost::multiprecision; + using namespace boost::random; + + // + // Generate integers in a given range using uniform_int, + // the underlying generator is invoked multiple times + // to generate enough bits: + // + mt19937 mt; + uniform_int_distribution ui(0, mpz_int(1) << 256); + // + // Generate the numbers: + // + std::cout << std::hex << std::showbase; + for(unsigned i = 0; i < 10; ++i) + std::cout << ui(mt) << std::endl; + + //] +} + +void t3() +{ + //[random_eg3 + //=#include + //=#include + + using namespace boost::multiprecision; + using namespace boost::random; + // + // We need an underlying generator with at least as many bits as the + // floating point type to generate numbers in [0, 1) with all the bits + // in the floating point type randomly filled: + // + uniform_01 uf; + independent_bits_engine gen; + // + // Generate the values: + // + std::cout << std::setprecision(50); + for(unsigned i = 0; i < 20; ++i) + std::cout << uf(gen) << std::endl; + //] +} + +void t4() +{ + //[random_eg4 + //=#include + //=#include + + using namespace boost::multiprecision; + using namespace boost::random; + // + // We can repeat the above example, with other distributions: + // + uniform_real_distribution ur(-20, 20); + gamma_distribution gd(20); + independent_bits_engine gen; + // + // Generate some values: + // + std::cout << std::setprecision(50); + for(unsigned i = 0; i < 20; ++i) + std::cout << ur(gen) << std::endl; + for(unsigned i = 0; i < 20; ++i) + std::cout << gd(gen) << std::endl; + //] +} + +int main() +{ + t1(); + t2(); + t3(); + t4(); + return 0; +} + diff --git a/example/safe_prime.cpp b/example/safe_prime.cpp new file mode 100644 index 00000000..71adf4f3 --- /dev/null +++ b/example/safe_prime.cpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +//[safe_prime + +#include +#include +#include +#include + +int main() +{ + using namespace boost::random; + using namespace boost::multiprecision; + + typedef cpp_int int_type; + mt11213b base_gen(clock()); + independent_bits_engine gen(base_gen); + // + // We must use a different generator for the tests and number generation, otherwise + // we get false positives. + // + mt19937 gen2(clock()); + + for(unsigned i = 0; i < 100000; ++i) + { + int_type n = gen(); + if(miller_rabin_test(n, 25, gen2)) + { + // Value n is probably prime, see if (n-1)/2 is also prime: + std::cout << "We have a probable prime with value: " << std::hex << std::showbase << n << std::endl; + if(miller_rabin_test((n-1)/2, 25, gen2)) + { + std::cout << "We have a safe prime with value: " << std::hex << std::showbase << n << std::endl; + return 0; + } + } + } + std::cout << "Ooops, no safe primes were found" << std::endl; + return 1; +} + +//] diff --git a/example/tommath_snips.cpp b/example/tommath_snips.cpp new file mode 100644 index 00000000..6c0f73d2 --- /dev/null +++ b/example/tommath_snips.cpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include +#include + +void t1() +{ + //[tommath_eg + //=#include + + boost::multiprecision::tom_int v = 1; + + // Do some arithmetic: + for(unsigned i = 1; i <= 1000; ++i) + v *= i; + + std::cout << v << std::endl; // prints 1000! + std::cout << std::hex << v << std::endl; // prints 1000! in hex format + + try{ + std::cout << std::hex << -v << std::endl; // Ooops! can't print a negative value in hex format! + } + catch(const std::runtime_error& e) + { + std::cout << e.what() << std::endl; + } + + try{ + // v is not a 2's complement type, bitwise operations are only supported + // on positive values: + v = -v & 2; + } + catch(const std::runtime_error& e) + { + std::cout << e.what() << std::endl; + } + + //] +} + +void t3() +{ + //[mp_rat_eg + //=#include + + using namespace boost::multiprecision; + + tom_rational v = 1; + + // Do some arithmetic: + for(unsigned i = 1; i <= 1000; ++i) + v *= i; + v /= 10; + + std::cout << v << std::endl; // prints 1000! / 10 + std::cout << numerator(v) << std::endl; + std::cout << denominator(v) << std::endl; + + tom_rational w(2, 3); // Component wise constructor + std::cout << w << std::endl; // prints 2/3 + + //] +} + +int main() +{ + t1(); + return 0; +} + diff --git a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp new file mode 100644 index 00000000..6c33ee76 --- /dev/null +++ b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MATH_CONCEPTS_ER_HPP +#define BOOST_MATH_CONCEPTS_ER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace multiprecision{ +namespace concepts{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4244) +#endif + +struct number_backend_float_architype +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef int exponent_type; + + number_backend_float_architype() + { + std::cout << "Default construct" << std::endl; + } + number_backend_float_architype(const number_backend_float_architype& o) + { + std::cout << "Copy construct" << std::endl; + m_value = o.m_value; + } + number_backend_float_architype& operator = (const number_backend_float_architype& o) + { + m_value = o.m_value; + std::cout << "Assignment (" << m_value << ")" << std::endl; + return *this; + } + number_backend_float_architype& operator = (unsigned long long i) + { + m_value = i; + std::cout << "UInt Assignment (" << i << ")" << std::endl; + return *this; + } + number_backend_float_architype& operator = (long long i) + { + m_value = i; + std::cout << "Int Assignment (" << i << ")" << std::endl; + return *this; + } + number_backend_float_architype& operator = (long double d) + { + m_value = d; + std::cout << "long double Assignment (" << d << ")" << std::endl; + return *this; + } + number_backend_float_architype& operator = (const char* s) + { + try + { + m_value = boost::lexical_cast(s); + } + catch(const std::exception&) + { + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse input string: \"") + s + std::string("\" as a valid floating point number."))); + } + std::cout << "const char* Assignment (" << s << ")" << std::endl; + return *this; + } + void swap(number_backend_float_architype& o) + { + std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl; + std::swap(m_value, o.m_value); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + std::stringstream ss; + ss.flags(f); + if(digits) + ss.precision(digits); + else + ss.precision(std::numeric_limits::digits10 + 2); + boost::intmax_t i = m_value; + boost::uintmax_t u = m_value; + if(!(f & std::ios_base::scientific) && m_value == i) + ss << i; + else if(!(f & std::ios_base::scientific) && m_value == u) + ss << u; + else + ss << m_value; + std::string s = ss.str(); + std::cout << "Converting to string (" << s << ")" << std::endl; + return s; + } + void negate() + { + std::cout << "Negating (" << m_value << ")" << std::endl; + m_value = -m_value; + } + int compare(const number_backend_float_architype& o)const + { + std::cout << "Comparison" << std::endl; + return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); + } + int compare(long long i)const + { + std::cout << "Comparison with int" << std::endl; + return m_value > i ? 1 : (m_value < i ? -1 : 0); + } + int compare(unsigned long long i)const + { + std::cout << "Comparison with unsigned" << std::endl; + return m_value > i ? 1 : (m_value < i ? -1 : 0); + } + int compare(long double d)const + { + std::cout << "Comparison with long double" << std::endl; + return m_value > d ? 1 : (m_value < d ? -1 : 0); + } + long double m_value; +}; + +inline void eval_add(number_backend_float_architype& result, const number_backend_float_architype& o) +{ + std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl; + result.m_value += o.m_value; +} +inline void eval_subtract(number_backend_float_architype& result, const number_backend_float_architype& o) +{ + std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl; + result.m_value -= o.m_value; +} +inline void eval_multiply(number_backend_float_architype& result, const number_backend_float_architype& o) +{ + std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl; + result.m_value *= o.m_value; +} +inline void eval_divide(number_backend_float_architype& result, const number_backend_float_architype& o) +{ + std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl; + result.m_value /= o.m_value; +} + +inline void eval_convert_to(unsigned long long* result, const number_backend_float_architype& val) +{ + *result = static_cast(val.m_value); +} +inline void eval_convert_to(long long* result, const number_backend_float_architype& val) +{ + *result = static_cast(val.m_value); +} +inline void eval_convert_to(long double* result, number_backend_float_architype& val) +{ + *result = val.m_value; +} + +inline void eval_frexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int* exp) +{ + result = std::frexp(arg.m_value, exp); +} + +inline void eval_ldexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int exp) +{ + result = std::ldexp(arg.m_value, exp); +} + +inline void eval_floor(number_backend_float_architype& result, const number_backend_float_architype& arg) +{ + result = std::floor(arg.m_value); +} + +inline void eval_ceil(number_backend_float_architype& result, const number_backend_float_architype& arg) +{ + result = std::ceil(arg.m_value); +} + +inline void eval_sqrt(number_backend_float_architype& result, const number_backend_float_architype& arg) +{ + result = std::sqrt(arg.m_value); +} + +inline int eval_fpclassify(const number_backend_float_architype& arg) +{ + return (boost::math::fpclassify)(arg.m_value); +} + +typedef boost::multiprecision::number mp_number_float_architype; + +} // namespace + +template<> +struct number_category : public mpl::int_{}; + +}} // namespaces + +namespace std{ + +template +class numeric_limits > : public std::numeric_limits +{ + typedef std::numeric_limits base_type; + typedef boost::multiprecision::number number_type; +public: + static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } + static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } + static number_type lowest() BOOST_NOEXCEPT { return -(max)(); } + static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } + static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } + static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } + static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } +}; + +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp new file mode 100644 index 00000000..3e31b257 --- /dev/null +++ b/include/boost/multiprecision/cpp_dec_float.hpp @@ -0,0 +1,3027 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2012. +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// + +#ifndef BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP +#define BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP + +#include +#include +#include +#include +#include + +// +// Headers required for Boost.Math integration: +// +#include + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +template +class cpp_dec_float; + +} // namespace + +template +struct number_category > : public mpl::int_{}; + +namespace backends{ + +namespace detail{ + +template +struct rebind +{ + typedef typename Allocator::template rebind::other type; +}; + +template +struct dynamic_array : public std::vector::type> +{ + dynamic_array() + : std::vector::type>(static_cast::type>::size_type>(S), static_cast(0)) {} +}; + +} + +template +class cpp_dec_float +{ +private: + static const boost::int32_t cpp_dec_float_digits10_setting = Digits10; + +public: + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef ExponentType exponent_type; + + static const boost::int32_t cpp_dec_float_radix = 10L; + static const boost::int32_t cpp_dec_float_digits10_limit_lo = 9L; + static const boost::int32_t cpp_dec_float_digits10_limit_hi = boost::integer_traits::const_max - 100; + static const boost::int32_t cpp_dec_float_digits10 = ((cpp_dec_float_digits10_setting < cpp_dec_float_digits10_limit_lo) ? cpp_dec_float_digits10_limit_lo : ((cpp_dec_float_digits10_setting > cpp_dec_float_digits10_limit_hi) ? cpp_dec_float_digits10_limit_hi : cpp_dec_float_digits10_setting)); + static const ExponentType cpp_dec_float_max_exp10 = (static_cast(1) << (std::numeric_limits::digits - 5)); + static const ExponentType cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10; + static const ExponentType cpp_dec_float_max_exp = static_cast((cpp_dec_float_max_exp10 / 301LL) * 1000LL); + static const ExponentType cpp_dec_float_min_exp = static_cast((cpp_dec_float_min_exp10 / 301LL) * 1000LL); + + BOOST_STATIC_ASSERT((cpp_dec_float::cpp_dec_float_max_exp10 == -cpp_dec_float::cpp_dec_float_min_exp10)); + +private: + static const boost::int32_t cpp_dec_float_elem_digits10 = 8L; + static const boost::int32_t cpp_dec_float_elem_mask = 100000000L; + + BOOST_STATIC_ASSERT(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10); + + // There are three guard limbs. + // 1) The first limb has 'play' from 1...8 decimal digits. + // 2) The last limb also has 'play' from 1...8 decimal digits. + // 3) One limb can get lost when justifying after multiply, + // as only half of the triangle is multiplied and a carry + // from below is missing. + static const boost::int32_t cpp_dec_float_elem_number_request = static_cast((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + (((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); + + // The number of elements needed (with a minimum of two) plus three added guard limbs. + static const boost::int32_t cpp_dec_float_elem_number = static_cast(((cpp_dec_float_elem_number_request < 2L) ? 2L : cpp_dec_float_elem_number_request) + 3L); + +public: + static const boost::int32_t cpp_dec_float_total_digits10 = static_cast(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10); + +private: + + typedef enum enum_fpclass_type + { + cpp_dec_float_finite, + cpp_dec_float_inf, + cpp_dec_float_NaN + } + fpclass_type; + + typedef typename mpl::if_, + boost::array, + detail::dynamic_array + >::type array_type; + + array_type data; + ExponentType exp; + bool neg; + fpclass_type fpclass; + boost::int32_t prec_elem; + + // + // Special values constructor: + // + cpp_dec_float(fpclass_type c) BOOST_NOEXCEPT : + data(), + exp (static_cast(0)), + neg (false), + fpclass (c), + prec_elem(cpp_dec_float_elem_number) { } + + // + // Static data initializer: + // + struct initializer + { + initializer() + { + cpp_dec_float::nan(); + cpp_dec_float::inf(); + (cpp_dec_float::min)(); + (cpp_dec_float::max)(); + cpp_dec_float::zero(); + cpp_dec_float::one(); + cpp_dec_float::two(); + cpp_dec_float::half(); + cpp_dec_float::double_min(); + cpp_dec_float::double_max(); + cpp_dec_float::long_double_max(); + cpp_dec_float::long_double_min(); + cpp_dec_float::long_long_max(); + cpp_dec_float::long_long_min(); + cpp_dec_float::ulong_long_max(); + cpp_dec_float::eps(); + cpp_dec_float::pow2(0); + } + void do_nothing(){} + }; + + static initializer init; + +public: + // Constructors + cpp_dec_float() BOOST_NOEXCEPT : + data(), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) { } + + cpp_dec_float(const char* s) : + data(), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) + { + *this = s; + } + + template + cpp_dec_float(I i, typename enable_if >::type* = 0) BOOST_NOEXCEPT : + data(), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) + { + from_unsigned_long_long(i); + } + + template + cpp_dec_float(I i, typename enable_if >::type* = 0) BOOST_NOEXCEPT : + data(), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) + { + if(i < 0) + { + from_unsigned_long_long(-i); + negate(); + } + else + from_unsigned_long_long(i); + } + + cpp_dec_float(const cpp_dec_float& f) BOOST_NOEXCEPT : + data (f.data), + exp (f.exp), + neg (f.neg), + fpclass (f.fpclass), + prec_elem(f.prec_elem) { } + + template + cpp_dec_float(const cpp_dec_float& f, typename enable_if_c::type* = 0) BOOST_NOEXCEPT : + data(), + exp (f.exp), + neg (f.neg), + fpclass (static_cast(static_cast(f.fpclass))), + prec_elem(cpp_dec_float_elem_number) + { + std::copy(f.data.begin(), f.data.begin() + f.prec_elem, data.begin()); + } + template + explicit cpp_dec_float(const cpp_dec_float& f, typename disable_if_c::type* = 0) BOOST_NOEXCEPT : + data(), + exp (f.exp), + neg (f.neg), + fpclass (static_cast(static_cast(f.fpclass))), + prec_elem(cpp_dec_float_elem_number) + { + // TODO: this doesn't round! + std::copy(f.data.begin(), f.data.begin() + prec_elem, data.begin()); + } + + template + cpp_dec_float(const F val, typename enable_if >::type* = 0) BOOST_NOEXCEPT : + data(), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) + { + *this = val; + } + + cpp_dec_float(const double val, ExponentType exponent) BOOST_NOEXCEPT; + + // Specific special values. + static const cpp_dec_float& nan() BOOST_NOEXCEPT + { + static const cpp_dec_float val(cpp_dec_float_NaN); + init.do_nothing(); + return val; + } + static const cpp_dec_float& inf() BOOST_NOEXCEPT + { + static const cpp_dec_float val(cpp_dec_float_inf); + init.do_nothing(); + return val; + } + static const cpp_dec_float& (max)() BOOST_NOEXCEPT + { + init.do_nothing(); + static bool init = false; + static const std::string str_max = std::string("9." + std::string(static_cast(cpp_dec_float_total_digits10), static_cast('9'))) + + std::string("e+" + boost::lexical_cast(cpp_dec_float_max_exp10)); + static cpp_dec_float val_max; + if(!init) + { + init = true; + val_max = str_max.c_str(); + } + return val_max; + } + + static const cpp_dec_float& (min)() BOOST_NOEXCEPT + { + init.do_nothing(); + static bool init = false; + static cpp_dec_float val_min; + if(!init) + { + init = true; + val_min = std::string("1.0e" + boost::lexical_cast(cpp_dec_float_min_exp10)).c_str(); + } + return val_min; + } + static const cpp_dec_float& zero() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(static_cast(0u)); + return val; + } + static const cpp_dec_float& one() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(static_cast(1u)); + return val; + } + static const cpp_dec_float& two() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(static_cast(2u)); + return val; + } + static const cpp_dec_float& half() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(0.5L); + return val; + } + static const cpp_dec_float& double_min() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(static_cast((std::numeric_limits::min)())); + return val; + } + static const cpp_dec_float& double_max() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(static_cast((std::numeric_limits::max)())); + return val; + } + static const cpp_dec_float& long_double_min() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val((std::numeric_limits::min)()); + return val; + } + static const cpp_dec_float& long_double_max() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val((std::numeric_limits::max)()); + return val; + } + static const cpp_dec_float& long_long_max() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val((std::numeric_limits::max)()); + return val; + } + static const cpp_dec_float& long_long_min() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val((std::numeric_limits::min)()); + return val; + } + static const cpp_dec_float& ulong_long_max() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val((std::numeric_limits::max)()); + return val; + } + static const cpp_dec_float& eps() BOOST_NOEXCEPT + { + init.do_nothing(); + static cpp_dec_float val(1.0, 1 - (int)Digits10); + return val; + } + + // Basic operations. + cpp_dec_float& operator= (const cpp_dec_float& v) BOOST_NOEXCEPT + { + data = v.data; + exp = v.exp; + neg = v.neg; + fpclass = v.fpclass; + prec_elem = v.prec_elem; + return *this; + } + template + cpp_dec_float& operator=(const cpp_dec_float& f) BOOST_NOEXCEPT + { + exp = f.exp; + neg = f.neg; + fpclass = static_cast(static_cast(f.fpclass)); + unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number); + std::copy(f.data.begin(), f.data.begin() + elems, data.begin()); + std::fill(data.begin() + elems, data.end(), 0); + prec_elem = cpp_dec_float_elem_number; + return *this; + } + cpp_dec_float& operator= (long long v) BOOST_NOEXCEPT + { + if(v < 0) + { + from_unsigned_long_long(-v); + negate(); + } + else + from_unsigned_long_long(v); + return *this; + } + cpp_dec_float& operator= (unsigned long long v) BOOST_NOEXCEPT + { + from_unsigned_long_long(v); + return *this; + } + cpp_dec_float& operator= (long double v) BOOST_NOEXCEPT; + cpp_dec_float& operator= (const char* v) + { + rd_string(v); + return *this; + } + + cpp_dec_float& operator+=(const cpp_dec_float& v) BOOST_NOEXCEPT; + cpp_dec_float& operator-=(const cpp_dec_float& v) BOOST_NOEXCEPT; + cpp_dec_float& operator*=(const cpp_dec_float& v) BOOST_NOEXCEPT; + cpp_dec_float& operator/=(const cpp_dec_float& v) BOOST_NOEXCEPT; + + cpp_dec_float& add_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT + { + cpp_dec_float t; + t.from_unsigned_long_long(n); + return *this += t; + } + cpp_dec_float& sub_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT + { + cpp_dec_float t; + t.from_unsigned_long_long(n); + return *this -= t; + } + cpp_dec_float& mul_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT; + cpp_dec_float& div_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT; + + // Elementary primitives. + cpp_dec_float& calculate_inv (void) BOOST_NOEXCEPT; + cpp_dec_float& calculate_sqrt(void) BOOST_NOEXCEPT; + void negate() BOOST_NOEXCEPT + { + if(!iszero()) + neg = !neg; + } + + // Comparison functions + bool isnan (void) const BOOST_NOEXCEPT { return (fpclass == cpp_dec_float_NaN); } + bool isinf (void) const BOOST_NOEXCEPT { return (fpclass == cpp_dec_float_inf); } + bool isfinite(void) const BOOST_NOEXCEPT { return (fpclass == cpp_dec_float_finite); } + + bool iszero (void) const BOOST_NOEXCEPT + { + return ((fpclass == cpp_dec_float_finite) && (data[0u] == 0u)); + } + bool isone (void) const BOOST_NOEXCEPT; + bool isint (void) const BOOST_NOEXCEPT; + bool isneg (void) const BOOST_NOEXCEPT { return neg; } + + // Operators pre-increment and pre-decrement + cpp_dec_float& operator++(void) BOOST_NOEXCEPT + { + return *this += one(); + } + cpp_dec_float& operator--(void) BOOST_NOEXCEPT + { + return *this -= one(); + } + + std::string str(boost::intmax_t digits, std::ios_base::fmtflags f)const; + + int compare(const cpp_dec_float& v)const BOOST_NOEXCEPT; + template + int compare(const V& v)const BOOST_NOEXCEPT + { + cpp_dec_float t; + t = v; + return compare(t); + } + + void swap(cpp_dec_float& v) BOOST_NOEXCEPT + { + data.swap(v.data); + std::swap(exp, v.exp); + std::swap(neg, v.neg); + std::swap(fpclass, v.fpclass); + std::swap(prec_elem, v.prec_elem); + } + + double extract_double (void) const BOOST_NOEXCEPT; + long double extract_long_double (void) const BOOST_NOEXCEPT; + signed long long extract_signed_long_long (void) const BOOST_NOEXCEPT; + unsigned long long extract_unsigned_long_long(void) const BOOST_NOEXCEPT; + void extract_parts (double& mantissa, ExponentType& exponent) const BOOST_NOEXCEPT; + cpp_dec_float extract_integer_part (void) const BOOST_NOEXCEPT; + void precision(const boost::int32_t prec_digits) BOOST_NOEXCEPT + { + if(prec_digits >= cpp_dec_float_total_digits10) + { + prec_elem = cpp_dec_float_elem_number; + } + else + { + const boost::int32_t elems = static_cast( static_cast( (prec_digits + (cpp_dec_float_elem_digits10 / 2)) / cpp_dec_float_elem_digits10) + + static_cast(((prec_digits % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); + + prec_elem = (std::min)(cpp_dec_float_elem_number, (std::max)(elems, static_cast(2))); + } + } + static cpp_dec_float pow2(long long i) BOOST_NOEXCEPT; + ExponentType order()const BOOST_NOEXCEPT + { + const bool bo_order_is_zero = ((!isfinite()) || (data[0] == static_cast(0u))); + // + // Binary search to find the order of the leading term: + // + ExponentType prefix = 0; + + if(data[0] >= 100000UL) + { + if(data[0] >= 10000000UL) + { + if(data[0] >= 100000000UL) + { + if(data[0] >= 1000000000UL) + prefix = 9; + else + prefix = 8; + } + else + prefix = 7; + } + else + { + if(data[0] >= 1000000UL) + prefix = 6; + else + prefix = 5; + } + } + else + { + if(data[0] >= 1000UL) + { + if(data[0] >= 10000UL) + prefix = 4; + else + prefix = 3; + } + else + { + if(data[0] >= 100) + prefix = 2; + else if(data[0] >= 10) + prefix = 1; + } + } + + return (bo_order_is_zero ? static_cast(0) : static_cast(exp + prefix)); + } + +private: + static bool data_elem_is_non_zero_predicate(const boost::uint32_t& d) BOOST_NOEXCEPT { return (d != static_cast(0u)); } + static bool data_elem_is_non_nine_predicate(const boost::uint32_t& d) BOOST_NOEXCEPT { return (d != static_cast(cpp_dec_float::cpp_dec_float_elem_mask - 1)); } + static bool char_is_nonzero_predicate(const char& c) BOOST_NOEXCEPT { return (c != static_cast('0')); } + + void from_unsigned_long_long(const unsigned long long u) BOOST_NOEXCEPT; + + int cmp_data(const array_type& vd) const BOOST_NOEXCEPT; + + + static boost::uint32_t mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p) BOOST_NOEXCEPT; + static boost::uint32_t mul_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) BOOST_NOEXCEPT; + static boost::uint32_t div_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) BOOST_NOEXCEPT; + + bool rd_string(const char* const s); + + template + friend class cpp_dec_float; + +}; + +template +typename cpp_dec_float::initializer cpp_dec_float::init; + +template +const boost::int32_t cpp_dec_float::cpp_dec_float_radix; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_setting; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_lo; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10_limit_hi; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_digits10; +template +const ExponentType cpp_dec_float::cpp_dec_float_max_exp; +template +const ExponentType cpp_dec_float::cpp_dec_float_min_exp; +template +const ExponentType cpp_dec_float::cpp_dec_float_max_exp10; +template +const ExponentType cpp_dec_float::cpp_dec_float_min_exp10; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_elem_digits10; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_elem_number_request; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_elem_number; +template +const boost::int32_t cpp_dec_float::cpp_dec_float_elem_mask; + + +template +cpp_dec_float& cpp_dec_float::operator+=(const cpp_dec_float& v) BOOST_NOEXCEPT +{ + if(isnan()) + { + return *this; + } + + if(isinf()) + { + if(v.isinf() && (isneg() != v.isneg())) + { + *this = nan(); + } + return *this; + } + + if(iszero()) + { + return operator=(v); + } + + // Get the offset for the add/sub operation. + static const ExponentType max_delta_exp = static_cast((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); + + const ExponentType ofs_exp = static_cast(exp - v.exp); + + // Check if the operation is out of range, requiring special handling. + if(v.iszero() || (ofs_exp > max_delta_exp)) + { + // Result is *this unchanged since v is negligible compared to *this. + return *this; + } + else if(ofs_exp < -max_delta_exp) + { + // Result is *this = v since *this is negligible compared to v. + return operator=(v); + } + + // Do the add/sub operation. + + typename array_type::iterator p_u = data.begin(); + typename array_type::const_iterator p_v = v.data.begin(); + bool b_copy = false; + const boost::int32_t ofs = static_cast(static_cast(ofs_exp) / cpp_dec_float_elem_digits10); + array_type n_data; + + if(neg == v.neg) + { + // Add v to *this, where the data array of either *this or v + // might have to be treated with a positive, negative or zero offset. + // The result is stored in *this. The data are added one element + // at a time, each element with carry. + if(ofs >= static_cast(0)) + { + std::copy(v.data.begin(), v.data.end() - static_cast(ofs), n_data.begin() + static_cast(ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), static_cast(0u)); + p_v = n_data.begin(); + } + else + { + std::copy(data.begin(), data.end() - static_cast(-ofs), n_data.begin() + static_cast(-ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(-ofs), static_cast(0u)); + p_u = n_data.begin(); + b_copy = true; + } + + // Addition algorithm + boost::uint32_t carry = static_cast(0u); + + for(boost::int32_t j = static_cast(cpp_dec_float_elem_number - static_cast(1)); j >= static_cast(0); j--) + { + boost::uint32_t t = static_cast(static_cast(p_u[j] + p_v[j]) + carry); + carry = t / static_cast(cpp_dec_float_elem_mask); + p_u[j] = static_cast(t - static_cast(carry * static_cast(cpp_dec_float_elem_mask))); + } + + if(b_copy) + { + data = n_data; + exp = v.exp; + } + + // There needs to be a carry into the element -1 of the array data + if(carry != static_cast(0u)) + { + std::copy_backward(data.begin(), data.end() - static_cast(1u), data.end()); + data[0] = carry; + exp += static_cast(cpp_dec_float_elem_digits10); + } + } + else + { + // Subtract v from *this, where the data array of either *this or v + // might have to be treated with a positive, negative or zero offset. + if((ofs > static_cast(0)) + || ( (ofs == static_cast(0)) + && (cmp_data(v.data) > static_cast(0))) + ) + { + // In this case, |u| > |v| and ofs is positive. + // Copy the data of v, shifted down to a lower value + // into the data array m_n. Set the operand pointer p_v + // to point to the copied, shifted data m_n. + std::copy(v.data.begin(), v.data.end() - static_cast(ofs), n_data.begin() + static_cast(ofs)); + std::fill(n_data.begin(), n_data.begin() + static_cast(ofs), static_cast(0u)); + p_v = n_data.begin(); + } + else + { + if(ofs != static_cast(0)) + { + // In this case, |u| < |v| and ofs is negative. + // Shift the data of u down to a lower value. + std::copy_backward(data.begin(), data.end() - static_cast(-ofs), data.end()); + std::fill(data.begin(), data.begin() + static_cast(-ofs), static_cast(0u)); + } + + // Copy the data of v into the data array n_data. + // Set the u-pointer p_u to point to m_n and the + // operand pointer p_v to point to the shifted + // data m_data. + n_data = v.data; + p_u = n_data.begin(); + p_v = data.begin(); + b_copy = true; + } + + boost::int32_t j; + + // Subtraction algorithm + boost::int32_t borrow = static_cast(0); + + for(j = static_cast(cpp_dec_float_elem_number - static_cast(1)); j >= static_cast(0); j--) + { + boost::int32_t t = static_cast(static_cast( static_cast(p_u[j]) + - static_cast(p_v[j])) - borrow); + + // Underflow? Borrow? + if(t < static_cast(0)) + { + // Yes, underflow and borrow + t += static_cast(cpp_dec_float_elem_mask); + borrow = static_cast(1); + } + else + { + borrow = static_cast(0); + } + + p_u[j] = static_cast(static_cast(t) % static_cast(cpp_dec_float_elem_mask)); + } + + if(b_copy) + { + data = n_data; + exp = v.exp; + neg = v.neg; + } + + // Is it necessary to justify the data? + const typename array_type::const_iterator first_nonzero_elem = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); + + if(first_nonzero_elem != data.begin()) + { + if(first_nonzero_elem == data.end()) + { + // This result of the subtraction is exactly zero. + // Reset the sign and the exponent. + neg = false; + exp = static_cast(0); + } + else + { + // Justify the data + const std::size_t sj = static_cast(std::distance(data.begin(), first_nonzero_elem)); + + std::copy(data.begin() + static_cast(sj), data.end(), data.begin()); + std::fill(data.end() - sj, data.end(), static_cast(0u)); + + exp -= static_cast(sj * static_cast(cpp_dec_float_elem_digits10)); + } + } + } + + // Check for underflow. + if(iszero()) + { + return *this = zero(); + } + + bool overflow = exp >= cpp_dec_float_max_exp10; + if(exp == cpp_dec_float_max_exp10) + { + // Check to see if we really truely have an overflow or not... + if(isneg()) + { + cpp_dec_float t(*this); + t.negate(); + overflow = t.compare((max)()) > 0; + } + else + { + overflow = compare((max)()) > 0; + } + } + + // Check for overflow. + if(overflow) + { + const bool b_result_is_neg = neg; + + *this = inf(); + if(b_result_is_neg) + negate(); + } + + return *this; +} + +template +cpp_dec_float& cpp_dec_float::operator-=(const cpp_dec_float& v) BOOST_NOEXCEPT +{ + // Use *this - v = -(-*this + v). + negate(); + *this += v; + negate(); + return *this; +} + +template +cpp_dec_float& cpp_dec_float::operator*=(const cpp_dec_float& v) BOOST_NOEXCEPT +{ + // Evaluate the sign of the result. + const bool b_result_is_neg = (neg != v.neg); + + // Artificially set the sign of the result to be positive. + neg = false; + + // Handle special cases like zero, inf and NaN. + const bool b_u_is_inf = isinf(); + const bool b_v_is_inf = v.isinf(); + const bool b_u_is_zero = iszero(); + const bool b_v_is_zero = v.iszero(); + + if( (isnan() || v.isnan()) + || (b_u_is_inf && b_v_is_zero) + || (b_v_is_inf && b_u_is_zero) + ) + { + *this = nan(); + return *this; + } + + if(b_u_is_inf || b_v_is_inf) + { + *this = inf(); + if(b_result_is_neg) + negate(); + return *this; + } + + if(b_u_is_zero || b_v_is_zero) + { + return *this = zero(); + } + + // Check for overflow or underflow. + const bool u_exp_is_neg = (exp < static_cast(0)); + const bool v_exp_is_neg = (v.exp < static_cast(0)); + + if(u_exp_is_neg == v_exp_is_neg) + { + // Get the unsigned base-10 exponents of *this and v and... + const ExponentType u_exp = ((!u_exp_is_neg) ? exp : static_cast( -exp)); + const ExponentType v_exp = ((!v_exp_is_neg) ? v.exp : static_cast(-v.exp)); + + // Check the range of the upcoming multiplication. + const bool b_result_is_out_of_range = (v_exp >= static_cast(cpp_dec_float_max_exp10 - u_exp)); + + if(b_result_is_out_of_range) + { + if(u_exp_is_neg) + { + *this = zero(); + } + else + { + *this = inf(); + if(b_result_is_neg) + negate(); + } + return *this; + } + } + + // Set the exponent of the result. + exp += v.exp; + + const boost::int32_t prec_mul = (std::min)(prec_elem, v.prec_elem); + + const boost::uint32_t carry = mul_loop_uv(data.data(), v.data.data(), prec_mul); + + // Handle a potential carry. + if(carry != static_cast(0u)) + { + exp += cpp_dec_float_elem_digits10; + + // Shift the result of the multiplication one element to the right... + std::copy_backward(data.begin(), + data.begin() + static_cast(prec_elem - static_cast(1)), + data.begin() + static_cast(prec_elem)); + + // ... And insert the carry. + data.front() = carry; + } + + // Set the sign of the result. + neg = b_result_is_neg; + + return *this; +} + +template +cpp_dec_float& cpp_dec_float::operator/=(const cpp_dec_float& v) BOOST_NOEXCEPT +{ + const bool u_and_v_are_finite_and_identical = ( isfinite() + && (fpclass == v.fpclass) + && (exp == v.exp) + && (cmp_data(v.data) == static_cast(0))); + + if(u_and_v_are_finite_and_identical) + { + if(neg != v.neg) + { + *this = one(); + negate(); + } + else + *this = one(); + return *this; + } + else + { + if(iszero()) + { + if(v.isnan() || v.iszero()) + { + return *this = v; + } + return *this; + } + cpp_dec_float t(v); + t.calculate_inv(); + return operator*=(t); + } +} + +template +cpp_dec_float& cpp_dec_float::mul_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT +{ + // Multiply *this with a constant unsigned long long. + + // Evaluate the sign of the result. + const bool b_neg = neg; + + // Artificially set the sign of the result to be positive. + neg = false; + + // Handle special cases like zero, inf and NaN. + const bool b_u_is_inf = isinf(); + const bool b_n_is_zero = (n == static_cast(0)); + + if(isnan() || (b_u_is_inf && b_n_is_zero)) + { + return (*this = nan()); + } + + if(b_u_is_inf) + { + *this = inf(); + if(b_neg) + negate(); + return *this; + } + + if(iszero() || b_n_is_zero) + { + // Multiplication by zero. + return *this = zero(); + } + + if(n >= static_cast(cpp_dec_float_elem_mask)) + { + neg = b_neg; + cpp_dec_float t; + t = n; + return operator*=(t); + } + + if(n == static_cast(1u)) + { + neg = b_neg; + return *this; + } + + // Set up the multiplication loop. + const boost::uint32_t nn = static_cast(n); + const boost::uint32_t carry = mul_loop_n(data.data(), nn, prec_elem); + + // Handle the carry and adjust the exponent. + if(carry != static_cast(0u)) + { + exp += static_cast(cpp_dec_float_elem_digits10); + + // Shift the result of the multiplication one element to the right. + std::copy_backward(data.begin(), + data.begin() + static_cast(prec_elem - static_cast(1)), + data.begin() + static_cast(prec_elem)); + + data.front() = static_cast(carry); + } + + bool overflow = exp >= cpp_dec_float_max_exp10; + if(exp == cpp_dec_float_max_exp10) + { + // Check to see if we really truly have an overflow or not... + if(isneg()) + { + cpp_dec_float t(*this); + t.negate(); + overflow = t.compare((max)()) > 0; + } + else + { + overflow = compare((max)()) > 0; + } + } + + if(overflow) + { + *this = inf(); + if(b_neg) + negate(); + return *this; + } + + // Set the sign. + neg = b_neg; + + return *this; +} + +template +cpp_dec_float& cpp_dec_float::div_unsigned_long_long(const unsigned long long n) BOOST_NOEXCEPT +{ + // Divide *this by a constant unsigned long long. + + // Evaluate the sign of the result. + const bool b_neg = neg; + + // Artificially set the sign of the result to be positive. + neg = false; + + // Handle special cases like zero, inf and NaN. + if(isnan()) + { + return *this; + } + + if(isinf()) + { + *this = inf(); + if(b_neg) + negate(); + return *this; + } + + if(n == static_cast(0u)) + { + // Divide by 0. + if(iszero()) + { + *this = nan(); + return *this; + } + else + { + *this = inf(); + if(isneg()) + negate(); + return *this; + } + } + + if(iszero()) + { + return *this; + } + + if(n >= static_cast(cpp_dec_float_elem_mask)) + { + neg = b_neg; + cpp_dec_float t; + t = n; + return operator/=(t); + } + + const boost::uint32_t nn = static_cast(n); + + if(nn > static_cast(1u)) + { + // Do the division loop. + const boost::uint32_t prev = div_loop_n(data.data(), nn, prec_elem); + + // Determine if one leading zero is in the result data. + if(data[0] == static_cast(0u)) + { + // Adjust the exponent + exp -= static_cast(cpp_dec_float_elem_digits10); + + // Shift result of the division one element to the left. + std::copy(data.begin() + static_cast(1u), + data.begin() + static_cast(prec_elem - static_cast(1)), + data.begin()); + + data[prec_elem - static_cast(1)] = static_cast(static_cast(prev * static_cast(cpp_dec_float_elem_mask)) / nn); + } + } + + // Check for underflow. + if(iszero()) + { + return *this = zero(); + } + + // Set the sign of the result. + neg = b_neg; + + return *this; +} + +template +cpp_dec_float& cpp_dec_float::calculate_inv() BOOST_NOEXCEPT +{ + // Compute the inverse of *this. + const bool b_neg = neg; + + neg = false; + + // Handle special cases like zero, inf and NaN. + if(iszero()) + { + *this = inf(); + if(b_neg) + negate(); + return *this; + } + + if(isnan()) + { + return *this; + } + + if(isinf()) + { + return *this = zero(); + } + + if(isone()) + { + if(b_neg) + negate(); + return *this; + } + + // Save the original *this. + cpp_dec_float x(*this); + + // Generate the initial estimate using division. + // Extract the mantissa and exponent for a "manual" + // computation of the estimate. + double dd; + ExponentType ne; + x.extract_parts(dd, ne); + + // Do the inverse estimate using double precision estimates of mantissa and exponent. + operator=(cpp_dec_float(1.0 / dd, -ne)); + + // Compute the inverse of *this. Quadratically convergent Newton-Raphson iteration + // is used. During the iterative steps, the precision of the calculation is limited + // to the minimum required in order to minimize the run-time. + + static const boost::int32_t double_digits10_minus_a_few = std::numeric_limits::digits10 - 3; + + for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= static_cast(2)) + { + // Adjust precision of the terms. + precision(static_cast((digits + 10) * static_cast(2))); + x.precision(static_cast((digits + 10) * static_cast(2))); + + // Next iteration. + cpp_dec_float t(*this); + t *= x; + t -= two(); + t.negate(); + *this *= t; + } + + neg = b_neg; + + prec_elem = cpp_dec_float_elem_number; + + return *this; +} + +template +cpp_dec_float& cpp_dec_float::calculate_sqrt(void) BOOST_NOEXCEPT +{ + // Compute the square root of *this. + + if(isneg() || (!isfinite())) + { + *this = nan(); + return *this; + } + + if(iszero() || isone()) + { + return *this; + } + + // Save the original *this. + cpp_dec_float x(*this); + + // Generate the initial estimate using division. + // Extract the mantissa and exponent for a "manual" + // computation of the estimate. + double dd; + ExponentType ne; + extract_parts(dd, ne); + + // Force the exponent to be an even multiple of two. + if((ne % static_cast(2)) != static_cast(0)) + { + ++ne; + dd /= 10.0; + } + + // Setup the iteration. + // Estimate the square root using simple manipulations. + const double sqd = std::sqrt(dd); + + *this = cpp_dec_float(sqd, static_cast(ne / static_cast(2))); + + // Estimate 1.0 / (2.0 * x0) using simple manipulations. + cpp_dec_float vi(0.5 / sqd, static_cast(-ne / static_cast(2))); + + // Compute the square root of x. Coupled Newton iteration + // as described in "Pi Unleashed" is used. During the + // iterative steps, the precision of the calculation is + // limited to the minimum required in order to minimize + // the run-time. + // + // Book references: + // http://www.jjj.de/pibook/pibook.html + // http://www.amazon.com/exec/obidos/tg/detail/-/3540665722/qid=1035535482/sr=8-7/ref=sr_8_7/104-3357872-6059916?v=glance&n=507846 + + static const boost::uint32_t double_digits10_minus_a_few = std::numeric_limits::digits10 - 3; + + for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= 2u) + { + // Adjust precision of the terms. + precision((digits + 10) * 2); + vi.precision((digits + 10) * 2); + + // Next iteration of vi + cpp_dec_float t(*this); + t *= vi; + t.negate(); + t.mul_unsigned_long_long(2u); + t += one(); + t *= vi; + vi += t; + + // Next iteration of *this + t = *this; + t *= *this; + t.negate(); + t += x; + t *= vi; + *this += t; + } + + prec_elem = cpp_dec_float_elem_number; + + return *this; +} + +template +int cpp_dec_float::cmp_data(const array_type& vd) const BOOST_NOEXCEPT +{ + // Compare the data of *this with those of v. + // Return +1 for *this > v + // 0 for *this = v + // -1 for *this < v + + const std::pair mismatch_pair = std::mismatch(data.begin(), data.end(), vd.begin()); + + const bool is_equal = ((mismatch_pair.first == data.end()) && (mismatch_pair.second == vd.end())); + + if(is_equal) + { + return 0; + } + else + { + return ((*mismatch_pair.first > *mismatch_pair.second) ? 1 : -1); + } +} + +template +int cpp_dec_float::compare(const cpp_dec_float& v) const BOOST_NOEXCEPT +{ + // Compare v with *this. + // Return +1 for *this > v + // 0 for *this = v + // -1 for *this < v + + // Handle all non-finite cases. + if((!isfinite()) || (!v.isfinite())) + { + // NaN can never equal NaN. Return an implementation-dependent + // signed result. Also note that comparison of NaN with NaN + // using operators greater-than or less-than is undefined. + if(isnan() || v.isnan()) { return (isnan() ? 1 : -1); } + + if(isinf() && v.isinf()) + { + // Both *this and v are infinite. They are equal if they have the same sign. + // Otherwise, *this is less than v if and only if *this is negative. + return ((neg == v.neg) ? 0 : (neg ? -1 : 1)); + } + + if(isinf()) + { + // *this is infinite, but v is finite. + // So negative infinite *this is less than any finite v. + // Whereas positive infinite *this is greater than any finite v. + return (isneg() ? -1 : 1); + } + else + { + // *this is finite, and v is infinite. + // So any finite *this is greater than negative infinite v. + // Whereas any finite *this is less than positive infinite v. + return (v.neg ? 1 : -1); + } + } + + // And now handle all *finite* cases. + if(iszero()) + { + // The value of *this is zero and v is either zero or non-zero. + return (v.iszero() ? 0 + : (v.neg ? 1 : -1)); + } + else if(v.iszero()) + { + // The value of v is zero and *this is non-zero. + return (neg ? -1 : 1); + } + else + { + // Both *this and v are non-zero. + + if(neg != v.neg) + { + // The signs are different. + return (neg ? -1 : 1); + } + else if(exp != v.exp) + { + // The signs are the same and the exponents are different. + const int val_cexpression = ((exp < v.exp) ? 1 : -1); + + return (neg ? val_cexpression : -val_cexpression); + } + else + { + // The signs are the same and the exponents are the same. + // Compare the data. + const int val_cmp_data = cmp_data(v.data); + + return ((!neg) ? val_cmp_data : -val_cmp_data); + } + } +} + +template +bool cpp_dec_float::isone() const BOOST_NOEXCEPT +{ + // Check if the value of *this is identically 1 or very close to 1. + + const bool not_negative_and_is_finite = ((!neg) && isfinite()); + + if(not_negative_and_is_finite) + { + if((data[0u] == static_cast(1u)) && (exp == static_cast(0))) + { + const typename array_type::const_iterator it_non_zero = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); + return (it_non_zero == data.end()); + } + else if((data[0u] == static_cast(cpp_dec_float_elem_mask - 1)) && (exp == static_cast(-cpp_dec_float_elem_digits10))) + { + const typename array_type::const_iterator it_non_nine = std::find_if(data.begin(), data.end(), data_elem_is_non_nine_predicate); + return (it_non_nine == data.end()); + } + } + + return false; +} + +template +bool cpp_dec_float::isint() const BOOST_NOEXCEPT +{ + if(fpclass != cpp_dec_float_finite) { return false; } + + if(iszero()) { return true; } + + if(exp < static_cast(0)) { return false; } // |*this| < 1. + + const typename array_type::size_type offset_decimal_part = static_cast(exp / cpp_dec_float_elem_digits10) + 1u; + + if(offset_decimal_part >= static_cast(cpp_dec_float_elem_number)) + { + // The number is too large to resolve the integer part. + // It considered to be a pure integer. + return true; + } + + typename array_type::const_iterator it_non_zero = std::find_if(data.begin() + offset_decimal_part, data.end(), data_elem_is_non_zero_predicate); + + return (it_non_zero == data.end()); +} + +template +void cpp_dec_float::extract_parts(double& mantissa, ExponentType& exponent) const BOOST_NOEXCEPT +{ + // Extract the approximate parts mantissa and base-10 exponent from the input cpp_dec_float value x. + + // Extracts the mantissa and exponent. + exponent = exp; + + boost::uint32_t p10 = static_cast(1u); + boost::uint32_t test = data[0u]; + + for(;;) + { + test /= static_cast(10u); + + if(test == static_cast(0u)) + { + break; + } + + p10 *= static_cast(10u); + ++exponent; + } + + mantissa = static_cast(data[0]) + + (static_cast(data[1]) / static_cast(cpp_dec_float_elem_mask)) + + ((static_cast(data[2]) / static_cast(cpp_dec_float_elem_mask)) / static_cast(cpp_dec_float_elem_mask)); + + mantissa /= static_cast(p10); + + if(neg) { mantissa = -mantissa; } +} + +template +double cpp_dec_float::extract_double(void) const BOOST_NOEXCEPT +{ + // Returns the double conversion of a cpp_dec_float. + + // Check for non-normal cpp_dec_float. + if(!isfinite()) + { + if(isnan()) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + } + + cpp_dec_float xx(*this); + if(xx.isneg()) + xx.negate(); + + // Check if *this cpp_dec_float is zero. + if(iszero() || (xx.compare(double_min()) < 0)) + { + return 0.0; + } + + // Check if *this cpp_dec_float exceeds the maximum of double. + if(xx.compare(double_max()) > 0) + { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + + std::stringstream ss; + + ss << str(std::numeric_limits::digits10 + (2 + 1), std::ios_base::scientific); + + double d; + ss >> d; + + return d; +} + +template +long double cpp_dec_float::extract_long_double(void) const BOOST_NOEXCEPT +{ + // Returns the long double conversion of a cpp_dec_float. + + // Check if *this cpp_dec_float is subnormal. + if(!isfinite()) + { + if(isnan()) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + } + + cpp_dec_float xx(*this); + if(xx.isneg()) + xx.negate(); + + // Check if *this cpp_dec_float is zero. + if(iszero() || (xx.compare(long_double_min()) < 0)) + { + return static_cast(0.0); + } + + // Check if *this cpp_dec_float exceeds the maximum of double. + if(xx.compare(long_double_max()) > 0) + { + return ((!neg) ? std::numeric_limits::infinity() + : -std::numeric_limits::infinity()); + } + + std::stringstream ss; + + ss << str(std::numeric_limits::digits10 + (2 + 1), std::ios_base::scientific); + + long double ld; + ss >> ld; + + return ld; +} + +template +signed long long cpp_dec_float::extract_signed_long_long(void) const BOOST_NOEXCEPT +{ + // Extracts a signed long long from *this. + // If (x > maximum of signed long long) or (x < minimum of signed long long), + // then the maximum or minimum of signed long long is returned accordingly. + + if(exp < static_cast(0)) + { + return static_cast(0); + } + + const bool b_neg = isneg(); + + unsigned long long val; + + if((!b_neg) && (compare(long_long_max()) > 0)) + { + return (std::numeric_limits::max)(); + } + else if(b_neg && (compare(long_long_min()) < 0)) + { + return (std::numeric_limits::min)(); + } + else + { + // Extract the data into an unsigned long long value. + cpp_dec_float xn(extract_integer_part()); + if(xn.isneg()) + xn.negate(); + + val = static_cast(xn.data[0]); + + const boost::int32_t imax = (std::min)(static_cast(static_cast(xn.exp) / cpp_dec_float_elem_digits10), static_cast(cpp_dec_float_elem_number - static_cast(1))); + + for(boost::int32_t i = static_cast(1); i <= imax; i++) + { + val *= static_cast(cpp_dec_float_elem_mask); + val += static_cast(xn.data[i]); + } + } + + return ((!b_neg) ? static_cast(val) : static_cast(-static_cast(val))); +} + +template +unsigned long long cpp_dec_float::extract_unsigned_long_long(void) const BOOST_NOEXCEPT +{ + // Extracts an unsigned long long from *this. + // If x exceeds the maximum of unsigned long long, + // then the maximum of unsigned long long is returned. + // If x is negative, then the unsigned long long cast of + // the signed long long extracted value is returned. + + if(isneg()) + { + return static_cast(extract_signed_long_long()); + } + + if(exp < static_cast(0)) + { + return static_cast(0u); + } + + const cpp_dec_float xn(extract_integer_part()); + + unsigned long long val; + + if(xn.compare(ulong_long_max()) > 0) + { + return (std::numeric_limits::max)(); + } + else + { + // Extract the data into an unsigned long long value. + val = static_cast(xn.data[0]); + + const boost::int32_t imax = (std::min)(static_cast(static_cast(xn.exp) / cpp_dec_float_elem_digits10), static_cast(cpp_dec_float_elem_number - static_cast(1))); + + for(boost::int32_t i = static_cast(1); i <= imax; i++) + { + val *= static_cast(cpp_dec_float_elem_mask); + val += static_cast(xn.data[i]); + } + } + + return val; +} + +template +cpp_dec_float cpp_dec_float::extract_integer_part(void) const BOOST_NOEXCEPT +{ + // Compute the signed integer part of x. + + if(!isfinite()) + { + return *this; + } + + if(exp < static_cast(0)) + { + // The absolute value of the number is smaller than 1. + // Thus the integer part is zero. + return zero(); + } + else if(exp >= static_cast(Digits10 - 1)) + { + // The number is too large to resolve the integer part. + // Thus it is already a pure integer part. + return *this; + } + + // Make a local copy. + cpp_dec_float x = *this; + + // Clear out the decimal portion + const size_t first_clear = (static_cast(x.exp) / static_cast(cpp_dec_float_elem_digits10)) + 1u; + const size_t last_clear = static_cast(cpp_dec_float_elem_number); + + std::fill(x.data.begin() + first_clear, x.data.begin() + last_clear, static_cast(0u)); + + return x; +} + +template +std::string cpp_dec_float::str(boost::intmax_t number_of_digits, std::ios_base::fmtflags f) const +{ + if(this->isinf()) + { + if(this->isneg()) + return "-inf"; + else if(f & std::ios_base::showpos) + return "+inf"; + else + return "inf"; + } + else if(this->isnan()) + { + return "nan"; + } + + std::string str; + boost::intmax_t org_digits(number_of_digits); + ExponentType my_exp = order(); + if(number_of_digits == 0) + number_of_digits = cpp_dec_float_total_digits10; + if(f & std::ios_base::fixed) + { + number_of_digits += my_exp + 1; + } + else if(f & std::ios_base::scientific) + ++number_of_digits; + // Determine the number of elements needed to provide the requested digits from cpp_dec_float. + const std::size_t number_of_elements = (std::min)(static_cast((number_of_digits / static_cast(cpp_dec_float_elem_digits10)) + 2u), + static_cast(cpp_dec_float_elem_number)); + + // Extract the remaining digits from cpp_dec_float after the decimal point. + str = boost::lexical_cast(data[0]); + + // Extract all of the digits from cpp_dec_float, beginning with the first data element. + for(std::size_t i = static_cast(1u); i < number_of_elements; i++) + { + std::stringstream ss; + + ss << std::setw(static_cast(cpp_dec_float_elem_digits10)) + << std::setfill(static_cast('0')) + << data[i]; + + str += ss.str(); + } + bool have_leading_zeros = false; + if(number_of_digits == 0) + { + // We only get here if the output format is "fixed" and we just need to + // round the first non-zero digit. + number_of_digits -= my_exp + 1; // reset to original value + str.insert(0, std::string::size_type(number_of_digits), '0'); + have_leading_zeros = true; + } + if(number_of_digits < 0) + { + str = "0"; + if(isneg()) + str.insert(0, 1, '-'); + boost::multiprecision::detail::format_float_string(str, 0, number_of_digits - my_exp - 1, f, this->iszero()); + return str; + } + else + { + // Cut the output to the size of the precision. + if(str.length() > static_cast(number_of_digits)) + { + // Get the digit after the last needed digit for rounding + const boost::uint32_t round = static_cast(static_cast(str[static_cast(number_of_digits)]) - static_cast('0')); + + bool need_round_up = round >= 5u; + + if(round == 5u) + { + const boost::uint32_t ix = static_cast(static_cast(str[static_cast(number_of_digits - 1)]) - static_cast('0')); + if((ix & 1u) == 0) + { + // We have an even digit followed by a 5, so we might not actually need to round up + // if all the remaining digits are zero: + if(str.find_first_not_of('0', static_cast(number_of_digits + 1)) == std::string::npos) + { + bool all_zeros = true; + // No none-zero trailing digits in the string, now check whatever parts we didn't convert to the string: + for(std::size_t i = number_of_elements; i < data.size(); i++) + { + if(data[i]) + { + all_zeros = false; + break; + } + } + if(all_zeros) + need_round_up = false; // tie break - round to even. + } + } + } + + // Truncate the string + str.erase(static_cast(number_of_digits)); + + if(need_round_up) + { + std::size_t ix = static_cast(str.length() - 1u); + + // Every trailing 9 must be rounded up + while(ix && (static_cast(str.at(ix)) - static_cast('0') == static_cast(9))) + { + str.at(ix) = static_cast('0'); + --ix; + } + + if(!ix) + { + // There were nothing but trailing nines. + if(static_cast(static_cast(str.at(ix)) - static_cast(0x30)) == static_cast(9)) + { + // Increment up to the next order and adjust exponent. + str.at(ix) = static_cast('1'); + ++my_exp; + } + else + { + // Round up this digit. + ++str.at(ix); + } + } + else + { + // Round up the last digit. + ++str[ix]; + } + } + } + } + if(have_leading_zeros) + { + // We need to take the zeros back out again, and correct the exponent + // if we rounded up: + if(str[std::string::size_type(number_of_digits - 1)] != '0') + { + ++my_exp; + str.erase(0, std::string::size_type(number_of_digits - 1)); + } + else + str.erase(0, std::string::size_type(number_of_digits)); + } + if(isneg()) + str.insert(0, 1, '-'); + boost::multiprecision::detail::format_float_string(str, my_exp, org_digits, f, this->iszero()); + return str; +} + +template +bool cpp_dec_float::rd_string(const char* const s) +{ + try{ + + std::string str(s); + + // TBD: Using several regular expressions may significantly reduce + // the code complexity (and perhaps the run-time) of rd_string(). + + // Get a possible exponent and remove it. + exp = static_cast(0); + + std::size_t pos; + + if( ((pos = str.find('e')) != std::string::npos) + || ((pos = str.find('E')) != std::string::npos) + ) + { + // Remove the exponent part from the string. + exp = boost::lexical_cast(static_cast(str.c_str() + (pos + 1u))); + str = str.substr(static_cast(0u), pos); + } + + // Get a possible +/- sign and remove it. + neg = false; + + if(str.size()) + { + if(str[0] == '-') + { + neg = true; + str.erase(0, 1); + } + else if(str[0] == '+') + { + str.erase(0, 1); + } + } + // + // Special cases for infinities and NaN's: + // + if((str == "inf") || (str == "INF") || (str == "infinity") || (str == "INFINITY")) + { + if(neg) + { + *this = this->inf(); + this->negate(); + } + else + *this = this->inf(); + return true; + } + if((str.size() >= 3) && ((str.substr(0, 3) == "nan") || (str.substr(0, 3) == "NAN") || (str.substr(0, 3) == "NaN"))) + { + *this = this->nan(); + return true; + } + + // Remove the leading zeros for all input types. + const std::string::iterator fwd_it_leading_zero = std::find_if(str.begin(), str.end(), char_is_nonzero_predicate); + + if(fwd_it_leading_zero != str.begin()) + { + if(fwd_it_leading_zero == str.end()) + { + // The string contains nothing but leading zeros. + // This string represents zero. + operator=(zero()); + return true; + } + else + { + str.erase(str.begin(), fwd_it_leading_zero); + } + } + + // Put the input string into the standard cpp_dec_float input form + // aaa.bbbbE+/-n, where aaa has 1...cpp_dec_float_elem_digits10, bbbb has an + // even multiple of cpp_dec_float_elem_digits10 which are possibly zero padded + // on the right-end, and n is a signed 64-bit integer which is an + // even multiple of cpp_dec_float_elem_digits10. + + // Find a possible decimal point. + pos = str.find(static_cast('.')); + + if(pos != std::string::npos) + { + // Remove all trailing insignificant zeros. + const std::string::const_reverse_iterator rit_non_zero = std::find_if(str.rbegin(), str.rend(), char_is_nonzero_predicate); + + if(rit_non_zero != str.rbegin()) + { + const std::string::size_type ofs = str.length() - std::distance(str.rbegin(), rit_non_zero); + str.erase(str.begin() + ofs, str.end()); + } + + // Check if the input is identically zero. + if(str == std::string(".")) + { + operator=(zero()); + return true; + } + + // Remove leading significant zeros just after the decimal point + // and adjust the exponent accordingly. + // Note that the while-loop operates only on strings of the form ".000abcd..." + // and peels away the zeros just after the decimal point. + if(str.at(static_cast(0u)) == static_cast('.')) + { + const std::string::iterator it_non_zero = std::find_if(str.begin() + 1u, str.end(), char_is_nonzero_predicate); + + std::size_t delta_exp = static_cast(0u); + + if(str.at(static_cast(1u)) == static_cast('0')) + { + delta_exp = std::distance(str.begin() + 1u, it_non_zero); + } + + // Bring one single digit into the mantissa and adjust the exponent accordingly. + str.erase(str.begin(), it_non_zero); + str.insert(static_cast(1u), "."); + exp -= static_cast(delta_exp + 1u); + } + } + else + { + // Input string has no decimal point: Append decimal point. + str.append("."); + } + + // Shift the decimal point such that the exponent is an even multiple of cpp_dec_float_elem_digits10. + std::size_t n_shift = static_cast(0u); + const std::size_t n_exp_rem = static_cast(exp % static_cast(cpp_dec_float_elem_digits10)); + + if((exp % static_cast(cpp_dec_float_elem_digits10)) != static_cast(0)) + { + n_shift = ((exp < static_cast(0)) + ? static_cast(n_exp_rem + static_cast(cpp_dec_float_elem_digits10)) + : static_cast(n_exp_rem)); + } + + // Make sure that there are enough digits for the decimal point shift. + pos = str.find(static_cast('.')); + + std::size_t pos_plus_one = static_cast(pos + 1u); + + if((str.length() - pos_plus_one) < n_shift) + { + const std::size_t sz = static_cast(n_shift - (str.length() - pos_plus_one)); + + str.append(std::string(sz, static_cast('0'))); + } + + // Do the decimal point shift. + if(n_shift != static_cast(0u)) + { + str.insert(static_cast(pos_plus_one + n_shift), "."); + + str.erase(pos, static_cast(1u)); + + exp -= static_cast(n_shift); + } + + // Cut the size of the mantissa to <= cpp_dec_float_elem_digits10. + pos = str.find(static_cast('.')); + pos_plus_one = static_cast(pos + 1u); + + if(pos > static_cast(cpp_dec_float_elem_digits10)) + { + const boost::int32_t n_pos = static_cast(pos); + const boost::int32_t n_rem_is_zero = ((static_cast(n_pos % cpp_dec_float_elem_digits10) == static_cast(0)) ? static_cast(1) : static_cast(0)); + const boost::int32_t n = static_cast(static_cast(n_pos / cpp_dec_float_elem_digits10) - n_rem_is_zero); + + str.insert(static_cast(static_cast(n_pos - static_cast(n * cpp_dec_float_elem_digits10))), "."); + + str.erase(pos_plus_one, static_cast(1u)); + + exp += static_cast(static_cast(n) * static_cast(cpp_dec_float_elem_digits10)); + } + + // Pad the decimal part such that its value is an even + // multiple of cpp_dec_float_elem_digits10. + pos = str.find(static_cast('.')); + pos_plus_one = static_cast(pos + 1u); + + const boost::int32_t n_dec = static_cast(static_cast(str.length() - 1u) - static_cast(pos)); + const boost::int32_t n_rem = static_cast(n_dec % cpp_dec_float_elem_digits10); + boost::int32_t n_cnt = ((n_rem != static_cast(0)) ? static_cast(cpp_dec_float_elem_digits10 - n_rem) + : static_cast(0)); + + if(n_cnt != static_cast(0)) + { + str.append(static_cast(n_cnt), static_cast('0')); + } + + // Truncate decimal part if it is too long. + const std::size_t max_dec = static_cast((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); + + if(static_cast(str.length() - pos) > max_dec) + { + str = str.substr(static_cast(0u), + static_cast(pos_plus_one + max_dec)); + } + + // Now the input string has the standard cpp_dec_float input form. + // (See the comment above.) + + // Set all the data elements to 0. + std::fill(data.begin(), data.end(), static_cast(0u)); + + // Extract the data. + + // First get the digits to the left of the decimal point... + data[0u] = boost::lexical_cast(str.substr(static_cast(0u), pos)); + + // ...then get the remaining digits to the right of the decimal point. + const std::string::size_type i_end = ((str.length() - pos_plus_one) / static_cast(cpp_dec_float_elem_digits10)); + + for(std::string::size_type i = static_cast(0u); i < i_end; i++) + { + const std::string::const_iterator it = str.begin() + + pos_plus_one + + (i * static_cast(cpp_dec_float_elem_digits10)); + + data[i + 1u] = boost::lexical_cast(std::string(it, it + static_cast(cpp_dec_float_elem_digits10))); + } + + // Check for overflow... + if(exp > cpp_dec_float_max_exp10) + { + const bool b_result_is_neg = neg; + + *this = inf(); + if(b_result_is_neg) + negate(); + } + + // ...and check for underflow. + if(exp <= cpp_dec_float_min_exp10) + { + if(exp == cpp_dec_float_min_exp10) + { + // Check for identity with the minimum value. + cpp_dec_float test = *this; + + test.exp = static_cast(0); + + if(test.isone()) + { + *this = zero(); + } + } + else + { + *this = zero(); + } + } + + } + catch(const bad_lexical_cast&) + { + // Rethrow with better error message: + std::string msg = "Unable to parse the string \""; + msg += s; + msg += "\" as a floating point value."; + throw std::runtime_error(msg); + } + + return true; +} + +template +cpp_dec_float::cpp_dec_float(const double mantissa, const ExponentType exponent) BOOST_NOEXCEPT + : data (), + exp (static_cast(0)), + neg (false), + fpclass (cpp_dec_float_finite), + prec_elem(cpp_dec_float_elem_number) +{ + // Create *this cpp_dec_float from a given mantissa and exponent. + // Note: This constructor does not maintain the full precision of double. + + const bool mantissa_is_iszero = (::fabs(mantissa) < ((std::numeric_limits::min)() * (1.0 + std::numeric_limits::epsilon()))); + + if(mantissa_is_iszero) + { + std::fill(data.begin(), data.end(), static_cast(0u)); + return; + } + + const bool b_neg = (mantissa < 0.0); + + double d = ((!b_neg) ? mantissa : -mantissa); + ExponentType e = exponent; + + while(d > 10.0) { d /= 10.0; ++e; } + while(d < 1.0) { d *= 10.0; --e; } + + boost::int32_t shift = static_cast(e % static_cast(cpp_dec_float_elem_digits10)); + + while(static_cast(shift-- % cpp_dec_float_elem_digits10) != static_cast(0)) + { + d *= 10.0; + --e; + } + + exp = e; + neg = b_neg; + + std::fill(data.begin(), data.end(), static_cast(0u)); + + static const boost::int32_t digit_ratio = static_cast(static_cast(std::numeric_limits::digits10) / static_cast(cpp_dec_float_elem_digits10)); + static const boost::int32_t digit_loops = static_cast(digit_ratio + static_cast(2)); + + for(boost::int32_t i = static_cast(0); i < digit_loops; i++) + { + boost::uint32_t n = static_cast(static_cast(d)); + data[i] = static_cast(n); + d -= static_cast(n); + d *= static_cast(cpp_dec_float_elem_mask); + } +} + +template +cpp_dec_float& cpp_dec_float::operator = (long double a) BOOST_NOEXCEPT +{ + // Christopher Kormanyos's original code used a cast to long long here, but that fails + // when long double has more digits than a long long. + using std::frexp; + using std::ldexp; + using std::floor; + + if (a == 0) { + return *this = zero(); + } + + if (a == 1) { + return *this = one(); + } + + if((boost::math::isinf)(a)) + { + return *this = inf(); + } + if((boost::math::isnan)(a)) + return *this = nan(); + + int e; + long double f, term; + *this = zero(); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + *this *= pow2(shift); + if(term > 0) + add_unsigned_long_long(static_cast(term)); + else + sub_unsigned_long_long(static_cast(-term)); + f -= term; + } + if(e != 0) + *this *= pow2(e); + return *this; +} + +template +void cpp_dec_float::from_unsigned_long_long(const unsigned long long u) BOOST_NOEXCEPT +{ + std::fill(data.begin(), data.end(), static_cast(0u)); + + exp = static_cast(0); + neg = false; + fpclass = cpp_dec_float_finite; + prec_elem = cpp_dec_float_elem_number; + + std::size_t i =static_cast(0u); + + unsigned long long uu = u; + + boost::uint32_t temp[(std::numeric_limits::digits10 / static_cast(cpp_dec_float_elem_digits10)) + 3] = { static_cast(0u) }; + + while(uu != static_cast(0u)) + { + temp[i] = static_cast(uu % static_cast(cpp_dec_float_elem_mask)); + uu = static_cast(uu / static_cast(cpp_dec_float_elem_mask)); + ++i; + } + + if(i > static_cast(1u)) + { + exp += static_cast((i - 1u) * static_cast(cpp_dec_float_elem_digits10)); + } + + std::reverse(temp, temp + i); + std::copy(temp, temp + (std::min)(i, static_cast(cpp_dec_float_elem_number)), data.begin()); +} + +template +boost::uint32_t cpp_dec_float::mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p) BOOST_NOEXCEPT +{ + // + // There is a limit on how many limbs this algorithm can handle without dropping digits + // due to overflow in the carry, it is: + // + // FLOOR( (2^64 - 1) / (10^8 * 10^8) ) == 1844 + // + BOOST_STATIC_ASSERT_MSG(cpp_dec_float_elem_number < 1800, "Too many limbs in the data type for the multiplication algorithm - unsupported precision in cpp_dec_float."); + + boost::uint64_t carry = static_cast(0u); + + for(boost::int32_t j = static_cast(p - 1u); j >= static_cast(0); j--) + { + boost::uint64_t sum = carry; + + for(boost::int32_t i = j; i >= static_cast(0); i--) + { + sum += static_cast(u[j - i] * static_cast(v[i])); + } + + u[j] = static_cast(sum % static_cast(cpp_dec_float_elem_mask)); + carry = static_cast(sum / static_cast(cpp_dec_float_elem_mask)); + } + + return static_cast(carry); +} + +template +boost::uint32_t cpp_dec_float::mul_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) BOOST_NOEXCEPT +{ + boost::uint64_t carry = static_cast(0u); + + // Multiplication loop. + for(boost::int32_t j = p - 1; j >= static_cast(0); j--) + { + const boost::uint64_t t = static_cast(carry + static_cast(u[j] * static_cast(n))); + carry = static_cast(t / static_cast(cpp_dec_float_elem_mask)); + u[j] = static_cast(t - static_cast(static_cast(cpp_dec_float_elem_mask) * static_cast(carry))); + } + + return static_cast(carry); +} + +template +boost::uint32_t cpp_dec_float::div_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p) BOOST_NOEXCEPT +{ + boost::uint64_t prev = static_cast(0u); + + for(boost::int32_t j = static_cast(0); j < p; j++) + { + const boost::uint64_t t = static_cast(u[j] + static_cast(prev * static_cast(cpp_dec_float_elem_mask))); + u[j] = static_cast(t / n); + prev = static_cast(t - static_cast(n * static_cast(u[j]))); + } + + return static_cast(prev); +} + +template +cpp_dec_float cpp_dec_float::pow2(const long long p) BOOST_NOEXCEPT +{ + // Create a static const table of p^2 for -128 < p < +128. + // Note: The size of this table must be odd-numbered and + // symmetric about 0. + init.do_nothing(); + static const boost::array, 255u> p2_data = + {{ + cpp_dec_float("5.877471754111437539843682686111228389093327783860437607543758531392086297273635864257812500000000000e-39"), + cpp_dec_float("1.175494350822287507968736537222245677818665556772087521508751706278417259454727172851562500000000000e-38"), + cpp_dec_float("2.350988701644575015937473074444491355637331113544175043017503412556834518909454345703125000000000000e-38"), + cpp_dec_float("4.701977403289150031874946148888982711274662227088350086035006825113669037818908691406250000000000000e-38"), + cpp_dec_float("9.403954806578300063749892297777965422549324454176700172070013650227338075637817382812500000000000000e-38"), + cpp_dec_float("1.880790961315660012749978459555593084509864890835340034414002730045467615127563476562500000000000000e-37"), + cpp_dec_float("3.761581922631320025499956919111186169019729781670680068828005460090935230255126953125000000000000000e-37"), + cpp_dec_float("7.523163845262640050999913838222372338039459563341360137656010920181870460510253906250000000000000000e-37"), + cpp_dec_float("1.504632769052528010199982767644474467607891912668272027531202184036374092102050781250000000000000000e-36"), + cpp_dec_float("3.009265538105056020399965535288948935215783825336544055062404368072748184204101562500000000000000000e-36"), + cpp_dec_float("6.018531076210112040799931070577897870431567650673088110124808736145496368408203125000000000000000000e-36"), + cpp_dec_float("1.203706215242022408159986214115579574086313530134617622024961747229099273681640625000000000000000000e-35"), + cpp_dec_float("2.407412430484044816319972428231159148172627060269235244049923494458198547363281250000000000000000000e-35"), + cpp_dec_float("4.814824860968089632639944856462318296345254120538470488099846988916397094726562500000000000000000000e-35"), + cpp_dec_float("9.629649721936179265279889712924636592690508241076940976199693977832794189453125000000000000000000000e-35"), + cpp_dec_float("1.925929944387235853055977942584927318538101648215388195239938795566558837890625000000000000000000000e-34"), + cpp_dec_float("3.851859888774471706111955885169854637076203296430776390479877591133117675781250000000000000000000000e-34"), + cpp_dec_float("7.703719777548943412223911770339709274152406592861552780959755182266235351562500000000000000000000000e-34"), + cpp_dec_float("1.540743955509788682444782354067941854830481318572310556191951036453247070312500000000000000000000000e-33"), + cpp_dec_float("3.081487911019577364889564708135883709660962637144621112383902072906494140625000000000000000000000000e-33"), + cpp_dec_float("6.162975822039154729779129416271767419321925274289242224767804145812988281250000000000000000000000000e-33"), + cpp_dec_float("1.232595164407830945955825883254353483864385054857848444953560829162597656250000000000000000000000000e-32"), + cpp_dec_float("2.465190328815661891911651766508706967728770109715696889907121658325195312500000000000000000000000000e-32"), + cpp_dec_float("4.930380657631323783823303533017413935457540219431393779814243316650390625000000000000000000000000000e-32"), + cpp_dec_float("9.860761315262647567646607066034827870915080438862787559628486633300781250000000000000000000000000000e-32"), + cpp_dec_float("1.972152263052529513529321413206965574183016087772557511925697326660156250000000000000000000000000000e-31"), + cpp_dec_float("3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000000000000000e-31"), + cpp_dec_float("7.888609052210118054117285652827862296732064351090230047702789306640625000000000000000000000000000000e-31"), + cpp_dec_float("1.577721810442023610823457130565572459346412870218046009540557861328125000000000000000000000000000000e-30"), + cpp_dec_float("3.155443620884047221646914261131144918692825740436092019081115722656250000000000000000000000000000000e-30"), + cpp_dec_float("6.310887241768094443293828522262289837385651480872184038162231445312500000000000000000000000000000000e-30"), + cpp_dec_float("1.262177448353618888658765704452457967477130296174436807632446289062500000000000000000000000000000000e-29"), + cpp_dec_float("2.524354896707237777317531408904915934954260592348873615264892578125000000000000000000000000000000000e-29"), + cpp_dec_float("5.048709793414475554635062817809831869908521184697747230529785156250000000000000000000000000000000000e-29"), + cpp_dec_float("1.009741958682895110927012563561966373981704236939549446105957031250000000000000000000000000000000000e-28"), + cpp_dec_float("2.019483917365790221854025127123932747963408473879098892211914062500000000000000000000000000000000000e-28"), + cpp_dec_float("4.038967834731580443708050254247865495926816947758197784423828125000000000000000000000000000000000000e-28"), + cpp_dec_float("8.077935669463160887416100508495730991853633895516395568847656250000000000000000000000000000000000000e-28"), + cpp_dec_float("1.615587133892632177483220101699146198370726779103279113769531250000000000000000000000000000000000000e-27"), + cpp_dec_float("3.231174267785264354966440203398292396741453558206558227539062500000000000000000000000000000000000000e-27"), + cpp_dec_float("6.462348535570528709932880406796584793482907116413116455078125000000000000000000000000000000000000000e-27"), + cpp_dec_float("1.292469707114105741986576081359316958696581423282623291015625000000000000000000000000000000000000000e-26"), + cpp_dec_float("2.584939414228211483973152162718633917393162846565246582031250000000000000000000000000000000000000000e-26"), + cpp_dec_float("5.169878828456422967946304325437267834786325693130493164062500000000000000000000000000000000000000000e-26"), + cpp_dec_float("1.033975765691284593589260865087453566957265138626098632812500000000000000000000000000000000000000000e-25"), + cpp_dec_float("2.067951531382569187178521730174907133914530277252197265625000000000000000000000000000000000000000000e-25"), + cpp_dec_float("4.135903062765138374357043460349814267829060554504394531250000000000000000000000000000000000000000000e-25"), + cpp_dec_float("8.271806125530276748714086920699628535658121109008789062500000000000000000000000000000000000000000000e-25"), + cpp_dec_float("1.654361225106055349742817384139925707131624221801757812500000000000000000000000000000000000000000000e-24"), + cpp_dec_float("3.308722450212110699485634768279851414263248443603515625000000000000000000000000000000000000000000000e-24"), + cpp_dec_float("6.617444900424221398971269536559702828526496887207031250000000000000000000000000000000000000000000000e-24"), + cpp_dec_float("1.323488980084844279794253907311940565705299377441406250000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("2.646977960169688559588507814623881131410598754882812500000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("5.293955920339377119177015629247762262821197509765625000000000000000000000000000000000000000000000000e-23"), + cpp_dec_float("1.058791184067875423835403125849552452564239501953125000000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("2.117582368135750847670806251699104905128479003906250000000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("4.235164736271501695341612503398209810256958007812500000000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("8.470329472543003390683225006796419620513916015625000000000000000000000000000000000000000000000000000e-22"), + cpp_dec_float("1.694065894508600678136645001359283924102783203125000000000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("3.388131789017201356273290002718567848205566406250000000000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("6.776263578034402712546580005437135696411132812500000000000000000000000000000000000000000000000000000e-21"), + cpp_dec_float("1.355252715606880542509316001087427139282226562500000000000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("2.710505431213761085018632002174854278564453125000000000000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("5.421010862427522170037264004349708557128906250000000000000000000000000000000000000000000000000000000e-20"), + cpp_dec_float("1.084202172485504434007452800869941711425781250000000000000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("2.168404344971008868014905601739883422851562500000000000000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("4.336808689942017736029811203479766845703125000000000000000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("8.673617379884035472059622406959533691406250000000000000000000000000000000000000000000000000000000000e-19"), + cpp_dec_float("1.734723475976807094411924481391906738281250000000000000000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("3.469446951953614188823848962783813476562500000000000000000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("6.938893903907228377647697925567626953125000000000000000000000000000000000000000000000000000000000000e-18"), + cpp_dec_float("1.387778780781445675529539585113525390625000000000000000000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("2.775557561562891351059079170227050781250000000000000000000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("5.551115123125782702118158340454101562500000000000000000000000000000000000000000000000000000000000000e-17"), + cpp_dec_float("1.110223024625156540423631668090820312500000000000000000000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("2.220446049250313080847263336181640625000000000000000000000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("4.440892098500626161694526672363281250000000000000000000000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("8.881784197001252323389053344726562500000000000000000000000000000000000000000000000000000000000000000e-16"), + cpp_dec_float("1.776356839400250464677810668945312500000000000000000000000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("3.552713678800500929355621337890625000000000000000000000000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("7.105427357601001858711242675781250000000000000000000000000000000000000000000000000000000000000000000e-15"), + cpp_dec_float("1.421085471520200371742248535156250000000000000000000000000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("2.842170943040400743484497070312500000000000000000000000000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("5.684341886080801486968994140625000000000000000000000000000000000000000000000000000000000000000000000e-14"), + cpp_dec_float("1.136868377216160297393798828125000000000000000000000000000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("2.273736754432320594787597656250000000000000000000000000000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("4.547473508864641189575195312500000000000000000000000000000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("9.094947017729282379150390625000000000000000000000000000000000000000000000000000000000000000000000000e-13"), + cpp_dec_float("1.818989403545856475830078125000000000000000000000000000000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("3.637978807091712951660156250000000000000000000000000000000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("7.275957614183425903320312500000000000000000000000000000000000000000000000000000000000000000000000000e-12"), + cpp_dec_float("1.455191522836685180664062500000000000000000000000000000000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("2.910383045673370361328125000000000000000000000000000000000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("5.820766091346740722656250000000000000000000000000000000000000000000000000000000000000000000000000000e-11"), + cpp_dec_float("1.164153218269348144531250000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("2.328306436538696289062500000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("4.656612873077392578125000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("9.313225746154785156250000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"), + cpp_dec_float("1.862645149230957031250000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("3.725290298461914062500000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("7.450580596923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"), + cpp_dec_float("1.490116119384765625000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("2.980232238769531250000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("5.960464477539062500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"), + cpp_dec_float("1.192092895507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("2.384185791015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("4.768371582031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("9.536743164062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"), + cpp_dec_float("1.907348632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("3.814697265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("7.629394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"), + cpp_dec_float("0.000015258789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000030517578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000061035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000122070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000244140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.000976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.003906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.01562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.03125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.06250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + cpp_dec_float("0.125"), + cpp_dec_float("0.25"), + cpp_dec_float("0.5"), + one(), + two(), + cpp_dec_float(static_cast(4)), + cpp_dec_float(static_cast(8)), + cpp_dec_float(static_cast(16)), + cpp_dec_float(static_cast(32)), + cpp_dec_float(static_cast(64)), + cpp_dec_float(static_cast(128)), + cpp_dec_float(static_cast(256)), + cpp_dec_float(static_cast(512)), + cpp_dec_float(static_cast(1024)), + cpp_dec_float(static_cast(2048)), + cpp_dec_float(static_cast(4096)), + cpp_dec_float(static_cast(8192)), + cpp_dec_float(static_cast(16384)), + cpp_dec_float(static_cast(32768)), + cpp_dec_float(static_cast(65536)), + cpp_dec_float(static_cast(131072)), + cpp_dec_float(static_cast(262144)), + cpp_dec_float(static_cast(524288)), + cpp_dec_float(static_cast(1uL << 20u)), + cpp_dec_float(static_cast(1uL << 21u)), + cpp_dec_float(static_cast(1uL << 22u)), + cpp_dec_float(static_cast(1uL << 23u)), + cpp_dec_float(static_cast(1uL << 24u)), + cpp_dec_float(static_cast(1uL << 25u)), + cpp_dec_float(static_cast(1uL << 26u)), + cpp_dec_float(static_cast(1uL << 27u)), + cpp_dec_float(static_cast(1uL << 28u)), + cpp_dec_float(static_cast(1uL << 29u)), + cpp_dec_float(static_cast(1uL << 30u)), + cpp_dec_float(static_cast(1uL << 31u)), + cpp_dec_float(static_cast(1uLL << 32u)), + cpp_dec_float(static_cast(1uLL << 33u)), + cpp_dec_float(static_cast(1uLL << 34u)), + cpp_dec_float(static_cast(1uLL << 35u)), + cpp_dec_float(static_cast(1uLL << 36u)), + cpp_dec_float(static_cast(1uLL << 37u)), + cpp_dec_float(static_cast(1uLL << 38u)), + cpp_dec_float(static_cast(1uLL << 39u)), + cpp_dec_float(static_cast(1uLL << 40u)), + cpp_dec_float(static_cast(1uLL << 41u)), + cpp_dec_float(static_cast(1uLL << 42u)), + cpp_dec_float(static_cast(1uLL << 43u)), + cpp_dec_float(static_cast(1uLL << 44u)), + cpp_dec_float(static_cast(1uLL << 45u)), + cpp_dec_float(static_cast(1uLL << 46u)), + cpp_dec_float(static_cast(1uLL << 47u)), + cpp_dec_float(static_cast(1uLL << 48u)), + cpp_dec_float(static_cast(1uLL << 49u)), + cpp_dec_float(static_cast(1uLL << 50u)), + cpp_dec_float(static_cast(1uLL << 51u)), + cpp_dec_float(static_cast(1uLL << 52u)), + cpp_dec_float(static_cast(1uLL << 53u)), + cpp_dec_float(static_cast(1uLL << 54u)), + cpp_dec_float(static_cast(1uLL << 55u)), + cpp_dec_float(static_cast(1uLL << 56u)), + cpp_dec_float(static_cast(1uLL << 57u)), + cpp_dec_float(static_cast(1uLL << 58u)), + cpp_dec_float(static_cast(1uLL << 59u)), + cpp_dec_float(static_cast(1uLL << 60u)), + cpp_dec_float(static_cast(1uLL << 61u)), + cpp_dec_float(static_cast(1uLL << 62u)), + cpp_dec_float(static_cast(1uLL << 63u)), + cpp_dec_float("1.844674407370955161600000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), + cpp_dec_float("3.689348814741910323200000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), + cpp_dec_float("7.378697629483820646400000000000000000000000000000000000000000000000000000000000000000000000000000000e19"), + cpp_dec_float("1.475739525896764129280000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), + cpp_dec_float("2.951479051793528258560000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), + cpp_dec_float("5.902958103587056517120000000000000000000000000000000000000000000000000000000000000000000000000000000e20"), + cpp_dec_float("1.180591620717411303424000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), + cpp_dec_float("2.361183241434822606848000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), + cpp_dec_float("4.722366482869645213696000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), + cpp_dec_float("9.444732965739290427392000000000000000000000000000000000000000000000000000000000000000000000000000000e21"), + cpp_dec_float("1.888946593147858085478400000000000000000000000000000000000000000000000000000000000000000000000000000e22"), + cpp_dec_float("3.777893186295716170956800000000000000000000000000000000000000000000000000000000000000000000000000000e22"), + cpp_dec_float("7.555786372591432341913600000000000000000000000000000000000000000000000000000000000000000000000000000e22"), + cpp_dec_float("1.511157274518286468382720000000000000000000000000000000000000000000000000000000000000000000000000000e23"), + cpp_dec_float("3.022314549036572936765440000000000000000000000000000000000000000000000000000000000000000000000000000e23"), + cpp_dec_float("6.044629098073145873530880000000000000000000000000000000000000000000000000000000000000000000000000000e23"), + cpp_dec_float("1.208925819614629174706176000000000000000000000000000000000000000000000000000000000000000000000000000e24"), + cpp_dec_float("2.417851639229258349412352000000000000000000000000000000000000000000000000000000000000000000000000000e24"), + cpp_dec_float("4.835703278458516698824704000000000000000000000000000000000000000000000000000000000000000000000000000e24"), + cpp_dec_float("9.671406556917033397649408000000000000000000000000000000000000000000000000000000000000000000000000000e24"), + cpp_dec_float("1.934281311383406679529881600000000000000000000000000000000000000000000000000000000000000000000000000e25"), + cpp_dec_float("3.868562622766813359059763200000000000000000000000000000000000000000000000000000000000000000000000000e25"), + cpp_dec_float("7.737125245533626718119526400000000000000000000000000000000000000000000000000000000000000000000000000e25"), + cpp_dec_float("1.547425049106725343623905280000000000000000000000000000000000000000000000000000000000000000000000000e26"), + cpp_dec_float("3.094850098213450687247810560000000000000000000000000000000000000000000000000000000000000000000000000e26"), + cpp_dec_float("6.189700196426901374495621120000000000000000000000000000000000000000000000000000000000000000000000000e26"), + cpp_dec_float("1.237940039285380274899124224000000000000000000000000000000000000000000000000000000000000000000000000e27"), + cpp_dec_float("2.475880078570760549798248448000000000000000000000000000000000000000000000000000000000000000000000000e27"), + cpp_dec_float("4.951760157141521099596496896000000000000000000000000000000000000000000000000000000000000000000000000e27"), + cpp_dec_float("9.903520314283042199192993792000000000000000000000000000000000000000000000000000000000000000000000000e27"), + cpp_dec_float("1.980704062856608439838598758400000000000000000000000000000000000000000000000000000000000000000000000e28"), + cpp_dec_float("3.961408125713216879677197516800000000000000000000000000000000000000000000000000000000000000000000000e28"), + cpp_dec_float("7.922816251426433759354395033600000000000000000000000000000000000000000000000000000000000000000000000e28"), + cpp_dec_float("1.584563250285286751870879006720000000000000000000000000000000000000000000000000000000000000000000000e29"), + cpp_dec_float("3.169126500570573503741758013440000000000000000000000000000000000000000000000000000000000000000000000e29"), + cpp_dec_float("6.338253001141147007483516026880000000000000000000000000000000000000000000000000000000000000000000000e29"), + cpp_dec_float("1.267650600228229401496703205376000000000000000000000000000000000000000000000000000000000000000000000e30"), + cpp_dec_float("2.535301200456458802993406410752000000000000000000000000000000000000000000000000000000000000000000000e30"), + cpp_dec_float("5.070602400912917605986812821504000000000000000000000000000000000000000000000000000000000000000000000e30"), + cpp_dec_float("1.014120480182583521197362564300800000000000000000000000000000000000000000000000000000000000000000000e31"), + cpp_dec_float("2.028240960365167042394725128601600000000000000000000000000000000000000000000000000000000000000000000e31"), + cpp_dec_float("4.056481920730334084789450257203200000000000000000000000000000000000000000000000000000000000000000000e31"), + cpp_dec_float("8.112963841460668169578900514406400000000000000000000000000000000000000000000000000000000000000000000e31"), + cpp_dec_float("1.622592768292133633915780102881280000000000000000000000000000000000000000000000000000000000000000000e32"), + cpp_dec_float("3.245185536584267267831560205762560000000000000000000000000000000000000000000000000000000000000000000e32"), + cpp_dec_float("6.490371073168534535663120411525120000000000000000000000000000000000000000000000000000000000000000000e32"), + cpp_dec_float("1.298074214633706907132624082305024000000000000000000000000000000000000000000000000000000000000000000e33"), + cpp_dec_float("2.596148429267413814265248164610048000000000000000000000000000000000000000000000000000000000000000000e33"), + cpp_dec_float("5.192296858534827628530496329220096000000000000000000000000000000000000000000000000000000000000000000e33"), + cpp_dec_float("1.038459371706965525706099265844019200000000000000000000000000000000000000000000000000000000000000000e34"), + cpp_dec_float("2.076918743413931051412198531688038400000000000000000000000000000000000000000000000000000000000000000e34"), + cpp_dec_float("4.153837486827862102824397063376076800000000000000000000000000000000000000000000000000000000000000000e34"), + cpp_dec_float("8.307674973655724205648794126752153600000000000000000000000000000000000000000000000000000000000000000e34"), + cpp_dec_float("1.661534994731144841129758825350430720000000000000000000000000000000000000000000000000000000000000000e35"), + cpp_dec_float("3.323069989462289682259517650700861440000000000000000000000000000000000000000000000000000000000000000e35"), + cpp_dec_float("6.646139978924579364519035301401722880000000000000000000000000000000000000000000000000000000000000000e35"), + cpp_dec_float("1.329227995784915872903807060280344576000000000000000000000000000000000000000000000000000000000000000e36"), + cpp_dec_float("2.658455991569831745807614120560689152000000000000000000000000000000000000000000000000000000000000000e36"), + cpp_dec_float("5.316911983139663491615228241121378304000000000000000000000000000000000000000000000000000000000000000e36"), + cpp_dec_float("1.063382396627932698323045648224275660800000000000000000000000000000000000000000000000000000000000000e37"), + cpp_dec_float("2.126764793255865396646091296448551321600000000000000000000000000000000000000000000000000000000000000e37"), + cpp_dec_float("4.253529586511730793292182592897102643200000000000000000000000000000000000000000000000000000000000000e37"), + cpp_dec_float("8.507059173023461586584365185794205286400000000000000000000000000000000000000000000000000000000000000e37"), + cpp_dec_float("1.701411834604692317316873037158841057280000000000000000000000000000000000000000000000000000000000000e38") + }}; + + if((p > static_cast(-128)) && (p < static_cast(+128))) + { + return p2_data[static_cast(p + ((p2_data.size() - 1u) / 2u))]; + } + + // Compute and return 2^p. + if(p < static_cast(0)) + { + return pow2(static_cast(-p)).calculate_inv(); + } + else if(p < static_cast(std::numeric_limits::digits)) + { + const boost::uint64_t p2 = static_cast(static_cast(1uLL) << p); + return cpp_dec_float(p2); + } + else + { + cpp_dec_float t; + default_ops::detail::pow_imp(t, two(), p, mpl::true_()); + return t; + } +} + + +template +inline void eval_add(cpp_dec_float& result, const cpp_dec_float& o) BOOST_NOEXCEPT +{ + result += o; +} +template +inline void eval_subtract(cpp_dec_float& result, const cpp_dec_float& o) BOOST_NOEXCEPT +{ + result -= o; +} +template +inline void eval_multiply(cpp_dec_float& result, const cpp_dec_float& o) BOOST_NOEXCEPT +{ + result *= o; +} +template +inline void eval_divide(cpp_dec_float& result, const cpp_dec_float& o) BOOST_NOEXCEPT +{ + result /= o; +} + +template +inline void eval_add(cpp_dec_float& result, const unsigned long long& o) BOOST_NOEXCEPT +{ + result.add_unsigned_long_long(o); +} +template +inline void eval_subtract(cpp_dec_float& result, const unsigned long long& o) BOOST_NOEXCEPT +{ + result.sub_unsigned_long_long(o); +} +template +inline void eval_multiply(cpp_dec_float& result, const unsigned long long& o) BOOST_NOEXCEPT +{ + result.mul_unsigned_long_long(o); +} +template +inline void eval_divide(cpp_dec_float& result, const unsigned long long& o) BOOST_NOEXCEPT +{ + result.div_unsigned_long_long(o); +} + +template +inline void eval_add(cpp_dec_float& result, long long o) BOOST_NOEXCEPT +{ + if(o < 0) + result.sub_unsigned_long_long(-o); + else + result.add_unsigned_long_long(o); +} +template +inline void eval_subtract(cpp_dec_float& result, long long o) BOOST_NOEXCEPT +{ + if(o < 0) + result.add_unsigned_long_long(-o); + else + result.sub_unsigned_long_long(o); +} +template +inline void eval_multiply(cpp_dec_float& result, long long o) BOOST_NOEXCEPT +{ + if(o < 0) + { + result.mul_unsigned_long_long(-o); + result.negate(); + } + else + result.mul_unsigned_long_long(o); +} +template +inline void eval_divide(cpp_dec_float& result, long long o) BOOST_NOEXCEPT +{ + if(o < 0) + { + result.div_unsigned_long_long(-o); + result.negate(); + } + else + result.div_unsigned_long_long(o); +} + +template +inline void eval_convert_to(unsigned long long* result, const cpp_dec_float& val) BOOST_NOEXCEPT +{ + *result = val.extract_unsigned_long_long(); +} +template +inline void eval_convert_to(long long* result, const cpp_dec_float& val) BOOST_NOEXCEPT +{ + *result = val.extract_signed_long_long(); +} +template +inline void eval_convert_to(long double* result, cpp_dec_float& val) BOOST_NOEXCEPT +{ + *result = val.extract_long_double(); +} + +// +// Non member function support: +// +template +inline int eval_fpclassify(const cpp_dec_float& x) BOOST_NOEXCEPT +{ + if(x.isinf()) + return FP_INFINITE; + if(x.isnan()) + return FP_NAN; + if(x.iszero()) + return FP_ZERO; + return FP_NORMAL; +} + +template +inline void eval_abs(cpp_dec_float& result, const cpp_dec_float& x) BOOST_NOEXCEPT +{ + result = x; + if(x.isneg()) + result.negate(); +} + +template +inline void eval_fabs(cpp_dec_float& result, const cpp_dec_float& x) BOOST_NOEXCEPT +{ + result = x; + if(x.isneg()) + result.negate(); +} + +template +inline void eval_sqrt(cpp_dec_float& result, const cpp_dec_float& x) BOOST_NOEXCEPT +{ + result = x; + result.calculate_sqrt(); +} + +template +inline void eval_floor(cpp_dec_float& result, const cpp_dec_float& x) BOOST_NOEXCEPT +{ + result = x; + if(!x.isfinite() || x.isint()) + { + return; + } + + if(x.isneg()) + result -= cpp_dec_float::one(); + result = result.extract_integer_part(); +} + +template +inline void eval_ceil(cpp_dec_float& result, const cpp_dec_float& x) BOOST_NOEXCEPT +{ + result = x; + if(!x.isfinite() || x.isint()) + { + return; + } + + if(!x.isneg()) + result += cpp_dec_float::one(); + result = result.extract_integer_part(); +} + +template +inline void eval_trunc(cpp_dec_float& result, const cpp_dec_float& x) +{ + if(!x.isfinite()) + { + result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number >(x), 0, boost::math::policies::policy<>()).backend(); + return; + } + else if(x.isint()) + { + result = x; + return; + } + result = x.extract_integer_part(); +} + +template +inline void eval_ldexp(cpp_dec_float& result, const cpp_dec_float& x, ArgType e) BOOST_NOEXCEPT +{ + if((static_cast(e) > (std::numeric_limits::max)()) || (static_cast(e) < (std::numeric_limits::min)())) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Exponent value is out of range."))); + result = x; + result *= cpp_dec_float::pow2(e); +} + +template +inline void eval_frexp(cpp_dec_float& result, const cpp_dec_float& x, ExponentType* e) +{ + result = x; + if(result.isneg()) + result.negate(); + + if(result.iszero()) + { + *e = 0; + return; + } + + ExponentType t = result.order(); + BOOST_MP_USING_ABS + if(abs(t) < ((std::numeric_limits::max)() / 1000)) + { + t *= 1000; + t /= 301; + } + else + { + t /= 301; + t *= 1000; + } + + result *= cpp_dec_float::pow2(-t); + + if(result.iszero() || result.isinf() || result.isnan()) + { + // pow2 overflowed, slip the calculation up: + result = x; + if(result.isneg()) + result.negate(); + t /= 2; + result *= cpp_dec_float::pow2(-t); + } + BOOST_MP_USING_ABS + if(abs(result.order()) > 5) + { + // If our first estimate doesn't get close enough then try recursion until we do: + ExponentType e2; + cpp_dec_float r2; + eval_frexp(r2, result, &e2); + // overflow protection: + if((t > 0) && (e2 > 0) && (t > (std::numeric_limits::max)() - e2)) + BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); + if((t < 0) && (e2 < 0) && (t < (std::numeric_limits::min)() - e2)) + BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); + t += e2; + result = r2; + } + + while(result.compare(cpp_dec_float::one()) >= 0) + { + result /= cpp_dec_float::two(); + ++t; + } + while(result.compare(cpp_dec_float::half()) < 0) + { + result *= cpp_dec_float::two(); + --t; + } + *e = t; + if(x.isneg()) + result.negate(); +} + +template +inline typename disable_if >::type eval_frexp(cpp_dec_float& result, const cpp_dec_float& x, int* e) +{ + ExponentType t; + eval_frexp(result, x, &t); + if((t > (std::numeric_limits::max)()) || (t < (std::numeric_limits::min)())) + BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is outside the range of an int")); + *e = static_cast(t); +} + +template +inline bool eval_is_zero(const cpp_dec_float& val) BOOST_NOEXCEPT +{ + return val.iszero(); +} +template +inline int eval_get_sign(const cpp_dec_float& val) BOOST_NOEXCEPT +{ + return val.iszero() ? 0 : val.isneg() ? -1 : 1; +} + +} // namespace backends + +using boost::multiprecision::backends::cpp_dec_float; + + +typedef number > cpp_dec_float_50; +typedef number > cpp_dec_float_100; + +#ifdef BOOST_NO_SFINAE_EXPR + +namespace detail{ + +template +struct is_explicitly_convertible, cpp_dec_float > : public mpl::true_ {}; + +} + +#endif + + +}} + +namespace std +{ + template + class numeric_limits, ExpressionTemplates> > + { + public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + BOOST_STATIC_CONSTEXPR int digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + BOOST_STATIC_CONSTEXPR int max_digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_total_digits10; + BOOST_STATIC_CONSTEXPR ExponentType min_exponent = boost::multiprecision::cpp_dec_float::cpp_dec_float_min_exp; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType min_exponent10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_min_exp10; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType max_exponent = boost::multiprecision::cpp_dec_float::cpp_dec_float_max_exp; // Type differs from int. + BOOST_STATIC_CONSTEXPR ExponentType max_exponent10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_max_exp10; // Type differs from int. + BOOST_STATIC_CONSTEXPR int radix = boost::multiprecision::cpp_dec_float::cpp_dec_float_radix; + BOOST_STATIC_CONSTEXPR std::float_round_style round_style = std::round_to_nearest; + BOOST_STATIC_CONSTEXPR bool has_infinity = true; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR std::float_denorm_style has_denorm = std::denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> (min) (void) { return (boost::multiprecision::cpp_dec_float::min)(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> (max) (void) { return (boost::multiprecision::cpp_dec_float::max)(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> lowest (void) { return boost::multiprecision::cpp_dec_float::zero(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> epsilon (void) { return boost::multiprecision::cpp_dec_float::eps(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> round_error (void) { return 0.5L; } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> infinity (void) { return boost::multiprecision::cpp_dec_float::inf(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> quiet_NaN (void) { return boost::multiprecision::cpp_dec_float::nan(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> signaling_NaN(void) { return boost::multiprecision::cpp_dec_float::zero(); } + BOOST_STATIC_CONSTEXPR boost::multiprecision::number, ExpressionTemplates> denorm_min (void) { return boost::multiprecision::cpp_dec_float::zero(); } + }; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +template +BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits, ExpressionTemplates> >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; + +#endif +} + +namespace boost{ namespace math{ + +namespace policies{ + +template +struct precision< boost::multiprecision::number, ExpressionTemplates>, Policy> +{ + // Define a local copy of cpp_dec_float_digits10 because it might differ + // from the template parameter Digits10 for small or large digit counts. + static const boost::int32_t cpp_dec_float_digits10 = boost::multiprecision::cpp_dec_float::cpp_dec_float_digits10; + + typedef typename Policy::precision_type precision_type; + typedef digits2<((cpp_dec_float_digits10 + 1LL) * 1000LL) / 301LL> digits_2; + typedef typename mpl::if_c< + ((digits_2::value <= precision_type::value) + || (Policy::precision_type::value <= 0)), + // Default case, full precision for RealType: + digits_2, + // User customised precision: + precision_type + >::type type; +}; + +} // namespace policies + +}} // namespaces boost::math + + +#endif + diff --git a/include/boost/multiprecision/cpp_int.hpp b/include/boost/multiprecision/cpp_int.hpp new file mode 100644 index 00000000..be4cfcca --- /dev/null +++ b/include/boost/multiprecision/cpp_int.hpp @@ -0,0 +1,1830 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_CPP_INT_HPP +#define BOOST_MP_CPP_INT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace multiprecision{ + +namespace backends{ + +#ifdef BOOST_MSVC +// warning C4127: conditional expression is constant +#pragma warning(push) +#pragma warning(disable:4127 4351 4293 4996 4307 4702) +#endif + +template >::type > +struct cpp_int_backend; + +template +struct cpp_int_base; +// +// Traits class determines the maximum and minimum precision values: +// +template struct max_precision; + +template +struct max_precision > +{ + static const unsigned value = is_void::value ? + static_unsigned_max::value + : (((MaxBits >= MinBits) && MaxBits) ? MaxBits : UINT_MAX); +}; + +template struct min_precision; + +template +struct min_precision > +{ + static const unsigned value = (is_void::value ? static_unsigned_max::value : MinBits); +}; +// +// Traits class determines whether the number of bits precision requested could fit in a native type, +// we call this a "trivial" cpp_int: +// +template +struct is_trivial_cpp_int +{ + static const bool value = false; +}; + +template +struct is_trivial_cpp_int > +{ + typedef cpp_int_backend self; + static const bool value = is_void::value && (max_precision::value <= (sizeof(double_limb_type) * CHAR_BIT) - (SignType == signed_packed ? 1 : 0)); +}; + +template +struct is_trivial_cpp_int > +{ + static const bool value = true; +}; + +} // namespace backends +// +// Traits class to determine whether a cpp_int_backend is signed or not: +// +template +struct is_unsigned_number > + : public mpl::bool_<(SignType == unsigned_magnitude) || (SignType == unsigned_packed)>{}; + +namespace backends{ +// +// Traits class determines whether T should be implicitly convertible to U, or +// whether the constructor should be made explicit. The latter happens if we +// are losing the sign, or have fewer digits precision in the target type: +// +template +struct is_implicit_cpp_int_conversion; + +template +struct is_implicit_cpp_int_conversion, cpp_int_backend > +{ + typedef cpp_int_backend t1; + typedef cpp_int_backend t2; + static const bool value = + (is_signed_number::value || !is_signed_number::value) + && (max_precision::value <= max_precision::value); +}; + +// +// Traits class to determine whether operations on a cpp_int may throw: +// +template +struct is_non_throwing_cpp_int : public mpl::false_{}; +template +struct is_non_throwing_cpp_int > : public mpl::true_ {}; + +// +// Traits class, determines whether the cpp_int is fixed precision or not: +// +template +struct is_fixed_precision; +template +struct is_fixed_precision > + : public mpl::bool_ >::value != UINT_MAX> {}; + +namespace detail{ + +inline void verify_new_size(unsigned new_size, unsigned min_size, const mpl::int_&) +{ + if(new_size < min_size) + BOOST_THROW_EXCEPTION(std::overflow_error("Unable to allocate sufficient storage for the value of the result: value overflows the maximum allowable magnitude.")); +} +inline void verify_new_size(unsigned /*new_size*/, unsigned /*min_size*/, const mpl::int_&){} + +template +inline void verify_limb_mask(bool b, U limb, U mask, const mpl::int_&) +{ + // When we mask out "limb" with "mask", do we loose bits? If so it's an overflow error: + if(b && (limb & ~mask)) + BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in cpp_int arithmetic: there is insufficient precision in the target type to hold all of the bits of the result.")); +} +template +inline void verify_limb_mask(bool /*b*/, U /*limb*/, U /*mask*/, const mpl::int_&){} + +} + +// +// Now define the various data layouts that are possible as partial specializations of the base class, +// starting with the default arbitrary precision signed integer type: +// +template +struct cpp_int_base : private Allocator::template rebind::other +{ + typedef typename Allocator::template rebind::other allocator_type; + typedef typename allocator_type::pointer limb_pointer; + typedef typename allocator_type::const_pointer const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT(!is_void::value); + +private: + struct limb_data + { + unsigned capacity; + limb_pointer data; + }; + +public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = + MinBits + ? MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0) + : sizeof(limb_data) / sizeof(limb_type)); + BOOST_STATIC_CONSTANT(bool, variable = true); + +private: + union data_type + { + limb_data ld; + limb_type la[internal_limb_count]; + limb_type first; + double_limb_type double_first; + + BOOST_CONSTEXPR data_type() : first(0) {} + BOOST_CONSTEXPR data_type(limb_type i) : first(i) {} + BOOST_CONSTEXPR data_type(signed_limb_type i) : first(i < 0 ? -i : i) {} +#ifdef BOOST_LITTLE_ENDIAN + BOOST_CONSTEXPR data_type(double_limb_type i) : double_first(i) {} + BOOST_CONSTEXPR data_type(signed_double_limb_type i) : double_first(i < 0 ? -i : i) {} +#endif + }; + + data_type m_data; + unsigned m_limbs; + bool m_sign, m_internal; + +public: + // + // Direct construction: + // + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT + : m_data(i), m_limbs(1), m_sign(false), m_internal(true) { } + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT + : m_data(i), m_limbs(1), m_sign(i < 0), m_internal(true) { } +#if defined(BOOST_LITTLE_ENDIAN) + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT + : m_data(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false), m_internal(true) { } + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT + : m_data(i), m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), + m_sign(i < 0), m_internal(true) { } +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_FORCEINLINE allocator_type& allocator() BOOST_NOEXCEPT { return *this; } + BOOST_FORCEINLINE const allocator_type& allocator()const BOOST_NOEXCEPT { return *this; } + BOOST_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } + BOOST_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; } + BOOST_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_internal ? m_data.la : m_data.ld.data; } + BOOST_FORCEINLINE unsigned capacity()const BOOST_NOEXCEPT { return m_internal ? internal_limb_count : m_data.ld.capacity; } + BOOST_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; } + void sign(bool b) BOOST_NOEXCEPT + { + m_sign = b; + // Check for zero value: + if(m_sign && (m_limbs == 1)) + { + if(limbs()[0] == 0) + m_sign = false; + } + } + void resize(unsigned new_size, unsigned min_size) + { + static const unsigned max_limbs = MaxBits / (CHAR_BIT * sizeof(limb_type)) + (MaxBits % (CHAR_BIT * sizeof(limb_type)) ? 1 : 0); + // We never resize beyond MaxSize: + if(new_size > max_limbs) + new_size = max_limbs; + detail::verify_new_size(new_size, min_size, checked_type()); + // See if we have enough capacity already: + unsigned cap = capacity(); + if(new_size > cap) + { + // Allocate a new buffer and copy everything over: + cap = (std::min)((std::max)(cap * 4, new_size), max_limbs); + limb_pointer pl = allocator().allocate(cap); + std::copy(limbs(), limbs() + size(), pl); + if(!m_internal) + allocator().deallocate(limbs(), capacity()); + else + m_internal = false; + m_limbs = new_size; + m_data.ld.capacity = cap; + m_data.ld.data = pl; + } + else + { + m_limbs = new_size; + } + } + BOOST_FORCEINLINE void normalize() BOOST_NOEXCEPT + { + limb_pointer p = limbs(); + while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; + } + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT : m_data(), m_limbs(1), m_sign(false), m_internal(true) {} + BOOST_FORCEINLINE cpp_int_base(const cpp_int_base& o) : allocator_type(o), m_limbs(0), m_internal(true) + { + resize(o.size(), o.size()); + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + m_sign = o.m_sign; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + cpp_int_base(cpp_int_base&& o) + : allocator_type(static_cast(o)), m_limbs(o.m_limbs), m_sign(o.m_sign), m_internal(o.m_internal) + { + if(m_internal) + { + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + } + else + { + m_data.ld = o.m_data.ld; + o.m_limbs = 0; + o.m_internal = true; + } + } + cpp_int_base& operator = (cpp_int_base&& o) BOOST_NOEXCEPT + { + if(!m_internal) + allocator().deallocate(m_data.ld.data, m_data.ld.capacity); + *static_cast(this) = static_cast(o); + m_limbs = o.m_limbs; + m_sign = o.m_sign; + m_internal = o.m_internal; + if(m_internal) + { + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + } + else + { + m_data.ld = o.m_data.ld; + o.m_limbs = 0; + o.m_internal = true; + } + return *this; + } +#endif + BOOST_FORCEINLINE ~cpp_int_base() BOOST_NOEXCEPT + { + if(!m_internal) + allocator().deallocate(limbs(), capacity()); + } + void assign(const cpp_int_base& o) + { + if(this != &o) + { + static_cast(*this) = static_cast(o); + m_limbs = 0; + resize(o.size(), o.size()); + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + m_sign = o.m_sign; + } + } + BOOST_FORCEINLINE void negate() BOOST_NOEXCEPT + { + m_sign = !m_sign; + // Check for zero value: + if(m_sign && (m_limbs == 1)) + { + if(limbs()[0] == 0) + m_sign = false; + } + } + BOOST_FORCEINLINE bool isneg()const BOOST_NOEXCEPT + { + return m_sign; + } + BOOST_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT + { + std::swap(m_data, o.m_data); + std::swap(m_sign, o.m_sign); + std::swap(m_internal, o.m_internal); + std::swap(m_limbs, o.m_limbs); + } +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +const unsigned cpp_int_base::limb_bits; +template +const limb_type cpp_int_base::max_limb_value; +template +const limb_type cpp_int_base::sign_bit_mask; +template +const unsigned cpp_int_base::internal_limb_count; +template +const bool cpp_int_base::variable; + +#endif + +template +struct cpp_int_base : private Allocator::template rebind::other +{ + // + // There is currently no support for unsigned arbitrary precision arithmetic, largely + // because it's not clear what subtraction should do: + // + BOOST_STATIC_ASSERT_MSG(((sizeof(Allocator) == 0) && !is_void::value), "There is curently no support for unsigned arbitrary precision integers."); +}; +// +// Fixed precision (i.e. no allocator), signed-magnitude type with limb-usage count: +// +template +struct cpp_int_base +{ + typedef limb_type* limb_pointer; + typedef const limb_type* const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + +public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0)); + BOOST_STATIC_CONSTANT(bool, variable = false); + BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0))); + BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs"); + +private: + union data_type{ + limb_type m_data[internal_limb_count]; + limb_type m_first_limb; + double_limb_type m_double_first_limb; + + BOOST_CONSTEXPR data_type(){} + BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {} + BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {} + } m_wrapper; + boost::uint16_t m_limbs; + bool m_sign; + +public: + // + // Direct construction: + // + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(1), m_sign(false) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT + : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1), m_sign(i < 0) {} +#if defined(BOOST_LITTLE_ENDIAN) + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT + : m_wrapper(double_limb_type(i < 0 ? -i : i)), + m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)), + m_sign(i < 0) {} +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } + BOOST_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; } + BOOST_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; } + BOOST_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; } + BOOST_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT + { + m_sign = b; + // Check for zero value: + if(m_sign && (m_limbs == 1)) + { + if(limbs()[0] == 0) + m_sign = false; + } + } + BOOST_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + m_limbs = static_cast((std::min)(new_size, internal_limb_count)); + detail::verify_new_size(m_limbs, min_size, checked_type()); + } + BOOST_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + limb_pointer p = limbs(); + detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type()); + p[internal_limb_count-1] &= upper_limb_mask; + while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; + if((m_limbs == 1) && (!*p)) m_sign = false; // zero is always unsigned + } + + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_wrapper(limb_type(0u)), m_limbs(1), m_sign(false) {} + BOOST_FORCEINLINE cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT : m_limbs(o.m_limbs), m_sign(o.m_sign) + { + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + } + //~cpp_int_base() BOOST_NOEXCEPT {} + void assign(const cpp_int_base& o) BOOST_NOEXCEPT + { + if(this != &o) + { + resize(o.size(), o.size()); + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + m_sign = o.m_sign; + } + } + BOOST_FORCEINLINE void negate() BOOST_NOEXCEPT + { + m_sign = !m_sign; + // Check for zero value: + if(m_sign && (m_limbs == 1)) + { + if(limbs()[0] == 0) + m_sign = false; + } + } + BOOST_FORCEINLINE bool isneg()const BOOST_NOEXCEPT + { + return m_sign; + } + BOOST_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT + { + for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i) + std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); + std::swap(m_sign, o.m_sign); + std::swap(m_limbs, o.m_limbs); + } +}; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +const unsigned cpp_int_base::limb_bits; +template +const limb_type cpp_int_base::max_limb_value; +template +const limb_type cpp_int_base::sign_bit_mask; +template +const unsigned cpp_int_base::internal_limb_count; +template +const bool cpp_int_base::variable; + +#endif +// +// Fixed precision (i.e. no allocator), unsigned type with limb-usage count: +// +template +struct cpp_int_base +{ + typedef limb_type* limb_pointer; + typedef const limb_type* const_limb_pointer; + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits > sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); + +public: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast(0u)); + BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1)); + BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + (MinBits % limb_bits ? 1 : 0)); + BOOST_STATIC_CONSTANT(bool, variable = false); + BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = MinBits % limb_bits ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0))); + BOOST_STATIC_ASSERT_MSG(internal_limb_count >= 2, "A fixed precision integer type must have at least 2 limbs"); + +private: + union data_type{ + limb_type m_data[internal_limb_count]; + limb_type m_first_limb; + double_limb_type m_double_first_limb; + + BOOST_CONSTEXPR data_type() {} + BOOST_CONSTEXPR data_type(limb_type i) : m_first_limb(i) {} + BOOST_CONSTEXPR data_type(double_limb_type i) : m_double_first_limb(i) {} + } m_wrapper; + limb_type m_limbs; + +public: + // + // Direct construction: + // + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(limb_type i)BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(1) {} + BOOST_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_wrapper(limb_type(i < 0 ? -i : i)), m_limbs(1) { if(i < 0) negate(); } +#ifdef BOOST_LITTLE_ENDIAN + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT + : m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {} + BOOST_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_wrapper(double_limb_type(i < 0 ? -i : i)), m_limbs(i < 0 ? (-i > max_limb_value ? 2 : 1) : (i > max_limb_value ? 2 : 1)) { if(i < 0) negate(); } +#endif + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_FORCEINLINE unsigned size()const BOOST_NOEXCEPT { return m_limbs; } + BOOST_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return m_wrapper.m_data; } + BOOST_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return m_wrapper.m_data; } + BOOST_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; } + BOOST_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked)) { if(b) negate(); } + BOOST_FORCEINLINE void resize(unsigned new_size, unsigned min_size) BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + m_limbs = (std::min)(new_size, internal_limb_count); + detail::verify_new_size(m_limbs, min_size, checked_type()); + } + BOOST_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + limb_pointer p = limbs(); + detail::verify_limb_mask(m_limbs == internal_limb_count, p[internal_limb_count-1], upper_limb_mask, checked_type()); + p[internal_limb_count-1] &= upper_limb_mask; + while((m_limbs-1) && !p[m_limbs - 1])--m_limbs; + } + + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() BOOST_NOEXCEPT + : m_wrapper(limb_type(0u)), m_limbs(1) {} + BOOST_FORCEINLINE cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT + : m_limbs(o.m_limbs) + { + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + } + //~cpp_int_base() BOOST_NOEXCEPT {} + BOOST_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT + { + if(this != &o) + { + resize(o.size(), o.size()); + std::copy(o.limbs(), o.limbs() + o.size(), limbs()); + } + } +private: + void check_negate(const mpl::int_&) + { + BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned number.")); + } + void check_negate(const mpl::int_&){} +public: + void negate() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + // Not so much a negate as a complement - this gets called when subtraction + // would result in a "negative" number: + unsigned i; + if((m_limbs == 1) && (m_wrapper.m_data[0] == 0)) + return; // negating zero is always zero, and always OK. + check_negate(checked_type()); + for(i = m_limbs; i < internal_limb_count; ++i) + m_wrapper.m_data[i] = 0; + m_limbs = internal_limb_count; + for(i = 0; i < internal_limb_count; ++i) + m_wrapper.m_data[i] = ~m_wrapper.m_data[i]; + normalize(); + eval_increment(static_cast& >(*this)); + } + BOOST_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT + { + return false; + } + BOOST_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT + { + for(unsigned i = 0; i < (std::max)(size(), o.size()); ++i) + std::swap(m_wrapper.m_data[i], o.m_wrapper.m_data[i]); + std::swap(m_limbs, o.m_limbs); + } +}; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +const unsigned cpp_int_base::limb_bits; +template +const limb_type cpp_int_base::max_limb_value; +template +const limb_type cpp_int_base::sign_bit_mask; +template +const unsigned cpp_int_base::internal_limb_count; +template +const bool cpp_int_base::variable; + +#endif +// +// Traits classes to figure out a native type with N bits, these vary from boost::uint_t only +// because some platforms have native integer types longer than long long, "really long long" anyone?? +// +template +struct trivial_limb_type_imp +{ + typedef double_limb_type type; +}; + +template +struct trivial_limb_type_imp +{ + typedef typename boost::uint_t::least type; +}; + +template +struct trivial_limb_type : public trivial_limb_type_imp {}; +// +// Backend for fixed precision signed-magnitude type which will fit entirely inside a "double_limb_type": +// +template +struct cpp_int_base +{ + typedef typename trivial_limb_type::type local_limb_type; + typedef local_limb_type* limb_pointer; + typedef const local_limb_type* const_limb_pointer; + typedef mpl::int_ checked_type; +protected: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = MinBits < limb_bits ? (local_limb_type(1) << MinBits) -1 : (~local_limb_type(0))); +private: + local_limb_type m_data; + bool m_sign; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); +protected: + template + typename disable_if_c::is_specialized && (std::numeric_limits::digits <= MinBits)>::type + check_in_range(T val, const mpl::int_&) + { + BOOST_MP_USING_ABS + typedef typename common_type::type common_type; + + if(static_cast(abs(val)) > static_cast(limb_mask)) + BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); + } + template + void check_in_range(T, const mpl::int_&){} + + template + void check_in_range(T val) + { + check_in_range(val, checked_type()); + } + +public: + // + // Direct construction: + // + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(i < 0 ? static_cast(-i) : static_cast(i)), m_sign(i < 0) {} + template + BOOST_FORCEINLINE cpp_int_base(SI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(i < 0 ? static_cast(-i) : static_cast(i)), m_sign(i < 0) { check_in_range(i); } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(i)), m_sign(false) {} + template + BOOST_FORCEINLINE cpp_int_base(UI i, typename enable_if_c::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(i)), m_sign(false) { check_in_range(i); } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(F i, typename enable_if_c::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(std::fabs(i))), m_sign(i < 0) {} + template + BOOST_FORCEINLINE cpp_int_base(F i, typename enable_if_c::value && (Checked == checked)>::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(std::fabs(i))), m_sign(i < 0) { check_in_range(i); } + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; } + BOOST_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; } + BOOST_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; } + BOOST_FORCEINLINE bool sign()const BOOST_NOEXCEPT { return m_sign; } + BOOST_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT + { + m_sign = b; + // Check for zero value: + if(m_sign && !m_data) + { + m_sign = false; + } + } + BOOST_FORCEINLINE void resize(unsigned new_size, unsigned min_size) + { + detail::verify_new_size(2, min_size, checked_type()); + } + BOOST_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + if(!m_data) + m_sign = false; // zero is always unsigned + detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); + m_data &= limb_mask; + } + + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0), m_sign(false) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT + : m_data(o.m_data), m_sign(o.m_sign) {} + //~cpp_int_base() BOOST_NOEXCEPT {} + BOOST_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT + { + m_data = o.m_data; + m_sign = o.m_sign; + } + BOOST_FORCEINLINE void negate() BOOST_NOEXCEPT + { + m_sign = !m_sign; + // Check for zero value: + if(m_data == 0) + { + m_sign = false; + } + } + BOOST_FORCEINLINE bool isneg()const BOOST_NOEXCEPT + { + return m_sign; + } + BOOST_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT + { + std::swap(m_sign, o.m_sign); + std::swap(m_data, o.m_data); + } +}; +// +// Backend for unsigned fixed precision (i.e. no allocator) type which will fit entirely inside a "double_limb_type": +// +template +struct cpp_int_base +{ + typedef typename trivial_limb_type::type local_limb_type; + typedef local_limb_type* limb_pointer; + typedef const local_limb_type* const_limb_pointer; +private: + BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(local_limb_type) * CHAR_BIT); + BOOST_STATIC_CONSTANT(local_limb_type, limb_mask = (~local_limb_type(0)) >> (limb_bits - MinBits)); + + local_limb_type m_data; + + typedef mpl::int_ checked_type; + + // + // Interface invariants: + // + BOOST_STATIC_ASSERT_MSG(MinBits <= sizeof(double_limb_type) * CHAR_BIT, "Template parameter MinBits is inconsistent with the parameter trivial - did you mistakingly try to override the trivial parameter?"); +protected: + template + typename disable_if_c::is_specialized && (std::numeric_limits::digits <= MinBits)>::type + check_in_range(T val, const mpl::int_&, const mpl::false_&) + { + typedef typename common_type::type common_type; + + if(static_cast(val) > limb_mask) + BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); + } + template + void check_in_range(T val, const mpl::int_&, const mpl::true_&) + { + typedef typename common_type::type common_type; + + if(static_cast(val) > limb_mask) + BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent.")); + if(val < 0) + BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative.")); + } + template + BOOST_FORCEINLINE void check_in_range(T, const mpl::int_&, const mpl::bool_&){} + + template + BOOST_FORCEINLINE void check_in_range(T val) + { + check_in_range(val, checked_type(), is_signed()); + } + +public: + // + // Direct construction: + // + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(i < 0 ? 1 + ~static_cast(-i) : static_cast(i)) {} + template + BOOST_FORCEINLINE cpp_int_base(SI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(i < 0 ? 1 + ~static_cast(-i) : static_cast(i)) { check_in_range(i); } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(i)) {} + template + BOOST_FORCEINLINE cpp_int_base(UI i, typename enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(i)) { check_in_range(i); } + template + BOOST_FORCEINLINE cpp_int_base(F i, typename enable_if >::type const* = 0) BOOST_NOEXCEPT_IF((Checked == unchecked)) + : m_data(static_cast(std::fabs(i))) + { + check_in_range(i); + if(i < 0) + negate(); + } + // + // Helper functions for getting at our internal data, and manipulating storage: + // + BOOST_FORCEINLINE BOOST_CONSTEXPR unsigned size()const BOOST_NOEXCEPT { return 1; } + BOOST_FORCEINLINE limb_pointer limbs() BOOST_NOEXCEPT { return &m_data; } + BOOST_FORCEINLINE const_limb_pointer limbs()const BOOST_NOEXCEPT { return &m_data; } + BOOST_FORCEINLINE BOOST_CONSTEXPR bool sign()const BOOST_NOEXCEPT { return false; } + BOOST_FORCEINLINE void sign(bool b) BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + if(b) + negate(); + } + BOOST_FORCEINLINE void resize(unsigned new_size, unsigned min_size) + { + detail::verify_new_size(2, min_size, checked_type()); + } + BOOST_FORCEINLINE void normalize() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + detail::verify_limb_mask(true, m_data, limb_mask, checked_type()); + m_data &= limb_mask; + } + + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base() : m_data(0) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(const cpp_int_base& o) BOOST_NOEXCEPT + : m_data(o.m_data) {} + //~cpp_int_base() BOOST_NOEXCEPT {} + BOOST_FORCEINLINE void assign(const cpp_int_base& o) BOOST_NOEXCEPT + { + m_data = o.m_data; + } + BOOST_FORCEINLINE void negate() BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + if(Checked == checked) + { + BOOST_THROW_EXCEPTION(std::range_error("Attempt to negate an unsigned type.")); + } + m_data = ~m_data; + ++m_data; + } + BOOST_FORCEINLINE BOOST_CONSTEXPR bool isneg()const BOOST_NOEXCEPT + { + return false; + } + BOOST_FORCEINLINE void do_swap(cpp_int_base& o) BOOST_NOEXCEPT + { + std::swap(m_data, o.m_data); + } +}; +// +// Traits class, lets us know whether type T can be directly converted to the base type, +// used to enable/disable constructors etc: +// +template +struct is_allowed_cpp_int_base_conversion : public mpl::if_c< + is_same::value || is_same::value +#ifdef BOOST_LITTLE_ENDIAN + || is_same::value || is_same::value +#endif + || (is_trivial_cpp_int::value && is_arithmetic::value), + mpl::true_, + mpl::false_ + >::type +{}; +// +// Now the actual backend, normalising parameters passed to the base class: +// +template +struct cpp_int_backend + : public cpp_int_base< + min_precision >::value, + max_precision >::value, + SignType, + Checked, + Allocator, + is_trivial_cpp_int >::value> +{ + typedef cpp_int_backend self_type; + typedef cpp_int_base< + min_precision::value, + max_precision::value, + SignType, + Checked, + Allocator, + is_trivial_cpp_int::value> base_type; + typedef mpl::bool_::value> trivial_tag; +public: + typedef typename mpl::if_< + trivial_tag, + mpl::list< + signed char, short, int, long, + long long, signed_double_limb_type>, + mpl::list + >::type signed_types; + typedef typename mpl::if_< + trivial_tag, + mpl::list, + mpl::list + >::type unsigned_types; + typedef typename mpl::if_< + trivial_tag, + mpl::list, + mpl::list + >::type float_types; + typedef mpl::int_ checked_type; + + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend() BOOST_NOEXCEPT{} + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(const cpp_int_backend& o) BOOST_NOEXCEPT_IF(boost::is_void::value) : base_type(o) {} +#ifndef BOOST_NO_RVALUE_REFERENCES + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(cpp_int_backend&& o) BOOST_NOEXCEPT + : base_type(static_cast(o)) {} +#endif + // + // Direct construction from arithmetic type: + // + template + BOOST_FORCEINLINE BOOST_CONSTEXPR cpp_int_backend(Arg i, typename enable_if_c::value >::type const* = 0)BOOST_NOEXCEPT_IF((Checked == unchecked)) + : base_type(i) {} + +private: + template + void do_assign(const cpp_int_backend& other, mpl::true_ const&, mpl::true_ const &) + { + // Assigning trivial type to trivial type: + this->check_in_range(*other.limbs()); + *this->limbs() = static_cast(*other.limbs()); + this->sign(other.sign()); + this->normalize(); + } + template + void do_assign(const cpp_int_backend& other, mpl::true_ const&, mpl::false_ const &) + { + // non-trivial to trivial narrowing conversion: + double_limb_type v = *other.limbs(); + if(other.size() > 1) + { + v |= static_cast(other.limbs()[1]) << bits_per_limb; + if((Checked == checked) && (other.size() > 2)) + { + BOOST_THROW_EXCEPTION(std::range_error("Assignment of a cpp_int that is out of range for the target type.")); + } + } + *this = v; + this->sign(other.sign()); + this->normalize(); + } + template + void do_assign(const cpp_int_backend& other, mpl::false_ const&, mpl::true_ const &) + { + // trivial to non-trivial, treat the trivial argument as if it were an unsigned arithmetic type, then set the sign afterwards: + *this = static_cast< + typename boost::multiprecision::detail::canonical< + typename cpp_int_backend::local_limb_type, + cpp_int_backend + >::type + >(*other.limbs()); + this->sign(other.sign()); + } + template + void do_assign(const cpp_int_backend& other, mpl::false_ const&, mpl::false_ const &) + { + // regular non-trivial to non-trivial assign: + this->resize(other.size(), other.size()); + std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs()); + this->sign(other.sign()); + this->normalize(); + } +public: + template + cpp_int_backend( + const cpp_int_backend& other, + typename enable_if_c, self_type>::value>::type* = 0) + : base_type() + { + do_assign( + other, + mpl::bool_::value>(), + mpl::bool_ >::value>()); + } + template + explicit cpp_int_backend( + const cpp_int_backend& other, + typename disable_if_c, self_type>::value>::type* = 0) + : base_type() + { + do_assign( + other, + mpl::bool_::value>(), + mpl::bool_ >::value>()); + } + template + cpp_int_backend& operator=( + const cpp_int_backend& other) + { + do_assign( + other, + mpl::bool_::value>(), + mpl::bool_ >::value>()); + return *this; + } +#if 0 + template + cpp_int_backend(const cpp_int_backend& other, typename enable_if_c >::value >::type* = 0) + : base_type() + { + *this = static_cast< + typename boost::multiprecision::detail::canonical< + typename cpp_int_backend::local_limb_type, + cpp_int_backend + >::type + >(*other.limbs()); + this->sign(other.sign()); + } + template + typename enable_if_c >::value, cpp_int_backend&>::type + operator=(const cpp_int_backend& other) + { + *this = static_cast< + typename boost::multiprecision::detail::canonical< + typename cpp_int_backend::local_limb_type, + cpp_int_backend + >::type + >(*other.limbs()); + this->sign(other.sign()); + return *this; + } + + template + cpp_int_backend(const cpp_int_backend& other, + typename enable_if_c< + ((is_signed_number >::value || !is_signed_number >::value) + && (!is_void::value || (is_void::value && (MinBits >= MinBits2))) + && !is_trivial_cpp_int >::value + && !is_trivial_cpp_int >::value) + >::type* = 0) + : base_type() + { + this->resize(other.size(), other_size()); + std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs()); + this->sign(other.sign()); + } + + template + explicit cpp_int_backend(const cpp_int_backend& other, + typename enable_if_c< + (!((is_signed_number >::value || !is_signed_number >::value) + && (!is_void::value || (is_void::value && (MinBits >= MinBits2)))) + && !is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value) + >::type* = 0) + : base_type() + { + double_limb_type v = *other.limbs(); + if(other.size() > 1) + v |= static_cast(other.limbs()[1]) << bits_per_limb; + *this = v; + this->sign(other.sign()); + } + + template + explicit cpp_int_backend(const cpp_int_backend& other, + typename enable_if_c< + (!((is_signed_number >::value || !is_signed_number >::value)) + && (!is_void::value || (is_void::value && (MinBits >= MinBits2))) + && !is_trivial_cpp_int >::value + && !is_trivial_cpp_int >::value) + >::type* = 0) + : base_type() + { + this->resize(other.size(), other.size()); + std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs()); + this->sign(other.sign()); + } + + template + explicit cpp_int_backend(const cpp_int_backend& other, + typename enable_if_c< + (!((is_signed_number >::value || !is_signed_number >::value)) + && (!is_void::value || (is_void::value && (MinBits >= MinBits2))) + && !is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value) + >::type* = 0) + : base_type() + { + double_limb_type v = *other.limbs(); + if(other.size() > 1) + v |= static_cast(other.limbs()[1]) << bits_per_limb; + *this = v; + this->sign(other.sign()); + } + + template + typename enable_if_c<(!is_trivial_cpp_int >::value + && !is_trivial_cpp_int >::value), cpp_int_backend&>::type + operator=(const cpp_int_backend& other) + { + this->resize(other.size(), other.size()); + std::copy(other.limbs(), other.limbs() + (std::min)(other.size(), this->size()), this->limbs()); + this->sign(other.sign()); + return *this; + } + + template + typename enable_if_c<(!is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value), cpp_int_backend&>::type + operator=(const cpp_int_backend& other) + { + double_limb_type v = *other.limbs(); + if(other.size() > 1) + v |= static_cast(other.limbs()[1]) << bits_per_limb; + *this = v; + this->sign(other.sign()); + } +#endif + BOOST_FORCEINLINE cpp_int_backend& operator = (const cpp_int_backend& o) BOOST_NOEXCEPT_IF(boost::is_void::value) + { + this->assign(o); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + BOOST_FORCEINLINE cpp_int_backend& operator = (cpp_int_backend&& o) BOOST_NOEXCEPT_IF(boost::is_void::value) + { + *static_cast(this) = static_cast(o); + return *this; + } +#endif +private: + template + typename enable_if >::type do_assign_arithmetic(A val, const mpl::true_&) + { + this->check_in_range(val); + *this->limbs() = static_cast(val); + this->normalize(); + } + template + typename disable_if >::type do_assign_arithmetic(A val, const mpl::true_&) + { + this->check_in_range(val); + *this->limbs() = (val < 0) ? static_cast(-val) : static_cast(val); + this->sign(val < 0); + this->normalize(); + } + BOOST_FORCEINLINE void do_assign_arithmetic(limb_type i, const mpl::false_&) BOOST_NOEXCEPT + { + this->resize(1, 1); + *this->limbs() = i; + this->sign(false); + } + BOOST_FORCEINLINE void do_assign_arithmetic(signed_limb_type i, const mpl::false_&) BOOST_NOEXCEPT_IF((Checked == unchecked)) + { + this->resize(1, 1); + *this->limbs() = static_cast(std::abs(i)); + this->sign(i < 0); + } + void do_assign_arithmetic(double_limb_type i, const mpl::false_&) + { + BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); + BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); + typename base_type::limb_pointer p = this->limbs(); + *p = static_cast(i); + p[1] = static_cast(i >> base_type::limb_bits); + this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); + this->sign(false); + } + void do_assign_arithmetic(signed_double_limb_type i, const mpl::false_&) + { + BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); + BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); + bool s = false; + if(i < 0) + { + s = true; + i = -i; + } + else + this->sign(false); + typename base_type::limb_pointer p = this->limbs(); + *p = static_cast(i); + p[1] = static_cast(i >> base_type::limb_bits); + this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); + this->sign(s); + } + + void do_assign_arithmetic(long double a, const mpl::false_&) + { + using default_ops::eval_add; + using default_ops::eval_subtract; + using std::frexp; + using std::ldexp; + using std::floor; + + if (a == 0) { + *this = static_cast(0u); + } + + if (a == 1) { + *this = static_cast(1u); + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + *this = static_cast(0u); + + f = frexp(a, &e); + + static const limb_type shift = std::numeric_limits::digits; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + eval_left_shift(*this, shift); + if(term > 0) + eval_add(*this, static_cast(term)); + else + eval_subtract(*this, static_cast(-term)); + f -= term; + } + if(e > 0) + eval_left_shift(*this, e); + else if(e < 0) + eval_right_shift(*this, -e); + } +public: + template + BOOST_FORCEINLINE cpp_int_backend& operator = (Arithmetic val) + { + do_assign_arithmetic(val, trivial_tag()); + return *this; + } +private: + void do_assign_string(const char* s, const mpl::true_&) + { + std::size_t n = s ? std::strlen(s) : 0; + *this->limbs() = 0; + unsigned radix = 10; + bool isneg = false; + if(n && (*s == '-')) + { + --n; + ++s; + isneg = true; + } + if(n && (*s == '0')) + { + if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) + { + radix = 16; + s +=2; + n -= 2; + } + else + { + radix = 8; + n -= 1; + } + } + if(n) + { + unsigned val; + while(*s) + { + if(*s >= '0' && *s <= '9') + val = *s - '0'; + else if(*s >= 'a' && *s <= 'f') + val = 10 + *s - 'a'; + else if(*s >= 'A' && *s <= 'F') + val = 10 + *s - 'A'; + else + val = radix + 1; + if(val >= radix) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); + } + *this->limbs() = detail::checked_multiply(*this->limbs(), static_cast(radix), checked_type()); + *this->limbs() = detail::checked_add(*this->limbs(), static_cast(val), checked_type()); + ++s; + } + } + if(isneg) + this->negate(); + } + void do_assign_string(const char* s, const mpl::false_&) + { + using default_ops::eval_multiply; + using default_ops::eval_add; + std::size_t n = s ? std::strlen(s) : 0; + *this = static_cast(0u); + unsigned radix = 10; + bool isneg = false; + if(n && (*s == '-')) + { + --n; + ++s; + isneg = true; + } + if(n && (*s == '0')) + { + if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) + { + radix = 16; + s +=2; + n -= 2; + } + else + { + radix = 8; + n -= 1; + } + } + if(n) + { + if(radix == 8 || radix == 16) + { + unsigned shift = radix == 8 ? 3 : 4; + unsigned block_count = base_type::limb_bits / shift; + unsigned block_shift = shift * block_count; + limb_type val, block; + while(*s) + { + block = 0; + for(unsigned i = 0; (i < block_count); ++i) + { + if(*s >= '0' && *s <= '9') + val = *s - '0'; + else if(*s >= 'a' && *s <= 'f') + val = 10 + *s - 'a'; + else if(*s >= 'A' && *s <= 'F') + val = 10 + *s - 'A'; + else + val = base_type::max_limb_value; + if(val >= radix) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); + } + block <<= shift; + block |= val; + if(!*++s) + { + // final shift is different: + block_shift = (i + 1) * shift; + break; + } + } + eval_left_shift(*this, block_shift); + this->limbs()[0] |= block; + } + } + else + { + // Base 10, we extract blocks of size 10^9 at a time, that way + // the number of multiplications is kept to a minimum: + limb_type block_mult = max_block_10; + while(*s) + { + limb_type block = 0; + for(unsigned i = 0; i < digits_per_block_10; ++i) + { + limb_type val; + if(*s >= '0' && *s <= '9') + val = *s - '0'; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input.")); + block *= 10; + block += val; + if(!*++s) + { + block_mult = block_multiplier(i); + break; + } + } + eval_multiply(*this, block_mult); + eval_add(*this, block); + } + } + } + if(isneg) + this->negate(); + } +public: + cpp_int_backend& operator = (const char* s) + { + do_assign_string(s, trivial_tag()); + return *this; + } + BOOST_FORCEINLINE void swap(cpp_int_backend& o) BOOST_NOEXCEPT + { + this->do_swap(o); + } +private: + std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::false_&)const + { + if(this->sign() && (((f & std::ios_base::hex) == std::ios_base::hex) || ((f & std::ios_base::oct) == std::ios_base::oct))) + BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + std::stringstream ss; + ss.flags(f & ~std::ios_base::showpos); + ss << *this->limbs(); + std::string result; + if(this->sign()) + result += '-'; + else if(f & std::ios_base::showpos) + result += '+'; + result += ss.str(); + return result; + } + std::string do_get_trivial_string(std::ios_base::fmtflags f, const mpl::true_&)const + { + // Even though we have only one limb, we can't do IO on it :-( + int base = 10; + if((f & std::ios_base::oct) == std::ios_base::oct) + base = 8; + else if((f & std::ios_base::hex) == std::ios_base::hex) + base = 16; + std::string result; + + unsigned Bits = sizeof(typename base_type::local_limb_type) * CHAR_BIT; + + if(base == 8 || base == 16) + { + if(this->sign()) + BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + limb_type shift = base == 8 ? 3 : 4; + limb_type mask = static_cast((1u << shift) - 1); + typename base_type::local_limb_type v = *this->limbs(); + result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0'); + int pos = result.size() - 1; + for(unsigned i = 0; i < Bits / shift; ++i) + { + char c = '0' + static_cast(v & mask); + if(c > '9') + c += 'A' - '9' - 1; + result[pos--] = c; + v >>= shift; + } + if(Bits % shift) + { + mask = static_cast((1u << (Bits % shift)) - 1); + char c = '0' + static_cast(v & mask); + if(c > '9') + c += 'A' - '9'; + result[pos] = c; + } + // + // Get rid of leading zeros: + // + std::string::size_type n = result.find_first_not_of('0'); + if(!result.empty() && (n == std::string::npos)) + n = result.size() - 1; + result.erase(0, n); + if(f & std::ios_base::showbase) + { + const char* pp = base == 8 ? "0" : "0x"; + result.insert(0, pp); + } + } + else + { + result.assign(Bits / 3 + 1, '0'); + int pos = result.size() - 1; + typename base_type::local_limb_type v(*this->limbs()); + bool neg = false; + if(this->sign()) + { + neg = true; + } + while(v) + { + result[pos] = (v % 10) + '0'; + --pos; + v /= 10; + } + unsigned n = result.find_first_not_of('0'); + result.erase(0, n); + if(result.empty()) + result = "0"; + if(neg) + result.insert(0, 1, '-'); + else if(f & std::ios_base::showpos) + result.insert(0, 1, '+'); + } + return result; + } + std::string do_get_string(std::ios_base::fmtflags f, const mpl::true_&)const + { +#ifdef BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO + return do_get_trivial_string(f, mpl::bool_::value>()); +#else + return do_get_trivial_string(f, mpl::bool_()); +#endif + } + std::string do_get_string(std::ios_base::fmtflags f, const mpl::false_&)const + { + using default_ops::eval_get_sign; + int base = 10; + if((f & std::ios_base::oct) == std::ios_base::oct) + base = 8; + else if((f & std::ios_base::hex) == std::ios_base::hex) + base = 16; + std::string result; + + unsigned Bits = this->size() * base_type::limb_bits; + + if(base == 8 || base == 16) + { + if(this->sign()) + BOOST_THROW_EXCEPTION(std::runtime_error("Base 8 or 16 printing of negative numbers is not supported.")); + limb_type shift = base == 8 ? 3 : 4; + limb_type mask = static_cast((1u << shift) - 1); + cpp_int_backend t(*this); + result.assign(Bits / shift + (Bits % shift ? 1 : 0), '0'); + int pos = result.size() - 1; + for(unsigned i = 0; i < Bits / shift; ++i) + { + char c = '0' + static_cast(t.limbs()[0] & mask); + if(c > '9') + c += 'A' - '9' - 1; + result[pos--] = c; + eval_right_shift(t, shift); + } + if(Bits % shift) + { + mask = static_cast((1u << (Bits % shift)) - 1); + char c = '0' + static_cast(t.limbs()[0] & mask); + if(c > '9') + c += 'A' - '9'; + result[pos] = c; + } + // + // Get rid of leading zeros: + // + std::string::size_type n = result.find_first_not_of('0'); + if(!result.empty() && (n == std::string::npos)) + n = result.size() - 1; + result.erase(0, n); + if(f & std::ios_base::showbase) + { + const char* pp = base == 8 ? "0" : "0x"; + result.insert(0, pp); + } + } + else + { + result.assign(Bits / 3 + 1, '0'); + int pos = result.size() - 1; + cpp_int_backend t(*this); + cpp_int_backend r; + bool neg = false; + if(t.sign()) + { + t.negate(); + neg = true; + } + if(this->size() == 1) + { + result = boost::lexical_cast(t.limbs()[0]); + } + else + { + cpp_int_backend block10; + block10 = max_block_10; + while(eval_get_sign(t) != 0) + { + cpp_int_backend t2; + divide_unsigned_helper(&t2, t, block10, r); + t = t2; + limb_type v = r.limbs()[0]; + for(unsigned i = 0; i < digits_per_block_10; ++i) + { + char c = '0' + v % 10; + v /= 10; + result[pos] = c; + if(pos-- == 0) + break; + } + } + } + unsigned n = result.find_first_not_of('0'); + result.erase(0, n); + if(result.empty()) + result = "0"; + if(neg) + result.insert(0, 1, '-'); + else if(f & std::ios_base::showpos) + result.insert(0, 1, '+'); + } + return result; + } +public: + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const + { + return do_get_string(f, trivial_tag()); + } + template + typename enable_if_c< + !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value, + int + >::type compare(const cpp_int_backend& o)const BOOST_NOEXCEPT + { + if(this->sign() != o.sign()) + return this->sign() ? -1 : 1; + + // Only do the compare if the same sign: + int result = compare_unsigned(o); + + if(this->sign()) + result = -result; + return result; + } + template + typename enable_if_c< + is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value, + int + >::type compare(const cpp_int_backend& o)const + { + cpp_int_backend t(*this); + return t.compare(o); + } + template + typename enable_if_c< + !is_trivial_cpp_int >::value && is_trivial_cpp_int >::value, + int + >::type compare(const cpp_int_backend& o)const + { + cpp_int_backend t(o); + return compare(t); + } + template + typename enable_if_c< + is_trivial_cpp_int >::value && is_trivial_cpp_int >::value, + int + >::type compare(const cpp_int_backend& o)const BOOST_NOEXCEPT + { + if(this->sign()) + { + if(o.sign()) + { + return *this->limbs() < *o.limbs() ? 1 : (*this->limbs() > *o.limbs() ? -1 : 0); + } + else + return -1; + } + else + { + if(o.sign()) + return 1; + return *this->limbs() < *o.limbs() ? -1 : (*this->limbs() > *o.limbs() ? 1 : 0); + } + } + template + int compare_unsigned(const cpp_int_backend& o)const BOOST_NOEXCEPT + { + if(this->size() != o.size()) + { + return this->size() > o.size() ? 1 : -1; + } + typename base_type::const_limb_pointer pa = this->limbs(); + typename base_type::const_limb_pointer pb = o.limbs(); + for(int i = this->size() - 1; i >= 0; --i) + { + if(pa[i] != pb[i]) + return pa[i] > pb[i] ? 1 : -1; + } + return 0; + } + template + BOOST_FORCEINLINE typename enable_if, int>::type compare(Arithmetic i)const + { + // braindead version: + cpp_int_backend t; + t = i; + return compare(t); + } +}; + +} // namespace backends + +namespace detail{ + +template +struct double_precision_type; + +template +struct double_precision_type > +{ + typedef typename mpl::if_c< + backends::is_fixed_precision >::value, + backends::cpp_int_backend< + (is_void::value ? + 2 * backends::max_precision >::value + : MinBits), + 2 * backends::max_precision >::value, + SignType, + Checked, + Allocator>, + backends::cpp_int_backend + >::type type; +}; + + +} + +template +struct expression_template_default > +{ + static const expression_template_option value = et_off; +}; + +using boost::multiprecision::backends::cpp_int_backend; + +template +struct number_category > : public mpl::int_{}; + +typedef number > cpp_int; +typedef rational_adapter > cpp_rational_backend; +typedef number cpp_rational; + +// Fixed precision unsigned types: +typedef number > uint128_t; +typedef number > uint256_t; +typedef number > uint512_t; +typedef number > uint1024_t; + +// Fixed precision signed types: +typedef number > int128_t; +typedef number > int256_t; +typedef number > int512_t; +typedef number > int1024_t; + +// Over again, but with checking enabled this time: +typedef number > checked_cpp_int; +typedef rational_adapter > checked_cpp_rational_backend; +typedef number checked_cpp_rational; +// Fixed precision unsigned types: +typedef number > checked_uint128_t; +typedef number > checked_uint256_t; +typedef number > checked_uint512_t; +typedef number > checked_uint1024_t; + +// Fixed precision signed types: +typedef number > checked_int128_t; +typedef number > checked_int256_t; +typedef number > checked_int512_t; +typedef number > checked_int1024_t; + +#ifdef BOOST_NO_SFINAE_EXPR + +namespace detail{ + +template +struct is_explicitly_convertible, cpp_int_backend > : public mpl::true_ {}; + +} +#endif + +}} // namespaces + +// +// Last of all we include the implementations of all the eval_* non member functions: +// +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/include/boost/multiprecision/cpp_int/add.hpp b/include/boost/multiprecision/cpp_int/add.hpp new file mode 100644 index 00000000..068afc7d --- /dev/null +++ b/include/boost/multiprecision/cpp_int/add.hpp @@ -0,0 +1,509 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_ADD_HPP +#define BOOST_MP_CPP_INT_ADD_HPP + +namespace boost{ namespace multiprecision{ namespace backends{ + +// +// This is the key addition routine where all the argument types are non-trivial cpp_int's: +// +template +inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +{ + using std::swap; + + // Nothing fancy, just let uintmax_t take the strain: + double_limb_type carry = 0; + unsigned m, x; + unsigned as = a.size(); + unsigned bs = b.size(); + minmax(as, bs, m, x); + if(x == 1) + { + bool s = a.sign(); + result = static_cast(*a.limbs()) + static_cast(*b.limbs()); + result.sign(s); + return; + } + result.resize(x, x); + typename CppInt2::const_limb_pointer pa = a.limbs(); + typename CppInt3::const_limb_pointer pb = b.limbs(); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt1::limb_pointer pr_end = pr + m; + + if(as < bs) + swap(pa, pb); + + // First where a and b overlap: + while(pr != pr_end) + { + carry += static_cast(*pa) + static_cast(*pb); + *pr = static_cast(carry); + carry >>= CppInt1::limb_bits; + ++pr, ++pa, ++pb; + } + pr_end += x - m; + // Now where only a has digits: + while(pr != pr_end) + { + if(!carry) + { + if(pa != pr) + std::copy(pa, pa + (pr_end - pr), pr); + break; + } + carry += static_cast(*pa); + *pr = static_cast(carry); + carry >>= CppInt1::limb_bits; + ++pr, ++pa; + } + if(carry) + { + // We overflowed, need to add one more limb: + result.resize(x + 1, x + 1); + if(CppInt1::variable || (result.size() > x)) + result.limbs()[x] = static_cast(carry); + } + result.normalize(); + result.sign(a.sign()); +} +// +// As above, but for adding a single limb to a non-trivial cpp_int: +// +template +inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +{ + // Addition using modular arithmatic. + // Nothing fancy, just let uintmax_t take the strain: + if(&result != &a) + result.resize(a.size(), a.size()); + double_limb_type carry = o; + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer pa = a.limbs(); + unsigned i = 0; + // Addition with carry until we either run out of digits or carry is zero: + for(; carry && (i < result.size()); ++i) + { + carry += static_cast(pa[i]); + pr[i] = static_cast(carry); + carry >>= CppInt1::limb_bits; + } + // Just copy any remaining digits: + if(&a != &result) + { + for(; i < result.size(); ++i) + pr[i] = pa[i]; + } + if(carry) + { + // We overflowed, need to add one more limb: + unsigned x = result.size(); + result.resize(x + 1, x + 1); + if(CppInt1::variable || (result.size() > x)) + result.limbs()[x] = static_cast(carry); + } + result.normalize(); + result.sign(a.sign()); +} +// +// Core subtraction routine for all non-trivial cpp_int's: +// +template +inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +{ + using std::swap; + + // Nothing fancy, just let uintmax_t take the strain: + double_limb_type borrow = 0; + unsigned m, x; + minmax(a.size(), b.size(), m, x); + // + // special cases for small limb counts: + // + if(x == 1) + { + bool s = a.sign(); + limb_type al = *a.limbs(); + limb_type bl = *b.limbs(); + if(bl > al) + { + std::swap(al, bl); + s = !s; + } + result = al - bl; + result.sign(s); + return; + } + // This isn't used till later, but comparison has to occur before we resize the result, + // as that may also resize a or b if this is an inplace operation: + int c = a.compare_unsigned(b); + // Set up the result vector: + result.resize(x, x); + // Now that a, b, and result are stable, get pointers to their limbs: + typename CppInt2::const_limb_pointer pa = a.limbs(); + typename CppInt3::const_limb_pointer pb = b.limbs(); + typename CppInt1::limb_pointer pr = result.limbs(); + bool swapped = false; + if(c < 0) + { + swap(pa, pb); + swapped = true; + } + else if(c == 0) + { + result = static_cast(0); + return; + } + + unsigned i = 0; + // First where a and b overlap: + while(i < m) + { + borrow = static_cast(pa[i]) - static_cast(pb[i]) - borrow; + pr[i] = static_cast(borrow); + borrow = (borrow >> CppInt1::limb_bits) & 1u; + ++i; + } + // Now where only a has digits, only as long as we've borrowed: + while(borrow && (i < x)) + { + borrow = static_cast(pa[i]) - borrow; + pr[i] = static_cast(borrow); + borrow = (borrow >> CppInt1::limb_bits) & 1u; + ++i; + } + // Any remaining digits are the same as those in pa: + if((x != i) && (pa != pr)) + std::copy(pa + i, pa + x, pr + i); + BOOST_ASSERT(0 == borrow); + + // + // We may have lost digits, if so update limb usage count: + // + result.normalize(); + result.sign(a.sign()); + if(swapped) + result.negate(); +} +// +// And again to subtract a single limb: +// +template +inline void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_NOEXCEPT_IF(is_non_throwing_cpp_int::value) +{ + // Subtract one limb. + // Nothing fancy, just let uintmax_t take the strain: + BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast(CppInt1::max_limb_value) + 1); + result.resize(a.size(), a.size()); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer pa = a.limbs(); + if(*pa > b) + { + *pr = *pa - b; + if(&result != &a) + { + std::copy(pa + 1, pa + a.size(), pr + 1); + result.sign(a.sign()); + } + } + else if(result.size() == 1) + { + *pr = b - *pa; + result.sign(!a.sign()); + } + else + { + *pr = static_cast((borrow + *pa) - b); + unsigned i = 1; + while(!pa[i]) + { + pr[i] = CppInt1::max_limb_value; + ++i; + } + pr[i] = pa[i] - 1; + if(&result != &a) + { + ++i; + std::copy(pa + i, pa + a.size(), pr + i); + } + result.normalize(); + result.sign(a.sign()); + } +} + +// +// Now the actual functions called by the front end, all of which forward to one of the above: +// +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_add( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_add(result, result, o); +} +template +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_add( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(a.sign() != b.sign()) + { + subtract_unsigned(result, a, b); + return; + } + add_unsigned(result, a, b); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_add(cpp_int_backend& result, const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(result.sign()) + { + subtract_unsigned(result, result, o); + } + else + add_unsigned(result, result, o); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_add( + cpp_int_backend& result, + const cpp_int_backend& a, + const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(a.sign()) + { + subtract_unsigned(result, a, o); + } + else + add_unsigned(result, a, o); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_add( + cpp_int_backend& result, + const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(o < 0) + eval_subtract(result, static_cast(-o)); + else if(o > 0) + eval_add(result, static_cast(o)); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_add( + cpp_int_backend& result, + const cpp_int_backend& a, + const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(o < 0) + eval_subtract(result, a, static_cast(-o)); + else if(o > 0) + eval_add(result, a, static_cast(o)); + else if(&result != &a) + result = a; +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_subtract( + cpp_int_backend& result, + const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(result.sign()) + { + add_unsigned(result, result, o); + } + else + subtract_unsigned(result, result, o); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& a, + const limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(a.sign()) + { + add_unsigned(result, a, o); + } + else + { + subtract_unsigned(result, a, o); + } +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_subtract( + cpp_int_backend& result, + const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(o) + { + if(o < 0) + eval_add(result, static_cast(-o)); + else + eval_subtract(result, static_cast(o)); + } +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& a, + const signed_limb_type& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(o) + { + if(o < 0) + eval_add(result, a, static_cast(-o)); + else + eval_subtract(result, a, static_cast(o)); + } + else if(&result != &a) + result = a; +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_increment(cpp_int_backend& result) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + static const limb_type one = 1; + if(!result.sign() && (result.limbs()[0] < cpp_int_backend::max_limb_value)) + ++result.limbs()[0]; + else if(result.sign() && result.limbs()[0]) + --result.limbs()[0]; + else + eval_add(result, one); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_decrement(cpp_int_backend& result) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + static const limb_type one = 1; + if(!result.sign() && result.limbs()[0]) + --result.limbs()[0]; + else if(result.sign() && (result.limbs()[0] < cpp_int_backend::max_limb_value)) + ++result.limbs()[0]; + else + eval_subtract(result, one); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_subtract(result, result, o); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(a.sign() != b.sign()) + { + add_unsigned(result, a, b); + return; + } + subtract_unsigned(result, a, b); +} + +// +// Simple addition and subtraction routine for trivial cpp_int's come last: +// +// One of the arguments is signed: +// +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_add( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(result.sign() != o.sign()) + { + if(*o.limbs() > *result.limbs()) + { + *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend::checked_type()); + result.negate(); + } + else + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + } + else + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} +// Simple version for two unsigned arguments: +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_add(cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} + +// signed subtraction: +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(result.sign() != o.sign()) + { + *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + } + else if(*result.limbs() < *o.limbs()) + { + *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend::checked_type()); + result.negate(); + } + else + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_subtract( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/cpp_int/bitwise.hpp b/include/boost/multiprecision/cpp_int/bitwise.hpp new file mode 100644 index 00000000..7909cba3 --- /dev/null +++ b/include/boost/multiprecision/cpp_int/bitwise.hpp @@ -0,0 +1,567 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_BIT_HPP +#define BOOST_MP_CPP_INT_BIT_HPP + +namespace boost{ namespace multiprecision{ namespace backends{ + +template +void is_valid_bitwise_op( + cpp_int_backend& result, + const cpp_int_backend& o, const mpl::int_&) +{ + if(result.sign() || o.sign()) + BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior.")); +} + +template +void is_valid_bitwise_op( + cpp_int_backend&, + const cpp_int_backend& , const mpl::int_&){} + +template +void bitwise_op( + CppInt1& result, + const CppInt2& o, + Op op) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int::value)) +{ + // + // There are 4 cases: + // * Both positive. + // * result negative, o positive. + // * o negative, result positive. + // * Both negative. + // + // When one arg is negative we convert to 2's complement form "on the fly", + // and then convert back to signed-magnitude form at the end. + // + // Note however, that if the type is checked, then bitwise ops on negative values + // are not permitted and an exception will result. + // + is_valid_bitwise_op(result, o, typename CppInt1::checked_type()); + // + // First figure out how big the result needs to be and set up some data: + // + unsigned rs = result.size(); + unsigned os = o.size(); + unsigned m, x; + minmax(rs, os, m, x); + result.resize(x, x); + typename CppInt1::limb_pointer pr = result.limbs(); + typename CppInt2::const_limb_pointer po = o.limbs(); + for(unsigned i = rs; i < x; ++i) + pr[i] = 0; + + limb_type next_limb = 0; + + if(!result.sign()) + { + if(!o.sign()) + { + for(unsigned i = 0; i < os; ++i) + pr[i] = op(pr[i], po[i]); + for(unsigned i = os; i < x; ++i) + pr[i] = op(pr[i], limb_type(0)); + } + else + { + // "o" is negative: + double_limb_type carry = 1; + for(unsigned i = 0; i < os; ++i) + { + carry += static_cast(~po[i]); + pr[i] = op(pr[i], static_cast(carry)); + carry >>= CppInt1::limb_bits; + } + for(unsigned i = os; i < x; ++i) + { + carry += static_cast(~limb_type(0)); + pr[i] = op(pr[i], static_cast(carry)); + carry >>= CppInt1::limb_bits; + } + // Set the overflow into the "extra" limb: + carry += static_cast(~limb_type(0)); + next_limb = op(limb_type(0), static_cast(carry)); + } + } + else + { + if(!o.sign()) + { + // "result" is negative: + double_limb_type carry = 1; + for(unsigned i = 0; i < os; ++i) + { + carry += static_cast(~pr[i]); + pr[i] = op(static_cast(carry), po[i]); + carry >>= CppInt1::limb_bits; + } + for(unsigned i = os; i < x; ++i) + { + carry += static_cast(~pr[i]); + pr[i] = op(static_cast(carry), limb_type(0)); + carry >>= CppInt1::limb_bits; + } + // Set the overflow into the "extra" limb: + carry += static_cast(~limb_type(0)); + next_limb = op(static_cast(carry), limb_type(0)); + } + else + { + // both are negative: + double_limb_type r_carry = 1; + double_limb_type o_carry = 1; + for(unsigned i = 0; i < os; ++i) + { + r_carry += static_cast(~pr[i]); + o_carry += static_cast(~po[i]); + pr[i] = op(static_cast(r_carry), static_cast(o_carry)); + r_carry >>= CppInt1::limb_bits; + o_carry >>= CppInt1::limb_bits; + } + for(unsigned i = os; i < x; ++i) + { + r_carry += static_cast(~pr[i]); + o_carry += static_cast(~limb_type(0)); + pr[i] = op(static_cast(r_carry), static_cast(o_carry)); + r_carry >>= CppInt1::limb_bits; + o_carry >>= CppInt1::limb_bits; + } + // Set the overflow into the "extra" limb: + r_carry += static_cast(~limb_type(0)); + o_carry += static_cast(~limb_type(0)); + next_limb = op(static_cast(r_carry), static_cast(o_carry)); + } + } + // + // See if the result is negative or not: + // + if(static_cast(next_limb) < 0) + { + result.sign(true); + double_limb_type carry = 1; + for(unsigned i = 0; i < x; ++i) + { + carry += static_cast(~pr[i]); + pr[i] = static_cast(carry); + carry >>= CppInt1::limb_bits; + } + } + else + result.sign(false); + + result.normalize(); +} + +struct bit_and{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } }; +struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } }; +struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } }; + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_bitwise_and( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + bitwise_op(result, o, bit_and()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_bitwise_or( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + bitwise_op(result, o, bit_or()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_bitwise_xor( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + bitwise_op(result, o, bit_xor()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_complement( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); + // Increment and negate: + result = o; + eval_increment(result); + result.negate(); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_complement( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + unsigned os = o.size(); + result.resize(UINT_MAX, os); + for(unsigned i = 0; i < os; ++i) + result.limbs()[i] = ~o.limbs()[i]; + for(unsigned i = os; i < result.size(); ++i) + result.limbs()[i] = ~static_cast(0); + result.normalize(); +} + +template +inline typename enable_if_c >::value>::type + eval_left_shift( + cpp_int_backend& result, + double_limb_type s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(!s) + return; + + limb_type offset = static_cast(s / cpp_int_backend::limb_bits); + limb_type shift = static_cast(s % cpp_int_backend::limb_bits); + + /* + static const unsigned max_bits = max_bits >::value; + static const unsigned max_limbs = max_bits / cpp_int_backend::limb_bits + + (max_bits % cpp_int_backend::limb_bits ? 1 : 0); + */ + + unsigned ors = result.size(); + if((ors == 1) && (!*result.limbs())) + return; // shifting zero yields zero. + unsigned rs = ors; + if(shift && (result.limbs()[ors - 1] >> (cpp_int_backend::limb_bits - shift))) + ++rs; // Most significant limb will overflow when shifted + rs += offset; + result.resize(rs, rs); + bool truncated = result.size() != rs; + if(truncated) + rs = result.size(); + typename cpp_int_backend::limb_pointer pr = result.limbs(); + + if(offset > rs) + { + // The result is shifted past the end of the result: + result = static_cast(0); + return; + } + + unsigned i = 0; + if(shift) + { + // This code only works when shift is non-zero, otherwise we invoke undefined behaviour! + i = 0; + if(!truncated) + { + if(rs > ors + offset) + { + pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend::limb_bits - shift); + --rs; + } + else + { + pr[rs - 1 - i] = pr[ors - 1 - i] << shift; + if(ors > 1) + pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend::limb_bits - shift); + ++i; + } + } + for(; ors > 1 + i; ++i) + { + pr[rs - 1 - i] = pr[ors - 1 - i] << shift; + pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend::limb_bits - shift); + } + if(ors >= 1 + i) + { + pr[rs - 1 - i] = pr[ors - 1 - i] << shift; + ++i; + } + for(; i < rs; ++i) + pr[rs - 1 - i] = 0; + } + else + { + for(; i < ors; ++i) + pr[rs - 1 - i] = pr[ors - 1 - i]; + for(; i < rs; ++i) + pr[rs - 1 - i] = 0; + } + // + // We may have shifted off the end and have leading zeros: + // + if(truncated) + { + result.normalize(); + } +} + +template +inline typename enable_if_c >::value>::type + eval_right_shift( + cpp_int_backend& result, + double_limb_type s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(!s) + return; + + limb_type offset = static_cast(s / cpp_int_backend::limb_bits); + limb_type shift = static_cast(s % cpp_int_backend::limb_bits); + unsigned ors = result.size(); + unsigned rs = ors; + if(offset >= rs) + { + result = limb_type(0); + return; + } + rs -= offset; + typename cpp_int_backend::limb_pointer pr = result.limbs(); + if((pr[ors - 1] >> shift) == 0) + --rs; + if(rs == 0) + { + result = limb_type(0); + return; + } + unsigned i = 0; + if(shift) + { + // This code only works for non-zero shift, otherwise we invoke undefined behaviour! + for(; i + offset + 1 < ors; ++i) + { + pr[i] = pr[i + offset] >> shift; + pr[i] |= pr[i + offset + 1] << (cpp_int_backend::limb_bits - shift); + } + pr[i] = pr[i + offset] >> shift; + } + else + { + for(; i < rs; ++i) + pr[i] = pr[i + offset]; + } + result.resize(rs, rs); +} + +// +// Over agin for trivial cpp_int's: +// +template +BOOST_FORCEINLINE typename enable_if > >::type + eval_left_shift(cpp_int_backend& result, T s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend::checked_type()); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if > >::type + eval_right_shift(cpp_int_backend& result, T s) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + // Nothing to check here... just make sure we don't invoke undefined behavior: + *result.limbs() = (static_cast(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : *result.limbs() >>= s; +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_bitwise_and( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if(result.sign() || o.sign()) + { + static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; + cpp_int_backend t1(result); + cpp_int_backend t2(o); + eval_bitwise_and(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if(s) + { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } + else + { + *result.limbs() &= *o.limbs(); + } +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_bitwise_and( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() &= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_bitwise_or( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if(result.sign() || o.sign()) + { + static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; + cpp_int_backend t1(result); + cpp_int_backend t2(o); + eval_bitwise_or(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if(s) + { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } + else + { + *result.limbs() |= *o.limbs(); + result.normalize(); + } +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_bitwise_or( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() |= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_bitwise_xor( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + is_valid_bitwise_op(result, o, typename cpp_int_backend::checked_type()); + + using default_ops::eval_bit_test; + using default_ops::eval_increment; + + if(result.sign() || o.sign()) + { + static const unsigned m = static_unsigned_max::value, static_unsigned_max::value>::value; + cpp_int_backend t1(result); + cpp_int_backend t2(o); + eval_bitwise_xor(t1, t2); + bool s = eval_bit_test(t1, m + 1); + if(s) + { + eval_complement(t1, t1); + eval_increment(t1); + } + result = t1; + result.sign(s); + } + else + { + *result.limbs() ^= *o.limbs(); + } +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_bitwise_xor( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() ^= *o.limbs(); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value || is_signed_number >::value) + >::type + eval_complement( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); + // + // If we're not checked then emulate 2's complement behavior: + // + if(o.sign()) + { + *result.limbs() = *o.limbs() - 1; + result.sign(false); + } + else + { + *result.limbs() = 1 + *o.limbs(); + result.sign(true); + } + result.normalize(); +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_complement( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = ~*o.limbs(); + result.normalize(); +} + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/cpp_int/checked.hpp b/include/boost/multiprecision/cpp_int/checked.hpp new file mode 100644 index 00000000..5217ffe8 --- /dev/null +++ b/include/boost/multiprecision/cpp_int/checked.hpp @@ -0,0 +1,149 @@ + +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_CPP_INT_CHECKED_HPP +#define BOOST_MP_CPP_INT_CHECKED_HPP + +namespace boost{ namespace multiprecision{ namespace backends{ namespace detail{ + +// +// Simple routines for performing checked arithmetic with a builtin arithmetic type. +// Note that is is not a complete header, it must be included as part of boost/multiprecision/cpp_int.hpp. +// + +inline void raise_overflow(std::string op) +{ + BOOST_THROW_EXCEPTION(std::overflow_error("overflow in " + op)); +} +inline void raise_add_overflow() +{ + raise_overflow("addition"); +} +inline void raise_subtract_overflow() +{ + BOOST_THROW_EXCEPTION(std::range_error("Subtraction resulted in a negative value, but the type is unsigned")); +} +inline void raise_mul_overflow() +{ + raise_overflow("multiplication"); +} +inline void raise_div_overflow() +{ + raise_overflow("division"); +} + +template +inline A checked_add_imp(A a, A b, const mpl::true_&) +{ + if(a > 0) + { + if((b > 0) && ((integer_traits::const_max - b) < a)) + raise_add_overflow(); + } + else + { + if((b < 0) && ((integer_traits::const_min - b) > a)) + raise_add_overflow(); + } + return a + b; +} +template +inline A checked_add_imp(A a, A b, const mpl::false_&) +{ + if((integer_traits::const_max - b) < a) + raise_add_overflow(); + return a + b; +} +template +inline A checked_add(A a, A b, const mpl::int_&) +{ + return checked_add_imp(a, b, boost::is_signed()); +} +template +inline A checked_add(A a, A b, const mpl::int_&) +{ + return a + b; +} + +template +inline A checked_subtract_imp(A a, A b, const mpl::true_&) +{ + if(a > 0) + { + if((b < 0) && ((integer_traits::const_max + b) < a)) + raise_subtract_overflow(); + } + else + { + if((b > 0) && ((integer_traits::const_min + b) > a)) + raise_subtract_overflow(); + } + return a - b; +} +template +inline A checked_subtract_imp(A a, A b, const mpl::false_&) +{ + if(a < b) + raise_subtract_overflow(); + return a - b; +} +template +inline A checked_subtract(A a, A b, const mpl::int_&) +{ + return checked_subtract_imp(a, b, boost::is_signed()); +} +template +inline A checked_subtract(A a, A b, const mpl::int_&) +{ + return a - b; +} + +template +inline A checked_multiply(A a, A b, const mpl::int_&) +{ + BOOST_MP_USING_ABS + if(a && (integer_traits::const_max / abs(a) < abs(b))) + raise_mul_overflow(); + return a * b; +} +template +inline A checked_multiply(A a, A b, const mpl::int_&) +{ + return a * b; +} + +template +inline A checked_divide(A a, A b, const mpl::int_&) +{ + if(b == 0) + raise_div_overflow(); + return a / b; +} +template +inline A checked_divide(A a, A b, const mpl::int_&) +{ + return a / b; +} + +template +inline A checked_left_shift(A a, unsigned long long shift, const mpl::int_&) +{ + if(a && shift) + { + if((shift > sizeof(A) * CHAR_BIT) || (a >> (sizeof(A) * CHAR_BIT - shift))) + BOOST_THROW_EXCEPTION(std::overflow_error("Shift out of range")); + } + return a << shift; +} +template +inline A checked_left_shift(A a, unsigned long long shift, const mpl::int_&) +{ + return (shift >= sizeof(A) * CHAR_BIT) ? 0 : a << shift; +} + +}}}} // namespaces + +#endif + diff --git a/include/boost/multiprecision/cpp_int/comparison.hpp b/include/boost/multiprecision/cpp_int/comparison.hpp new file mode 100644 index 00000000..8ad701dc --- /dev/null +++ b/include/boost/multiprecision/cpp_int/comparison.hpp @@ -0,0 +1,389 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_COMPARISON_HPP +#define BOOST_MP_CPP_INT_COMPARISON_HPP + +#include + +namespace boost{ namespace multiprecision{ namespace backends{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4018 4389 4996) +#endif + +// +// Start with non-trivial cpp_int's: +// +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type + eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return (a.sign() == b.sign()) + && (a.size() == b.size()) + && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value + && !is_trivial_cpp_int >::value, + bool + >::type + eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return (a.sign() == b.sign()) + && (a.size() == b.size()) + && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + return (a.sign() == false) + && (a.size() == 1) + && (*a.limbs() == b); +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + return (a.sign() == (b < 0)) + && (a.size() == 1) + && (*a.limbs() == static_cast(std::abs(b))); +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + return (a.size() == 1) + && (*a.limbs() == b); +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + return (b < 0) ? eval_eq(a, cpp_int_backend(b)) : eval_eq(a, static_cast(b)); // Use bit pattern of b for comparison +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + if(a.sign()) + return true; + if(a.size() > 1) + return false; + return *a.limbs() < b; +} +template +inline typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + if((b == 0) || (a.sign() != (b < 0))) + return a.sign(); + if(a.sign()) + { + if(a.size() > 1) + return true; + return *a.limbs() > static_cast(std::abs(b)); + } + else + { + if(a.size() > 1) + return false; + return *a.limbs() < static_cast(b); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + if(a.size() > 1) + return false; + return *a.limbs() < b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + return (b < 0) ? a.compare(b) < 0 : eval_lt(a, static_cast(b)); // Use bit pattern of b for comparison +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + if(a.sign()) + return false; + if(a.size() > 1) + return true; + return *a.limbs() > b; +} +template +inline typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + if(b == 0) + return !a.sign() && ((a.size() > 1) || *a.limbs()); + if(a.sign() != (b < 0)) + return !a.sign(); + if(a.sign()) + { + if(a.size() > 1) + return false; + return *a.limbs() < static_cast(std::abs(b)); + } + else + { + if(a.size() > 1) + return true; + return *a.limbs() > static_cast(b); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT +{ + if(a.size() > 1) + return true; + return *a.limbs() > b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT +{ + return (b < 0) ? a.compare(b) > 0 : eval_gt(a, static_cast(b)); // Use bit pattern of b for comparison. +} +// +// And again for trivial cpp_ints: +// +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return *a.limbs() == *b.limbs(); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + return !a.sign() && (*a.limbs() == b); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + return (a.sign() == (b < 0)) && (*a.limbs() == static_cast(std::abs(b))); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + return *a.limbs() == b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + if(b < 0) + { + cpp_int_backend t(b); + return *a.limbs() == *t.limbs(); + } + else + { + return *a.limbs() == static_cast(b); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + if(a.sign() != b.sign()) + return a.sign(); + return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs(); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return *a.limbs() < *b.limbs(); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + if(a.sign()) + return true; + return *a.limbs() < b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + if(a.sign() != (b < 0)) + return a.sign(); + return a.sign() ? (*a.limbs() > static_cast(std::abs(b))) : (*a.limbs() < static_cast(std::abs(b))); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + return *a.limbs() < b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + if(b < 0) + { + cpp_int_backend t(b); + return *a.limbs() < *t.limbs(); + } + else + { + return *a.limbs() < static_cast(b); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + if(a.sign() != b.sign()) + return !a.sign(); + return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs(); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + return *a.limbs() > *b.limbs(); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + if(a.sign()) + return false; + return *a.limbs() > b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + if(a.sign() != (b < 0)) + return !a.sign(); + return a.sign() ? (*a.limbs() < static_cast(std::abs(b))) : (*a.limbs() > static_cast(std::abs(b))); +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_unsigned::value && is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT +{ + return *a.limbs() > b; +} +template +BOOST_FORCEINLINE typename enable_if_c< + is_signed::value && is_trivial_cpp_int >::value, + bool + >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT +{ + typedef typename make_unsigned::type ui_type; + if(b < 0) + { + cpp_int_backend t(b); + return *a.limbs() > *t.limbs(); + } + else + { + return *a.limbs() > static_cast(b); + } +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/cpp_int/cpp_int_config.hpp b/include/boost/multiprecision/cpp_int/cpp_int_config.hpp new file mode 100644 index 00000000..5c05d5ae --- /dev/null +++ b/include/boost/multiprecision/cpp_int/cpp_int_config.hpp @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_CPP_INT_CORE_HPP +#define BOOST_MP_CPP_INT_CORE_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace multiprecision{ + +namespace detail{ + +// +// These traits calculate the largest type in the list +// [unsigned] ong long, long, int, which has the specified number +// of bits. Note that intN_t and boost::int_t find the first +// member of the above list, not the last. We want the last in the +// list to ensure that mixed arithmetic operations are as efficient +// as possible. +// +template +struct largest_signed_type +{ + typedef typename mpl::if_c< + 1 + std::numeric_limits::digits == N, + long long, + typename mpl::if_c< + 1 + std::numeric_limits::digits == N, + long, + typename mpl::if_c< + 1 + std::numeric_limits::digits == N, + int, + typename boost::int_t::exact + >::type + >::type + >::type type; +}; + +template +struct largest_unsigned_type +{ + typedef typename mpl::if_c< + std::numeric_limits::digits == N, + unsigned long long, + typename mpl::if_c< + std::numeric_limits::digits == N, + unsigned long, + typename mpl::if_c< + std::numeric_limits::digits == N, + unsigned int, + typename boost::uint_t::exact + >::type + >::type + >::type type; +}; + +} // namepsace detail + +#if defined(BOOST_HAS_INT128) + +typedef detail::largest_unsigned_type<64>::type limb_type; +typedef detail::largest_signed_type<64>::type signed_limb_type; +typedef boost::uint128_type double_limb_type; +typedef boost::int128_type signed_double_limb_type; +static const limb_type max_block_10 = 1000000000000000000uLL; +static const limb_type digits_per_block_10 = 18; + +inline limb_type block_multiplier(unsigned count) +{ + static const limb_type values[digits_per_block_10] + = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000 }; + BOOST_ASSERT(count < digits_per_block_10); + return values[count]; +} + +// Can't do formatted IO on an __int128 +#define BOOST_MP_NO_DOUBLE_LIMB_TYPE_IO + +// Need to specialise integer_traits for __int128 as it's not a normal native type: +} // namespace multiprecision + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base(0)> +{ }; +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base((static_cast(1) << 127)), static_cast(((~static_cast(0)) >> 1))> +{ }; + +namespace multiprecision{ + +#else + +typedef detail::largest_unsigned_type<32>::type limb_type; +typedef detail::largest_signed_type<32>::type signed_limb_type; +typedef boost::uint64_t double_limb_type; +typedef boost::int64_t signed_double_limb_type; +static const limb_type max_block_10 = 1000000000; +static const limb_type digits_per_block_10 = 9; + +inline limb_type block_multiplier(unsigned count) +{ + static const limb_type values[digits_per_block_10] + = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + BOOST_ASSERT(count < digits_per_block_10); + return values[count]; +} + +#endif + +static const unsigned bits_per_limb = sizeof(limb_type) * CHAR_BIT; + +template +inline void minmax(const T& a, const T& b, T& aa, T& bb) +{ + if(a < b) + { + aa = a; + bb = b; + } + else + { + aa = b; + bb = a; + } +} + +enum cpp_integer_type +{ + signed_magnitude = 1, + unsigned_magnitude = 0, + signed_packed = 3, + unsigned_packed = 2 +}; + +enum cpp_int_check_type +{ + checked = 1, + unchecked = 0 +}; + +}} + +#endif // BOOST_MP_CPP_INT_CORE_HPP + diff --git a/include/boost/multiprecision/cpp_int/divide.hpp b/include/boost/multiprecision/cpp_int/divide.hpp new file mode 100644 index 00000000..c2afc7ec --- /dev/null +++ b/include/boost/multiprecision/cpp_int/divide.hpp @@ -0,0 +1,626 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_DIV_HPP +#define BOOST_MP_CPP_INT_DIV_HPP + +namespace boost{ namespace multiprecision{ namespace backends{ + +template +void divide_unsigned_helper( + CppInt1* result, + const CppInt2& x, + const CppInt3& y, + CppInt1& r) +{ + if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x)) + { + CppInt2 t(x); + divide_unsigned_helper(result, t, y, r); + return; + } + if(((void*)result == (void*)&y) || ((void*)&r == (void*)&y)) + { + CppInt3 t(y); + divide_unsigned_helper(result, x, t, r); + return; + } + + /* + Very simple, fairly braindead long division. + Start by setting the remainder equal to x, and the + result equal to 0. Then in each loop we calculate our + "best guess" for how many times y divides into r, + add our guess to the result, and subtract guess*y + from the remainder r. One wrinkle is that the remainder + may go negative, in which case we subtract the current guess + from the result rather than adding. The value of the guess + is determined by dividing the most-significant-limb of the + current remainder by the most-significant-limb of y. + + Note that there are more efficient algorithms than this + available, in particular see Knuth Vol 2. However for small + numbers of limbs this generally outperforms the alternatives + and avoids the normalisation step which would require extra storage. + */ + + + using default_ops::eval_subtract; + + if(result == &r) + { + CppInt1 rem; + divide_unsigned_helper(result, x, y, rem); + r = rem; + return; + } + + // + // Find the most significant words of numerator and denominator. + // + limb_type y_order = y.size() - 1; + + if(y_order == 0) + { + // + // Only a single non-zero limb in the denominator, in this case + // we can use a specialized divide-by-single-limb routine which is + // much faster. This also handles division by zero: + // + divide_unsigned_helper(result, x, y.limbs()[y_order], r); + return; + } + + typename CppInt2::const_limb_pointer px = x.limbs(); + typename CppInt3::const_limb_pointer py = y.limbs(); + + limb_type r_order = x.size() - 1; + if((r_order == 0) && (*px == 0)) + { + // x is zero, so is the result: + r = y; + if(result) + *result = x; + return; + } + + r = x; + r.sign(false); + if(result) + *result = static_cast(0u); + // + // Check if the remainder is already less than the divisor, if so + // we already have the result. Note we try and avoid a full compare + // if we can: + // + if(r_order <= y_order) + { + if((r_order < y_order) || (r.compare_unsigned(y) < 0)) + { + return; + } + } + + CppInt1 t; + bool r_neg = false; + + // + // See if we can short-circuit long division, and use basic arithmetic instead: + // + if(r_order == 0) + { + if(result) + *result = px[0] / py[0]; + r = px[0] % py[0]; + return; + } + else if(r_order == 1) + { + double_limb_type a, b; + a = (static_cast(px[1]) << CppInt1::limb_bits) | px[0]; + b = y_order ? + (static_cast(py[1]) << CppInt1::limb_bits) | py[0] + : py[0]; + if(result) + *result = a / b; + r = a % b; + return; + } + // + // prepare result: + // + if(result) + result->resize(1 + r_order - y_order, 1 + r_order - y_order); + typename CppInt1::const_limb_pointer prem = r.limbs(); + // This is initialised just to keep the compiler from emitting useless warnings later on: + typename CppInt1::limb_pointer pr + = typename CppInt1::limb_pointer(); + if(result) + { + pr = result->limbs(); + for(unsigned i = 1; i < 1 + r_order - y_order; ++i) + pr[i] = 0; + } + bool first_pass = true; + + do + { + // + // Calculate our best guess for how many times y divides into r: + // + limb_type guess; + if((prem[r_order] <= py[y_order]) && (r_order > 0)) + { + double_limb_type a, b, v; + a = (static_cast(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1]; + b = py[y_order]; + v = a / b; + if(v > CppInt1::max_limb_value) + guess = 1; + else + { + guess = static_cast(v); + --r_order; + } + } + else if(r_order == 0) + { + guess = prem[0] / py[y_order]; + } + else + { + double_limb_type a, b, v; + a = (static_cast(prem[r_order]) << CppInt1::limb_bits) | prem[r_order - 1]; + b = (y_order > 0) ? (static_cast(py[y_order]) << CppInt1::limb_bits) | py[y_order - 1] : (static_cast(py[y_order]) << CppInt1::limb_bits); + v = a / b; + guess = static_cast(v); + } + BOOST_ASSERT(guess); // If the guess ever gets to zero we go on forever.... + // + // Update result: + // + limb_type shift = r_order - y_order; + if(result) + { + if(r_neg) + { + if(pr[shift] > guess) + pr[shift] -= guess; + else + { + t.resize(shift + 1, shift + 1); + t.limbs()[shift] = guess; + for(unsigned i = 0; i < shift; ++i) + t.limbs()[i] = 0; + eval_subtract(*result, t); + } + } + else if(CppInt1::max_limb_value - pr[shift] > guess) + pr[shift] += guess; + else + { + t.resize(shift + 1, shift + 1); + t.limbs()[shift] = guess; + for(unsigned i = 0; i < shift; ++i) + t.limbs()[i] = 0; + eval_add(*result, t); + } + } + // + // Calculate guess * y, we use a fused mutiply-shift O(N) for this + // rather than a full O(N^2) multiply: + // + double_limb_type carry = 0; + t.resize(y.size() + shift + 1, y.size() + shift); + bool truncated_t = !CppInt1::variable && (t.size() != y.size() + shift + 1); + typename CppInt1::limb_pointer pt = t.limbs(); + for(unsigned i = 0; i < shift; ++i) + pt[i] = 0; + for(unsigned i = 0; i < y.size(); ++i) + { + carry += static_cast(py[i]) * static_cast(guess); + pt[i + shift] = static_cast(carry); + carry >>= CppInt1::limb_bits; + } + if(carry && !truncated_t) + { + pt[t.size() - 1] = static_cast(carry); + } + else if(!truncated_t) + { + t.resize(t.size() - 1, t.size() - 1); + } + // + // Update r in a way that won't actually produce a negative result + // in case the argument types are unsigned: + // + if(r.compare(t) > 0) + { + eval_subtract(r, t); + } + else + { + r.swap(t); + eval_subtract(r, t); + prem = r.limbs(); + r_neg = !r_neg; + } + // + // First time through we need to strip any leading zero, otherwise + // the termination condition goes belly-up: + // + if(result && first_pass) + { + first_pass = false; + while(pr[result->size() - 1] == 0) + result->resize(result->size() - 1, result->size() - 1); + } + // + // Update r_order: + // + r_order = r.size() - 1; + if(r_order < y_order) + break; + } + // Termination condition is really just a check that r > y, but with a common + // short-circuit case handled first: + while((r_order > y_order) || (r.compare_unsigned(y) >= 0)); + + // + // We now just have to normalise the result: + // + if(r_neg && eval_get_sign(r)) + { + // We have one too many in the result: + if(result) + eval_decrement(*result); + if(y.sign()) + { + r.negate(); + eval_subtract(r, y); + } + else + eval_subtract(r, y, r); + } + + BOOST_ASSERT(r.compare_unsigned(y) < 0); // remainder must be less than the divisor or our code has failed +} + +template +void divide_unsigned_helper( + CppInt1* result, + const CppInt2& x, + limb_type y, + CppInt1& r) +{ + if(((void*)result == (void*)&x) || ((void*)&r == (void*)&x)) + { + CppInt2 t(x); + divide_unsigned_helper(result, t, y, r); + return; + } + + if(result == &r) + { + CppInt1 rem; + divide_unsigned_helper(result, x, y, rem); + r = rem; + return; + } + + // As above, but simplified for integer divisor: + + using default_ops::eval_subtract; + + if(y == 0) + { + BOOST_THROW_EXCEPTION(std::overflow_error("Integer Division by zero.")); + } + // + // Find the most significant word of numerator. + // + limb_type r_order = x.size() - 1; + + // + // Set remainder and result to their initial values: + // + r = x; + r.sign(false); + typename CppInt1::limb_pointer pr = r.limbs(); + + if((r_order == 0) && (*pr == 0)) + { + // All the limbs in x are zero, so is the result: + return; + } + // + // check for x < y, try to do this without actually having to + // do a full comparison: + // + if((r_order == 0) && (*pr < y)) + { + if(result) + *result = static_cast(0u); + return; + } + + // + // See if we can short-circuit long division, and use basic arithmetic instead: + // + if(r_order == 0) + { + if(result) + { + *result = *pr / y; + result->sign(x.sign()); + } + *pr %= y; + r.sign(x.sign()); + return; + } + else if(r_order == 1) + { + double_limb_type a; + a = (static_cast(pr[r_order]) << CppInt1::limb_bits) | pr[0]; + if(result) + { + *result = a / y; + result->sign(x.sign()); + } + r = a % y; + r.sign(x.sign()); + return; + } + + // This is initialised just to keep the compiler from emitting useless warnings later on: + typename CppInt1::limb_pointer pres = typename CppInt1::limb_pointer(); + if(result) + { + result->resize(r_order + 1, r_order + 1); + pres = result->limbs(); + if(result->size() > r_order) + pres[r_order] = 0; // just in case we don't set the most significant limb below. + } + + do + { + // + // Calculate our best guess for how many times y divides into r: + // + if((pr[r_order] < y) && r_order) + { + double_limb_type a, b; + a = (static_cast(pr[r_order]) << CppInt1::limb_bits) | pr[r_order - 1]; + b = a % y; + r.resize(r.size() - 1, r.size() - 1); + --r_order; + pr[r_order] = static_cast(b); + if(result) + pres[r_order] = static_cast(a / y); + if(r_order && pr[r_order] == 0) + { + --r_order; // No remainder, division was exact. + r.resize(r.size() - 1, r.size() - 1); + if(result) + pres[r_order] = static_cast(0u); + } + } + else + { + if(result) + pres[r_order] = pr[r_order] / y; + pr[r_order] %= y; + if(r_order && pr[r_order] == 0) + { + --r_order; // No remainder, division was exact. + r.resize(r.size() - 1, r.size() - 1); + if(result) + pres[r_order] = static_cast(0u); + } + } + } + // Termination condition is really just a check that r > y, but with two common + // short-circuit cases handled first: + while(r_order || (pr[r_order] > y)); + + if(result) + { + result->normalize(); + result->sign(x.sign()); + } + r.normalize(); + r.sign(x.sign()); + + BOOST_ASSERT(r.compare(y) < 0); // remainder must be less than the divisor or our code has failed +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) +{ + cpp_int_backend r; + divide_unsigned_helper(&result, a, b, r); + result.sign(a.sign() != b.sign()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& a, + limb_type& b) +{ + cpp_int_backend r; + divide_unsigned_helper(&result, a, b, r); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& a, + signed_limb_type& b) +{ + cpp_int_backend r; + divide_unsigned_helper(&result, a, static_cast(std::abs(b)), r); + if(b < 0) + result.negate(); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_divide(result, a, b); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_divide( + cpp_int_backend& result, + limb_type b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_divide(result, a, b); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_divide( + cpp_int_backend& result, + signed_limb_type b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_divide(result, a, b); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_modulus( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) +{ + divide_unsigned_helper(static_cast* >(0), a, b, result); + result.sign(a.sign()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_modulus( + cpp_int_backend& result, + const cpp_int_backend& a, limb_type b) +{ + divide_unsigned_helper(static_cast* >(0), a, b, result); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_modulus( + cpp_int_backend& result, + const cpp_int_backend& a, + signed_limb_type b) +{ + divide_unsigned_helper(static_cast* >(0), a, static_cast(std::abs(b)), result); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_modulus( + cpp_int_backend& result, + const cpp_int_backend& b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_modulus(result, a, b); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_modulus( + cpp_int_backend& result, + limb_type b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_modulus(result, a, b); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_modulus( + cpp_int_backend& result, + signed_limb_type b) +{ + // There is no in place divide: + cpp_int_backend a(result); + eval_modulus(result, a, b); +} + +// +// Over again for trivial cpp_int's: +// +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value + || is_signed_number >::value) + >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& o) +{ + if(!*o.limbs()) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + *result.limbs() /= *o.limbs(); + result.sign(result.sign() != o.sign()); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_unsigned_number >::value + && is_unsigned_number >::value + >::type + eval_divide( + cpp_int_backend& result, + const cpp_int_backend& o) +{ + if(!*o.limbs()) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + *result.limbs() /= *o.limbs(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + >::type + eval_modulus( + cpp_int_backend& result, + const cpp_int_backend& o) +{ + if(!*o.limbs()) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + *result.limbs() %= *o.limbs(); + result.sign(result.sign()); +} + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/cpp_int/limits.hpp b/include/boost/multiprecision/cpp_int/limits.hpp new file mode 100644 index 00000000..7f7d7476 --- /dev/null +++ b/include/boost/multiprecision/cpp_int/limits.hpp @@ -0,0 +1,216 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_LIM_HPP +#define BOOST_MP_CPP_INT_LIM_HPP + +namespace std{ + +namespace detail{ + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_min(const boost::mpl::true_&, const boost::mpl::true_&) +{ + // Bounded and signed. + typedef boost::multiprecision::number, ExpressionTemplates> result_type; + typedef boost::multiprecision::number, ExpressionTemplates> ui_type; + static const result_type val = -result_type(~ui_type(0)); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_min(const boost::mpl::true_&, const boost::mpl::false_&) +{ + // Bounded and unsigned: + static const boost::multiprecision::number, ExpressionTemplates> val(0u); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_min(const boost::mpl::false_&, const boost::mpl::true_&) +{ + // Unbounded and signed. + // There is no minimum value, just return 0: + static const boost::multiprecision::number, ExpressionTemplates> val(0u); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_min(const boost::mpl::false_&, const boost::mpl::false_&) +{ + // Unbound and unsigned: + static const boost::multiprecision::number, ExpressionTemplates> val(0u); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_max(const boost::mpl::true_&, const boost::mpl::true_&) +{ + // Bounded and signed. + typedef boost::multiprecision::number, ExpressionTemplates> result_type; + typedef boost::multiprecision::number, ExpressionTemplates> ui_type; + static const result_type val = ~ui_type(0); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_max(const boost::mpl::true_&, const boost::mpl::false_&) +{ + // Bound and unsigned: + typedef boost::multiprecision::number, ExpressionTemplates> result_type; + typedef boost::multiprecision::number, ExpressionTemplates> ui_type; + static const result_type val = ~ui_type(0); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_max(const boost::mpl::false_&, const boost::mpl::true_&) +{ + // Unbounded and signed. + // There is no maximum value, just return 0: + static const boost::multiprecision::number, ExpressionTemplates> val(0u); + return val; +} + +template +inline boost::multiprecision::number, ExpressionTemplates> + get_max(const boost::mpl::false_&, const boost::mpl::false_&) +{ + // Unbound and unsigned: + static const boost::multiprecision::number, ExpressionTemplates> val(0u); + return val; +} + +} + +template +class numeric_limits, ExpressionTemplates> > +{ + typedef boost::multiprecision::cpp_int_backend backend_type; + typedef boost::multiprecision::number number_type; + + struct inititializer + { + inititializer() + { + (std::numeric_limits::max)(); + (std::numeric_limits::min)(); + } + void do_nothing()const{} + }; + + static const inititializer init; + +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type (min)() BOOST_NOEXCEPT + { + init.do_nothing(); + return detail::get_min(boost::multiprecision::backends::is_fixed_precision(), boost::multiprecision::is_signed_number()); + } + static number_type (max)() BOOST_NOEXCEPT + { + init.do_nothing(); + return detail::get_max(boost::multiprecision::backends::is_fixed_precision(), boost::multiprecision::is_signed_number()); + } + static number_type lowest() BOOST_NOEXCEPT { return (min)(); } + BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::backends::max_precision::value == UINT_MAX ? INT_MAX : boost::multiprecision::backends::max_precision::value; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; + BOOST_STATIC_CONSTEXPR bool is_signed = boost::multiprecision::is_signed_number::value; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() BOOST_NOEXCEPT { return 0; } + static number_type round_error() BOOST_NOEXCEPT { return 0; } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return 0; } + static number_type quiet_NaN() BOOST_NOEXCEPT { return 0; } + static number_type signaling_NaN() BOOST_NOEXCEPT { return 0; } + static number_type denorm_min() BOOST_NOEXCEPT { return 0; } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = boost::multiprecision::backends::is_fixed_precision::value; + BOOST_STATIC_CONSTEXPR bool is_modulo = (boost::multiprecision::backends::is_fixed_precision::value && (Checked == boost::multiprecision::unchecked)); + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +template +const typename numeric_limits, ExpressionTemplates> >::inititializer numeric_limits, ExpressionTemplates> >::init; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; + +#endif + +} // namespace std + +#endif diff --git a/include/boost/multiprecision/cpp_int/misc.hpp b/include/boost/multiprecision/cpp_int/misc.hpp new file mode 100644 index 00000000..217c9f8c --- /dev/null +++ b/include/boost/multiprecision/cpp_int/misc.hpp @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_MISC_HPP +#define BOOST_MP_CPP_INT_MISC_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4702) +#endif + +namespace boost{ namespace multiprecision{ namespace backends{ + +template +void check_in_range(const CppInt& val, const mpl::int_&) +{ + typedef typename boost::multiprecision::detail::canonical::type cast_type; + if(val.sign()) + { + if(val.compare(static_cast((std::numeric_limits::min)())) < 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); + } + else + { + if(val.compare(static_cast((std::numeric_limits::max)())) > 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); + } +} +template +void check_in_range(const CppInt& /*val*/, const mpl::int_&) BOOST_NOEXCEPT {} + +void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {} +void check_is_negative(const mpl::false_&) +{ + BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type.")); +} + +template +inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT +{ + return -i; +} +template +inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT +{ + return ~(i-1); +} + +template +inline typename enable_if_c::value && !is_trivial_cpp_int >::value, void>::type + eval_convert_to(R* result, const cpp_int_backend& backend) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + typedef mpl::int_ checked_type; + check_in_range(backend, checked_type()); + + *result = static_cast(backend.limbs()[0]); + unsigned shift = cpp_int_backend::limb_bits; + for(unsigned i = 1; (i < backend.size()) && (shift < static_cast(std::numeric_limits::digits)); ++i) + { + *result += static_cast(backend.limbs()[i]) << shift; + shift += cpp_int_backend::limb_bits; + } + if(backend.sign()) + { + check_is_negative(boost::is_signed()); + *result = negate_integer(*result, boost::is_signed()); + } +} + +template +inline typename enable_if_c::value && !is_trivial_cpp_int >::value, void>::type + eval_convert_to(R* result, const cpp_int_backend& backend) BOOST_NOEXCEPT +{ + typename cpp_int_backend::const_limb_pointer p = backend.limbs(); + unsigned shift = cpp_int_backend::limb_bits; + *result = static_cast(*p); + for(unsigned i = 1; i < backend.size(); ++i) + { + *result += static_cast(std::ldexp(static_cast(p[i]), shift)); + shift += cpp_int_backend::limb_bits; + } + if(backend.sign()) + *result = -*result; +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value, bool>::type + eval_is_zero(const cpp_int_backend& val) BOOST_NOEXCEPT +{ + return (val.size() == 1) && (val.limbs()[0] == 0); +} +template +BOOST_FORCEINLINE typename enable_if_c >::value, int>::type + eval_get_sign(const cpp_int_backend& val) BOOST_NOEXCEPT +{ + return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1; +} +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_abs(cpp_int_backend& result, const cpp_int_backend& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + result = val; + result.sign(false); +} + +// +// Get the location of the least-significant-bit: +// +template +inline typename enable_if_c >::value, unsigned>::type + eval_lsb(const cpp_int_backend& a) BOOST_NOEXCEPT +{ + using default_ops::eval_get_sign; + if(eval_get_sign(a) == 0) + { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if(a.sign()) + { + BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); + } + + unsigned result = 0; + // + // Find the index of the least significant limb that is non-zero: + // + unsigned index = 0; + while(!a.limbs()[index] && (index < a.size())) + ++index; + // + // Find the index of the least significant bit within that limb: + // + limb_type l = a.limbs()[index]; + while(!(l & 1u)) + { + l >>= 1; + ++result; + } + + return result + index * cpp_int_backend::limb_bits; +} + +template +inline typename enable_if_c >::value, bool>::type + eval_bit_test(const cpp_int_backend& val, unsigned index) BOOST_NOEXCEPT +{ + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if(offset >= val.size()) + return false; + return val.limbs()[offset] & mask ? true : false; +} + +template +inline typename enable_if_c >::value>::type + eval_bit_set(cpp_int_backend& val, unsigned index) +{ + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if(offset >= val.size()) + { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if(offset >= val.size()) + return; // fixed precision overflow + for(unsigned i = os; i <= offset; ++i) + val.limbs()[i] = 0; + } + val.limbs()[offset] |= mask; +} + +template +inline typename enable_if_c >::value>::type + eval_bit_unset(cpp_int_backend& val, unsigned index) BOOST_NOEXCEPT +{ + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if(offset >= val.size()) + return; + val.limbs()[offset] &= ~mask; + val.normalize(); +} + +template +inline typename enable_if_c >::value>::type + eval_bit_flip(cpp_int_backend& val, unsigned index) +{ + unsigned offset = index / cpp_int_backend::limb_bits; + unsigned shift = index % cpp_int_backend::limb_bits; + limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); + if(offset >= val.size()) + { + unsigned os = val.size(); + val.resize(offset + 1, offset + 1); + if(offset >= val.size()) + return; // fixed precision overflow + for(unsigned i = os; i <= offset; ++i) + val.limbs()[i] = 0; + } + val.limbs()[offset] ^= mask; + val.normalize(); +} + +template +inline typename enable_if_c >::value>::type + eval_qr( + const cpp_int_backend& x, + const cpp_int_backend& y, + cpp_int_backend& q, + cpp_int_backend& r) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + divide_unsigned_helper(&q, x, y, r); + q.sign(x.sign() != y.sign()); + r.sign(x.sign()); +} + +template +inline typename enable_if_c::value && !is_trivial_cpp_int >::value, Integer>::type + eval_integer_modulus(const cpp_int_backend& x, Integer val) +{ + if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits::max)())) + { + cpp_int_backend d; + divide_unsigned_helper(static_cast*>(0), x, static_cast(val), d); + return d.limbs()[0]; + } + else + { + return default_ops::eval_integer_modulus(x, val); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c::value && !is_trivial_cpp_int >::value, Integer>::type + eval_integer_modulus(const cpp_int_backend& x, Integer val) +{ + typedef typename make_unsigned::type unsigned_type; + return eval_integer_modulus(x, static_cast(std::abs(val))); +} + +// +// Now again for trivial backends: +// +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_gcd(cpp_int_backend& result, const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT +{ + *result.limbs() = boost::math::gcd(*a.limbs(), *b.limbs()); +} +// This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version: +template +BOOST_FORCEINLINE typename enable_if_c >::value && (Checked1 == unchecked)>::type + eval_lcm(cpp_int_backend& result, const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = boost::math::lcm(*a.limbs(), *b.limbs()); + result.normalize(); // result may overflow the specified number of bits +} + +inline void conversion_overflow(const mpl::int_&) +{ + BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type")); +} +inline void conversion_overflow(const mpl::int_&){} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_signed_number >::value + >::type + eval_convert_to(R* result, const cpp_int_backend& val) +{ + typedef typename common_type::local_limb_type>::type common_type; + if(std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > static_cast((std::numeric_limits::max)()))) + { + conversion_overflow(typename cpp_int_backend::checked_type()); + *result = (std::numeric_limits::max)(); + } + else + *result = static_cast(*val.limbs()); + if(val.isneg()) + { + check_is_negative(mpl::bool_::value || boost::is_floating_point::value>()); + *result = negate_integer(*result, mpl::bool_::value || boost::is_floating_point::value>()); + } +} + +template +inline typename enable_if_c< + is_trivial_cpp_int >::value + && is_unsigned_number >::value + >::type + eval_convert_to(R* result, const cpp_int_backend& val) +{ + typedef typename common_type::local_limb_type>::type common_type; + if(std::numeric_limits::is_specialized && (static_cast(*val.limbs()) > static_cast((std::numeric_limits::max)()))) + { + conversion_overflow(typename cpp_int_backend::checked_type()); + *result = (std::numeric_limits::max)(); + } + else + *result = static_cast(*val.limbs()); +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/cpp_int/multiply.hpp b/include/boost/multiprecision/cpp_int/multiply.hpp new file mode 100644 index 00000000..2559cead --- /dev/null +++ b/include/boost/multiprecision/cpp_int/multiply.hpp @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// Comparison operators for cpp_int_backend: +// +#ifndef BOOST_MP_CPP_INT_MUL_HPP +#define BOOST_MP_CPP_INT_MUL_HPP + +namespace boost{ namespace multiprecision{ namespace backends{ + +template +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(!val) + { + result = static_cast(0); + return; + } + if((void*)&a != (void*)&result) + result.resize(a.size(), a.size()); + double_limb_type carry = 0; + typename cpp_int_backend::limb_pointer p = result.limbs(); + typename cpp_int_backend::limb_pointer pe = result.limbs() + result.size(); + typename cpp_int_backend::const_limb_pointer pa = a.limbs(); + while(p != pe) + { + carry += static_cast(*pa) * static_cast(val); + *p = static_cast(carry); + carry >>= cpp_int_backend::limb_bits; + ++p, ++pa; + } + if(carry) + { + unsigned i = result.size(); + result.resize(i + 1, i + 1); + if(cpp_int_backend::variable || (result.size() > i)) + result.limbs()[i] = static_cast(carry); + } + result.sign(a.sign()); + if(!cpp_int_backend::variable) + result.normalize(); +} + +// +// resize_for_carry forces a resize of the underlying buffer only if a previous request +// for "required" elements could possibly have failed, *and* we have checking enabled. +// This will cause an overflow error inside resize(): +// +template +inline void resize_for_carry(cpp_int_backend& /*result*/, unsigned /*required*/){} + +template +inline void resize_for_carry(cpp_int_backend& result, unsigned required) +{ + if(result.size() != required) + result.resize(required, required); +} + +template +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + // Very simple long multiplication, only usable for small numbers of limb_type's + // but that's the typical use case for this type anyway: + // + // Special cases first: + // + unsigned as = a.size(); + unsigned bs = b.size(); + typename cpp_int_backend::const_limb_pointer pa = a.limbs(); + typename cpp_int_backend::const_limb_pointer pb = b.limbs(); + if(as == 1) + { + bool s = b.sign() != a.sign(); + if(bs == 1) + { + result = static_cast(*pa) * static_cast(*pb); + } + else + { + limb_type l = *pa; + eval_multiply(result, b, l); + } + result.sign(s); + return; + } + if(bs == 1) + { + bool s = b.sign() != a.sign(); + limb_type l = *pb; + eval_multiply(result, a, l); + result.sign(s); + return; + } + + if((void*)&result == (void*)&a) + { + cpp_int_backend t(a); + eval_multiply(result, t, b); + return; + } + if((void*)&result == (void*)&b) + { + cpp_int_backend t(b); + eval_multiply(result, a, t); + return; + } + + result.resize(as + bs, as + bs - 1); + typename cpp_int_backend::limb_pointer pr = result.limbs(); + + static const double_limb_type limb_max = ~static_cast(0u); + static const double_limb_type double_limb_max = ~static_cast(0u); + BOOST_STATIC_ASSERT(double_limb_max - 2 * limb_max >= limb_max * limb_max); + + double_limb_type carry = 0; + std::memset(pr, 0, result.size() * sizeof(limb_type)); + for(unsigned i = 0; i < as; ++i) + { + unsigned inner_limit = cpp_int_backend::variable ? bs : (std::min)(result.size() - i, bs); + for(unsigned j = 0; j < inner_limit; ++j) + { + BOOST_ASSERT(i+j < result.size()); + BOOST_ASSERT(!std::numeric_limits::is_specialized + || ((std::numeric_limits::max)() - carry + > + static_cast(cpp_int_backend::max_limb_value) * static_cast(cpp_int_backend::max_limb_value))); + carry += static_cast(pa[i]) * static_cast(pb[j]); + BOOST_ASSERT(!std::numeric_limits::is_specialized || ((std::numeric_limits::max)() - carry >= pr[i+j])); + carry += pr[i + j]; + pr[i + j] = static_cast(carry); + carry >>= cpp_int_backend::limb_bits; + BOOST_ASSERT(carry <= (cpp_int_backend::max_limb_value)); + } + resize_for_carry(result, as + bs); // May throw if checking is enabled + if(cpp_int_backend::variable || (i + bs < result.size())) + pr[i + bs] = static_cast(carry); + carry = 0; + } + result.normalize(); + // + // Set the sign of the result: + // + result.sign(a.sign() != b.sign()); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_multiply(result, result, a); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_multiply(cpp_int_backend& result, const limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_multiply(result, result, val); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const double_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(val <= (std::numeric_limits::max)()) + { + eval_multiply(result, a, static_cast(val)); + } + else + { + cpp_int_backend t(val); + eval_multiply(result, a, t); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_multiply(cpp_int_backend& result, const double_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_multiply(result, result, val); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const signed_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(val > 0) + eval_multiply(result, a, static_cast(val)); + else + { + eval_multiply(result, a, static_cast(-val)); + result.negate(); + } +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_multiply(cpp_int_backend& result, const signed_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_multiply(result, result, val); +} + +template +inline typename enable_if_c >::value && !is_trivial_cpp_int >::value >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const signed_double_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + if(val > 0) + { + if(val <= (std::numeric_limits::max)()) + { + eval_multiply(result, a, static_cast(val)); + return; + } + } + else if(val >= -static_cast((std::numeric_limits::max)())) + { + eval_multiply(result, a, static_cast(-val)); + result.negate(); + return; + } + cpp_int_backend t(val); + eval_multiply(result, a, t); +} + +template +BOOST_FORCEINLINE typename enable_if_c >::value>::type + eval_multiply(cpp_int_backend& result, const signed_double_limb_type& val) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + eval_multiply(result, result, val); +} + +// +// Now over again for trivial cpp_int's: +// +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value + || is_signed_number >::value) + >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.sign(result.sign() != o.sign()); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_unsigned_number >::value + >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& o) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_multiply(*result.limbs(), *o.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && (is_signed_number >::value + || is_signed_number >::value) + >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend::checked_type()); + result.sign(a.sign() != b.sign()); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + is_trivial_cpp_int >::value + && is_unsigned_number >::value + >::type + eval_multiply( + cpp_int_backend& result, + const cpp_int_backend& a, + const cpp_int_backend& b) BOOST_NOEXCEPT_IF((is_non_throwing_cpp_int >::value)) +{ + *result.limbs() = detail::checked_multiply(*a.limbs(), *b.limbs(), typename cpp_int_backend::checked_type()); + result.normalize(); +} + +// +// Special routines for multiplying two integers to obtain a multiprecision result: +// +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value + >::type + eval_multiply( + cpp_int_backend& result, + signed_double_limb_type a, signed_double_limb_type b) +{ + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + bool s = false; + double_limb_type w, x, y, z; + if(a < 0) + { + a = -a; + s = true; + } + if(b < 0) + { + b = -b; + s = !s; + } + w = a & mask; + x = a >> limb_bits; + y = b & mask; + z = b >> limb_bits; + + result.resize(4, 4); + limb_type* pr = result.limbs(); + + double_limb_type carry = w * y; + pr[0] = static_cast(carry); + carry >>= limb_bits; + carry += w * z + x * y; + pr[1] = static_cast(carry); + carry >>= limb_bits; + carry += x * z; + pr[2] = static_cast(carry); + pr[3] = static_cast(carry >> limb_bits); + + result.sign(s); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value + >::type + eval_multiply( + cpp_int_backend& result, + double_limb_type a, double_limb_type b) +{ + static const signed_double_limb_type mask = ~static_cast(0); + static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; + + double_limb_type w, x, y, z; + w = a & mask; + x = a >> limb_bits; + y = b & mask; + z = b >> limb_bits; + + result.resize(4, 4); + limb_type* pr = result.limbs(); + + double_limb_type carry = w * y; + pr[0] = static_cast(carry); + carry >>= limb_bits; + carry += w * z; + pr[1] = static_cast(carry); + carry >>= limb_bits; + pr[2] = static_cast(carry); + carry = x * y + pr[1]; + pr[1] = static_cast(carry); + carry >>= limb_bits; + carry += pr[2] + x * z; + pr[2] = static_cast(carry); + pr[3] = static_cast(carry >> limb_bits); + + result.sign(false); + result.normalize(); +} + +template +BOOST_FORCEINLINE typename enable_if_c< + !is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + && is_trivial_cpp_int >::value + >::type + eval_multiply( + cpp_int_backend& result, + cpp_int_backend const& a, + cpp_int_backend const& b) +{ + typedef typename boost::multiprecision::detail::canonical::local_limb_type, cpp_int_backend >::type canonical_type; + eval_multiply(result, static_cast(*a.limbs()), static_cast(*b.limbs())); + result.sign(a.sign() != b.sign()); +} + +template +BOOST_FORCEINLINE typename enable_if_c::value && (sizeof(SI) <= sizeof(signed_double_limb_type) / 2)>::type + eval_multiply( + cpp_int_backend& result, + SI a, SI b) +{ + result = static_cast(a) * static_cast(b); +} + +template +BOOST_FORCEINLINE typename enable_if_c::value && (sizeof(UI) <= sizeof(signed_double_limb_type) / 2)>::type + eval_multiply( + cpp_int_backend& result, + UI a, UI b) +{ + result = static_cast(a) * static_cast(b); +} + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/detail/big_lanczos.hpp b/include/boost/multiprecision/detail/big_lanczos.hpp new file mode 100644 index 00000000..094bcb02 --- /dev/null +++ b/include/boost/multiprecision/detail/big_lanczos.hpp @@ -0,0 +1,46 @@ + +// Copyright (c) 2011 John Maddock +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_BIG_LANCZOS +#define BOOST_MP_BIG_LANCZOS + +#include + +namespace boost{ namespace math{ + +namespace lanczos{ + +template +struct lanczos; + +template +struct lanczos, Policy> +{ + typedef typename boost::math::policies::precision, Policy>::type precision_type; + typedef typename mpl::if_c< + precision_type::value <= 73, + lanczos13UDT, + typename mpl::if_c< + precision_type::value <= 122, + lanczos22UDT, + typename mpl::if_c< + precision_type::value <= 172, + lanczos31UDT, + typename mpl::if_c< + precision_type::value <= 372, + lanczos61UDT, + undefined_lanczos + >::type + >::type + >::type + >::type type; +}; + +} // namespace lanczos + +}} // namespaces + +#endif diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp new file mode 100644 index 00000000..d93c0276 --- /dev/null +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -0,0 +1,1886 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BIG_NUM_DEF_OPS +#define BOOST_MATH_BIG_NUM_DEF_OPS + +#include +#include +#include +#include +#include +#include +#include + +#ifndef INSTRUMENT_BACKEND +#ifndef BOOST_MP_INSTRUMENT +#define INSTRUMENT_BACKEND(x) +#else +#define INSTRUMENT_BACKEND(x)\ + std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl; +#endif +#endif + + +namespace boost{ namespace multiprecision{ namespace default_ops{ + +#ifdef BOOST_MSVC +// warning C4127: conditional expression is constant +#pragma warning(push) +#pragma warning(disable:4127) +#endif +// +// Default versions of mixed arithmetic, these just construct a temporary +// from the arithmetic value and then do the arithmetic on that, two versions +// of each depending on whether the backend can be directly constructed from type V. +// +// Note that we have to provide *all* the template parameters to class number when used in +// enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter. +// Since the result of the test doesn't depend on whether expression templates are on or off +// we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the +// code even more.... +// +template +inline typename enable_if_c >::value && !is_convertible::value >::type + eval_add(T& result, V const& v) +{ + T t; + t = v; + eval_add(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value >::type + eval_add(T& result, V const& v) +{ + T t(v); + eval_add(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_subtract(T& result, V const& v) +{ + T t; + t = v; + eval_subtract(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_subtract(T& result, V const& v) +{ + T t(v); + eval_subtract(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_multiply(T& result, V const& v) +{ + T t; + t = v; + eval_multiply(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_multiply(T& result, V const& v) +{ + T t(v); + eval_multiply(result, t); +} + +template +void eval_multiply(T& t, const U& u, const V& v); + +template +inline typename disable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v) +{ + T z; + eval_multiply(z, u, v); + eval_add(t, z); +} +template +inline typename enable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v) +{ + eval_multiply_add(t, v, u); +} +template +inline typename disable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v) +{ + T z; + eval_multiply(z, u, v); + eval_subtract(t, z); +} +template +inline typename enable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v) +{ + eval_multiply_subtract(t, v, u); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_divide(T& result, V const& v) +{ + T t; + t = v; + eval_divide(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_divide(T& result, V const& v) +{ + T t(v); + eval_divide(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_modulus(T& result, V const& v) +{ + T t; + t = v; + eval_modulus(result, t); +} +template +inline typename enable_if_c >::value&& is_convertible::value>::type + eval_modulus(T& result, V const& v) +{ + T t(v); + eval_modulus(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_bitwise_and(T& result, V const& v) +{ + T t; + t = v; + eval_bitwise_and(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_bitwise_and(T& result, V const& v) +{ + T t(v); + eval_bitwise_and(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_bitwise_or(T& result, V const& v) +{ + T t; + t = v; + eval_bitwise_or(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_bitwise_or(T& result, V const& v) +{ + T t(v); + eval_bitwise_or(result, t); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_bitwise_xor(T& result, V const& v) +{ + T t; + t = v; + eval_bitwise_xor(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_bitwise_xor(T& result, V const& v) +{ + T t(v); + eval_bitwise_xor(result, t); +} + +template +inline typename enable_if_c >::value && !is_convertible::value>::type + eval_complement(T& result, V const& v) +{ + T t; + t = v; + eval_complement(result, t); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type + eval_complement(T& result, V const& v) +{ + T t(v); + eval_complement(result, t); +} + +// +// Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions: +// +template +void eval_add(T& t, const U& u, const V& v); + +template +inline void eval_add_default(T& t, const T& u, const T& v) +{ + if(&t == &v) + { + eval_add(t, u); + } + else if(&t == &u) + { + eval_add(t, v); + } + else + { + t = u; + eval_add(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_add_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_add(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_add_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_add(t, u, vv); +} +template +inline typename enable_if_c >::value>::type eval_add_default(T& t, const U& u, const T& v) +{ + eval_add(t, v, u); +} +template +inline void eval_add_default(T& t, const U& u, const V& v) +{ + t = u; + eval_add(t, v); +} +template +inline void eval_add(T& t, const U& u, const V& v) +{ + eval_add_default(t, u, v); +} + +template +void eval_subtract(T& t, const U& u, const V& v); + +template +inline void eval_subtract_default(T& t, const T& u, const T& v) +{ + if((&t == &v) && is_signed_number::value) + { + eval_subtract(t, u); + t.negate(); + } + else if(&t == &u) + { + eval_subtract(t, v); + } + else + { + t = u; + eval_subtract(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_subtract_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_subtract(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_subtract_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_subtract(t, u, vv); +} +template +inline typename enable_if_c >::value && is_signed_number::value>::type eval_subtract_default(T& t, const U& u, const T& v) +{ + eval_subtract(t, v, u); + t.negate(); +} +template +inline typename enable_if_c >::value && is_unsigned_number::value>::type eval_subtract_default(T& t, const U& u, const T& v) +{ + T temp(u); + eval_subtract(t, temp, v); +} +template +inline void eval_subtract_default(T& t, const U& u, const V& v) +{ + t = u; + eval_subtract(t, v); +} +template +inline void eval_subtract(T& t, const U& u, const V& v) +{ + eval_subtract_default(t, u, v); +} + +template +inline void eval_multiply_default(T& t, const T& u, const T& v) +{ + if(&t == &v) + { + eval_multiply(t, u); + } + else if(&t == &u) + { + eval_multiply(t, v); + } + else + { + t = u; + eval_multiply(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_multiply_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_multiply(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_multiply_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_multiply(t, u, vv); +} +template +inline typename enable_if_c >::value>::type eval_multiply_default(T& t, const U& u, const T& v) +{ + eval_multiply(t, v, u); +} +template +inline void eval_multiply_default(T& t, const U& u, const V& v) +{ + t = u; + eval_multiply(t, v); +} +template +inline void eval_multiply(T& t, const U& u, const V& v) +{ + eval_multiply_default(t, u, v); +} + +template +inline typename disable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x) +{ + if((void*)&x == (void*)&t) + { + T z; + z = x; + eval_multiply_add(t, u, v, z); + } + else + { + eval_multiply(t, u, v); + eval_add(t, x); + } +} +template +inline typename enable_if_c::value && is_same::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x) +{ + eval_multiply_add(t, v, u, x); +} +template +inline typename disable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x) +{ + if((void*)&x == (void*)&t) + { + T z; + z = x; + eval_multiply_subtract(t, u, v, z); + } + else + { + eval_multiply(t, u, v); + eval_subtract(t, x); + } +} +template +inline typename enable_if_c::value && is_same::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x) +{ + eval_multiply_subtract(t, v, u, x); +} + +template +void eval_divide(T& t, const U& u, const V& v); + +template +inline void eval_divide_default(T& t, const T& u, const T& v) +{ + if(&t == &u) + eval_divide(t, v); + else if(&t == &v) + { + T temp; + eval_divide(temp, u, v); + temp.swap(t); + } + else + { + t = u; + eval_divide(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_divide(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_divide_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_divide(t, u, vv); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide_default(T& t, const U& u, const T& v) +{ + T uu; + uu = u; + eval_divide(t, uu, v); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_divide_default(T& t, const U& u, const T& v) +{ + T uu(u); + eval_divide(t, uu, v); +} +template +inline void eval_divide_default(T& t, const U& u, const V& v) +{ + t = u; + eval_divide(t, v); +} +template +inline void eval_divide(T& t, const U& u, const V& v) +{ + eval_divide_default(t, u, v); +} + +template +void eval_modulus(T& t, const U& u, const V& v); + +template +inline void eval_modulus_default(T& t, const T& u, const T& v) +{ + if(&t == &u) + eval_modulus(t, v); + else if(&t == &v) + { + T temp; + eval_modulus(temp, u, v); + temp.swap(t); + } + else + { + t = u; + eval_modulus(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_modulus(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_modulus(t, u, vv); +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus_default(T& t, const U& u, const T& v) +{ + T uu; + uu = u; + eval_modulus(t, uu, v); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus_default(T& t, const U& u, const T& v) +{ + T uu(u); + eval_modulus(t, uu, v); +} +template +inline void eval_modulus_default(T& t, const U& u, const V& v) +{ + t = u; + eval_modulus(t, v); +} +template +inline void eval_modulus(T& t, const U& u, const V& v) +{ + eval_modulus_default(t, u, v); +} + +template +void eval_bitwise_and(T& t, const U& u, const V& v); + +template +inline void eval_bitwise_and_default(T& t, const T& u, const T& v) +{ + if(&t == &v) + { + eval_bitwise_and(t, u); + } + else if(&t == &u) + { + eval_bitwise_and(t, v); + } + else + { + t = u; + eval_bitwise_and(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_bitwise_and(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_bitwise_and(t, u, vv); +} +template +inline typename enable_if_c >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v) +{ + eval_bitwise_and(t, v, u); +} +template +inline void eval_bitwise_and_default(T& t, const U& u, const V& v) +{ + t = u; + eval_bitwise_and(t, v); +} +template +inline void eval_bitwise_and(T& t, const U& u, const V& v) +{ + eval_bitwise_and_default(t, u, v); +} + +template +void eval_bitwise_or(T& t, const U& u, const V& v); + +template +inline void eval_bitwise_or_default(T& t, const T& u, const T& v) +{ + if(&t == &v) + { + eval_bitwise_or(t, u); + } + else if(&t == &u) + { + eval_bitwise_or(t, v); + } + else + { + t = u; + eval_bitwise_or(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_bitwise_or(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_bitwise_or(t, u, vv); +} +template +inline typename enable_if_c >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v) +{ + eval_bitwise_or(t, v, u); +} +template +inline void eval_bitwise_or_default(T& t, const U& u, const V& v) +{ + t = u; + eval_bitwise_or(t, v); +} +template +inline void eval_bitwise_or(T& t, const U& u, const V& v) +{ + eval_bitwise_or_default(t, u, v); +} + +template +void eval_bitwise_xor(T& t, const U& u, const V& v); + +template +inline void eval_bitwise_xor_default(T& t, const T& u, const T& v) +{ + if(&t == &v) + { + eval_bitwise_xor(t, u); + } + else if(&t == &u) + { + eval_bitwise_xor(t, v); + } + else + { + t = u; + eval_bitwise_xor(t, v); + } +} +template +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v) +{ + T vv; + vv = v; + eval_bitwise_xor(t, u, vv); +} +template +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v) +{ + T vv(v); + eval_bitwise_xor(t, u, vv); +} +template +inline typename enable_if_c >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v) +{ + eval_bitwise_xor(t, v, u); +} +template +inline void eval_bitwise_xor_default(T& t, const U& u, const V& v) +{ + t = u; + eval_bitwise_xor(t, v); +} +template +inline void eval_bitwise_xor(T& t, const U& u, const V& v) +{ + eval_bitwise_xor_default(t, u, v); +} + +template +inline void eval_increment(T& val) +{ + typedef typename mpl::front::type ui_type; + eval_add(val, static_cast(1u)); +} +template +inline void eval_decrement(T& val) +{ + typedef typename mpl::front::type ui_type; + eval_subtract(val, static_cast(1u)); +} + +template +inline void eval_left_shift(T& result, const T& arg, const V val) +{ + result = arg; + eval_left_shift(result, val); +} + +template +inline void eval_right_shift(T& result, const T& arg, const V val) +{ + result = arg; + eval_right_shift(result, val); +} + +template +inline bool eval_is_zero(const T& val) +{ + typedef typename mpl::front::type ui_type; + return val.compare(static_cast(0)) == 0; +} +template +inline int eval_get_sign(const T& val) +{ + typedef typename mpl::front::type ui_type; + return val.compare(static_cast(0)); +} + +template +inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl::int_&) +{ + result = v1; + T t; + t = v2; + eval_divide(result, t); +} + +template +inline void assign_components(T& result, const V& v1, const V& v2) +{ + return assign_components_imp(result, v1, v2, typename number_category::type()); +} + +template +struct has_enough_bits +{ + template + struct type : public mpl::and_ >, mpl::bool_::digits >= b> >{}; +}; + +template +struct terminal +{ + terminal(const R& v) : value(v){} + terminal(){} + terminal& operator = (R val) { value = val; } + R value; + operator R()const { return value; } +}; + +template +struct calculate_next_larger_type +{ + typedef typename mpl::if_< + is_signed, + typename B::signed_types, + typename mpl::if_< + is_unsigned, + typename B::unsigned_types, + typename B::float_types + >::type + >::type list_type; + typedef typename has_enough_bits::digits>::template type pred_type; + typedef typename mpl::find_if< + list_type, + pred_type + >::type iter_type; + typedef typename mpl::eval_if< + is_same::type, iter_type>, + mpl::identity >, + mpl::deref + >::type type; +}; + +template +inline bool check_in_range(const T& t) +{ + // Can t fit in an R? + if(std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && (t > (std::numeric_limits::max)())) + return true; + return false; +} + +template +inline bool check_in_range(const terminal&) +{ + return false; +} + +template +inline void eval_convert_to(R* result, const B& backend) +{ + typedef typename calculate_next_larger_type::type next_type; + next_type n; + eval_convert_to(&n, backend); + if(check_in_range(n)) + { + *result = (std::numeric_limits::max)(); + } + else + *result = static_cast(n); +} + +template +inline void eval_convert_to(terminal* result, const B& backend) +{ + // + // We ran out of types to try for the convertion, try + // a lexical_cast and hope for the best: + // + result->value = boost::lexical_cast(backend.str(0, std::ios_base::fmtflags(0))); +} + +template +inline void eval_convert_to(std::string* result, const B& backend) +{ + *result = backend.str(0, std::ios_base::fmtflags(0)); +} +// +// Functions: +// +template +void eval_abs(T& result, const T& arg) +{ + typedef typename T::signed_types type_list; + typedef typename mpl::front::type front; + result = arg; + if(arg.compare(front(0)) < 0) + result.negate(); +} +template +void eval_fabs(T& result, const T& arg) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fabs function is only valid for floating point types."); + typedef typename T::signed_types type_list; + typedef typename mpl::front::type front; + result = arg; + if(arg.compare(front(0)) < 0) + result.negate(); +} + +template +inline int eval_fpclassify(const Backend& arg) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types."); + return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL; +} + +template +inline void eval_fmod(T& result, const T& a, const T& b) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The fmod function is only valid for floating point types."); + if((&result == &a) || (&result == &b)) + { + T temp; + eval_fmod(temp, a, b); + result = temp; + return; + } + T n; + eval_divide(result, a, b); + if(eval_get_sign(a) < 0) + eval_ceil(n, result); + else + eval_floor(n, result); + eval_multiply(n, b); + eval_subtract(result, a, n); +} +template +inline typename enable_if, void>::type eval_fmod(T& result, const T& x, const A& a) +{ + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = a; + eval_fmod(result, x, c); +} + +template +inline typename enable_if, void>::type eval_fmod(T& result, const A& x, const T& a) +{ + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = x; + eval_fmod(result, c, a); +} + +template +inline void eval_trunc(T& result, const T& a) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The trunc function is only valid for floating point types."); + int c = eval_fpclassify(a); + if(c == FP_NAN || c == FP_INFINITE) + { + result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number(a), 0, boost::math::policies::policy<>()).backend(); + return; + } + if(eval_get_sign(a) < 0) + eval_ceil(result, a); + else + eval_floor(result, a); +} + +template +inline void eval_round(T& result, const T& a) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The round function is only valid for floating point types."); + typedef typename boost::multiprecision::detail::canonical::type fp_type; + int c = eval_fpclassify(a); + if(c == FP_NAN || c == FP_INFINITE) + { + result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number(a), 0, boost::math::policies::policy<>()).backend(); + return; + } + if(eval_get_sign(a) < 0) + { + eval_subtract(result, a, fp_type(0.5f)); + eval_ceil(result, result); + } + else + { + eval_add(result, a, fp_type(0.5f)); + eval_floor(result, result); + } +} + +template +void eval_lcm(B& result, const B& a, const B& b); +template +void eval_gcd(B& result, const B& a, const B& b); + +template +inline typename enable_if >::type eval_gcd(T& result, const T& a, const Arithmetic& b) +{ + typedef typename boost::multiprecision::detail::canonical::type si_type; + using default_ops::eval_gcd; + T t; + t = static_cast(b); + eval_gcd(result, a, t); +} +template +inline typename enable_if >::type eval_gcd(T& result, const Arithmetic& a, const T& b) +{ + eval_gcd(result, b, a); +} +template +inline typename enable_if >::type eval_lcm(T& result, const T& a, const Arithmetic& b) +{ + typedef typename boost::multiprecision::detail::canonical::type si_type; + using default_ops::eval_lcm; + T t; + t = static_cast(b); + eval_lcm(result, a, t); +} +template +inline typename enable_if >::type eval_lcm(T& result, const Arithmetic& a, const T& b) +{ + eval_lcm(result, b, a); +} + +template +inline unsigned eval_lsb(const T& val) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + unsigned result = 0; + T mask, t; + mask = ui_type(1); + do + { + eval_bitwise_and(t, mask, val); + ++result; + eval_left_shift(mask, 1); + } + while(eval_is_zero(t)); + + return --result; +} + +template +inline bool eval_bit_test(const T& val, unsigned index) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + T mask, t; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_and(t, mask, val); + return !eval_is_zero(t); +} + +template +inline void eval_bit_set(T& val, unsigned index) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + T mask; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_or(val, mask); +} + +template +inline void eval_bit_flip(T& val, unsigned index) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + T mask; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_xor(val, mask); +} + +template +inline void eval_bit_unset(T& val, unsigned index) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + T mask, t; + mask = ui_type(1); + eval_left_shift(mask, index); + eval_bitwise_and(t, mask, val); + if(!eval_is_zero(t)) + eval_bitwise_xor(val, mask); +} + +// +// These have to implemented by the backend, declared here so that our macro generated code compiles OK. +// +template +typename enable_if_c::type eval_floor(); +template +typename enable_if_c::type eval_ceil(); +template +typename enable_if_c::type eval_trunc(); +template +typename enable_if_c::type eval_sqrt(); +template +typename enable_if_c::type eval_ldexp(); +template +typename enable_if_c::type eval_frexp(); +// +// These functions are implemented in separate files, but expanded inline here, +// DO NOT CHANGE THE ORDER OF THESE INCLUDES: +// +#include +#include +#include + +} + +} // namespace multiprecision +namespace math{ +// +// Default versions of floating point classification routines: +// +template +inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) +{ + using multiprecision::default_ops::eval_fpclassify; + return eval_fpclassify(arg.backend()); +} +template +inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) +{ + typedef typename multiprecision::detail::expression::result_type value_type; + return fpclassify(value_type(arg)); +} +template +inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) +{ + int v = fpclassify(arg); + return (v != FP_INFINITE) && (v != FP_NAN); +} +template +inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) +{ + typedef typename multiprecision::detail::expression::result_type value_type; + return isfinite(value_type(arg)); +} +template +inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) +{ + return fpclassify(arg) == FP_NAN; +} +template +inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) +{ + typedef typename multiprecision::detail::expression::result_type value_type; + return isnan(value_type(arg)); +} +template +inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) +{ + return fpclassify(arg) == FP_INFINITE; +} +template +inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) +{ + typedef typename multiprecision::detail::expression::result_type value_type; + return isinf(value_type(arg)); +} +template +inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number& arg) +{ + return fpclassify(arg) == FP_NORMAL; +} +template +inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression& arg) +{ + typedef typename multiprecision::detail::expression::result_type value_type; + return isnormal(value_type(arg)); +} + +} // namespace math +namespace multiprecision{ + +template +inline number& add(number& result, const number& a, const number& b) +{ + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), b.backend()); + return result; +} + +template +inline number& subtract(number& result, const number& a, const number& b) +{ + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), b.backend()); + return result; +} + +template +inline number& multiply(number& result, const number& a, const number& b) +{ + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + BOOST_STATIC_ASSERT_MSG((is_convertible::value), "No conversion to the target of a mixed precision addition exists"); + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), b.backend()); + return result; +} + +template +inline typename enable_if_c::value, number&>::type + add(number& result, const I& a, const I& b) +{ + using default_ops::eval_add; + typedef typename detail::canonical::type canonical_type; + eval_add(result.backend(), static_cast(a), static_cast(b)); + return result; +} + +template +inline typename enable_if_c::value, number&>::type + subtract(number& result, const I& a, const I& b) +{ + using default_ops::eval_subtract; + typedef typename detail::canonical::type canonical_type; + eval_subtract(result.backend(), static_cast(a), static_cast(b)); + return result; +} + +template +inline typename enable_if_c::value, number&>::type + multiply(number& result, const I& a, const I& b) +{ + using default_ops::eval_multiply; + typedef typename detail::canonical::type canonical_type; + eval_multiply(result.backend(), static_cast(a), static_cast(b)); + return result; +} + +template +inline typename detail::expression::result_type trunc(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(trunc(number_type(v), pol)); +} + +template +inline number trunc(const number& v, const Policy&) +{ + using default_ops::eval_trunc; + number result; + eval_trunc(result.backend(), v.backend()); + return BOOST_MP_MOVE(result); +} + +template +inline int itrunc(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol).template convert_to(); + return r.template convert_to(); +} +template +inline int itrunc(const detail::expression& v) +{ + return itrunc(v, boost::math::policies::policy<>()); +} +template +inline int itrunc(const number& v, const Policy& pol) +{ + number r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol).template convert_to(); + return r.template convert_to(); +} +template +inline int itrunc(const number& v) +{ + return itrunc(v, boost::math::policies::policy<>()); +} +template +inline long ltrunc(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long ltrunc(const detail::expression& v) +{ + return ltrunc(v, boost::math::policies::policy<>()); +} +template +inline long ltrunc(const number& v, const Policy& pol) +{ + number r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long ltrunc(const number& v) +{ + return ltrunc(v, boost::math::policies::policy<>()); +} +#ifndef BOOST_NO_LONG_LONG +template +inline long long lltrunc(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long long lltrunc(const detail::expression& v) +{ + return lltrunc(v, boost::math::policies::policy<>()); +} +template +inline long long lltrunc(const number& v, const Policy& pol) +{ + number r = trunc(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long long lltrunc(const number& v) +{ + return lltrunc(v, boost::math::policies::policy<>()); +} +#endif +template +inline typename detail::expression::result_type round(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + return BOOST_MP_MOVE(round(static_cast(v), pol)); +} +template +inline number round(const number& v, const Policy&) +{ + using default_ops::eval_round; + number result; + eval_round(result.backend(), v.backend()); + return BOOST_MP_MOVE(result); +} + +template +inline int iround(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol).template convert_to(); + return r.template convert_to(); +} +template +inline int iround(const detail::expression& v) +{ + return iround(v, boost::math::policies::policy<>()); +} +template +inline int iround(const number& v, const Policy& pol) +{ + number r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol).template convert_to(); + return r.template convert_to(); +} +template +inline int iround(const number& v) +{ + return iround(v, boost::math::policies::policy<>()); +} +template +inline long lround(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long lround(const detail::expression& v) +{ + return lround(v, boost::math::policies::policy<>()); +} +template +inline long lround(const number& v, const Policy& pol) +{ + number r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long lround(const number& v) +{ + return lround(v, boost::math::policies::policy<>()); +} +#ifndef BOOST_NO_LONG_LONG +template +inline long long llround(const detail::expression& v, const Policy& pol) +{ + typedef typename detail::expression::result_type number_type; + number_type r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long long llround(const detail::expression& v) +{ + return llround(v, boost::math::policies::policy<>()); +} +template +inline long long llround(const number& v, const Policy& pol) +{ + number r = round(v, pol); + if((r > (std::numeric_limits::max)()) || r < (std::numeric_limits::min)() || !boost::math::isfinite(v)) + return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol).template convert_to(); + return r.template convert_to(); +} +template +inline long long llround(const number& v) +{ + return llround(v, boost::math::policies::policy<>()); +} +#endif + +#define UNARY_OP_FUNCTOR(func, category)\ +namespace detail{\ +template \ +struct BOOST_JOIN(func, _funct)\ +{\ + void operator()(Backend& result, const Backend& arg)const\ + {\ + using default_ops::BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result, arg);\ + }\ +};\ +\ +}\ +\ +template \ +inline typename enable_if_c >::value == category,\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression > \ +>::type \ +func(const detail::expression& arg)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ +> (\ + detail::BOOST_JOIN(func, _funct) >::type>() \ + , arg \ + );\ +}\ +template \ +inline typename enable_if_c::value == category,\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number > \ +>::type \ +func(const number& arg)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg \ + );\ +}\ +template \ +inline typename boost::enable_if_c<\ + boost::multiprecision::number_category::value == category,\ + number >::type \ +func(const number& arg)\ +{\ + number result;\ + using default_ops::BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\ + return BOOST_MP_MOVE(result);\ +} + +#define BINARY_OP_FUNCTOR(func, category)\ +namespace detail{\ +template \ +struct BOOST_JOIN(func, _funct)\ +{\ + void operator()(Backend& result, const Backend& arg, const Backend& a)const\ + {\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result, arg, a);\ + }\ + template \ + void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\ + {\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result, arg, a);\ + }\ + template \ + void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\ + {\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result, arg, a);\ + }\ +};\ +\ +}\ +template \ +inline typename enable_if_c::value == category,\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , number > \ +>::type \ +func(const number& arg, const number& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , number \ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + (number_category::value == category) && (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , detail::expression > \ +>::type \ +func(const number& arg, const detail::expression& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , detail::expression \ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + (number_category::value == category) && (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , detail::expression \ + , number > \ +>::type \ +func(const detail::expression& arg, const number& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , detail::expression \ + , number \ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + (number_category >::value == category) && (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , detail::expression > \ +>::type \ +func(const detail::expression& arg, const detail::expression& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , detail::expression \ + >(\ + detail::BOOST_JOIN(func, _funct) >::type>() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , Arithmetic\ + > \ +>::type \ +func(const number& arg, const Arithmetic& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , Arithmetic\ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , Arithmetic\ + > \ +>::type \ +func(const detail::expression& arg, const Arithmetic& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , Arithmetic\ + >(\ + detail::BOOST_JOIN(func, _funct) >::type>() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , Arithmetic \ + , number \ + > \ +>::type \ +func(const Arithmetic& arg, const number& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , Arithmetic \ + , number \ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , Arithmetic \ + , detail::expression \ + > \ +>::type \ +func(const Arithmetic& arg, const detail::expression& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , Arithmetic \ + , detail::expression \ + >(\ + detail::BOOST_JOIN(func, _funct) >::type>() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<(number_category::value == category),\ + number >::type \ +func(const number& arg, const number& a)\ +{\ + number result;\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\ + return BOOST_MP_MOVE(result);\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category::value == category),\ + number \ +>::type \ +func(const number& arg, const Arithmetic& a)\ +{\ + typedef typename detail::canonical::type canonical_type;\ + number result;\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast(a));\ + return BOOST_MP_MOVE(result);\ +}\ +template \ +inline typename enable_if_c<\ + is_arithmetic::value && (number_category::value == category),\ + number \ +>::type \ +func(const Arithmetic& a, const number& arg)\ +{\ + typedef typename detail::canonical::type canonical_type;\ + number result;\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result.backend(), static_cast(a), arg.backend());\ + return BOOST_MP_MOVE(result);\ +}\ + + +#define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\ +template \ +inline typename enable_if_c<\ + (number_category >::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , Arg2> \ +>::type \ +func(const detail::expression& arg, Arg2 const& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) >::type> \ + , detail::expression \ + , Arg2\ + >(\ + detail::BOOST_JOIN(func, _funct) >::type>() \ + , arg, a \ + );\ +}\ +template \ +inline typename enable_if_c<\ + (number_category::value == category),\ + detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , Arg2> \ +>::type \ +func(const number& arg, Arg2 const& a)\ +{\ + return detail::expression<\ + detail::function\ + , detail::BOOST_JOIN(func, _funct) \ + , number \ + , Arg2\ + >(\ + detail::BOOST_JOIN(func, _funct)() \ + , arg,\ + a\ + );\ +}\ +template \ +inline typename enable_if_c<\ + (number_category::value == category),\ + number >::type \ +func(const number& arg, Arg2 const& a)\ +{\ + number result;\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\ + return BOOST_MP_MOVE(result);\ +}\ + +#define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\ +namespace detail{\ +template \ +struct BOOST_JOIN(func, _funct)\ +{\ + template \ + void operator()(Backend& result, Backend const& arg, Arg a)const\ + {\ + using default_ops:: BOOST_JOIN(eval_,func);\ + BOOST_JOIN(eval_,func)(result, arg, a);\ + }\ +};\ +\ +}\ +\ +HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) + +namespace detail{ +template +struct abs_funct +{ + void operator()(Backend& result, const Backend& arg)const + { + using default_ops::eval_abs; + eval_abs(result, arg); + } +}; + +} + +template +inline detail::expression< + detail::function + , detail::abs_funct >::type> + , detail::expression > +abs(const detail::expression& arg) +{ + return detail::expression< + detail::function + , detail::abs_funct >::type> + , detail::expression +> ( + detail::abs_funct >::type>() + , arg + ); +} +template +inline detail::expression< + detail::function + , detail::abs_funct + , number > +abs(const number& arg) +{ + return detail::expression< + detail::function + , detail::abs_funct + , number + >( + detail::abs_funct() + , arg + ); +} +template +inline number +abs(const number& arg) +{ + number result; + using default_ops::eval_abs; + eval_abs(result.backend(), arg.backend()); + return BOOST_MP_MOVE(result); +} + +UNARY_OP_FUNCTOR(fabs, number_kind_floating_point) +UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point) +UNARY_OP_FUNCTOR(floor, number_kind_floating_point) +UNARY_OP_FUNCTOR(ceil, number_kind_floating_point) +UNARY_OP_FUNCTOR(trunc, number_kind_floating_point) +UNARY_OP_FUNCTOR(round, number_kind_floating_point) +UNARY_OP_FUNCTOR(exp, number_kind_floating_point) +UNARY_OP_FUNCTOR(log, number_kind_floating_point) +UNARY_OP_FUNCTOR(log10, number_kind_floating_point) +UNARY_OP_FUNCTOR(cos, number_kind_floating_point) +UNARY_OP_FUNCTOR(sin, number_kind_floating_point) +UNARY_OP_FUNCTOR(tan, number_kind_floating_point) +UNARY_OP_FUNCTOR(asin, number_kind_floating_point) +UNARY_OP_FUNCTOR(acos, number_kind_floating_point) +UNARY_OP_FUNCTOR(atan, number_kind_floating_point) +UNARY_OP_FUNCTOR(cosh, number_kind_floating_point) +UNARY_OP_FUNCTOR(sinh, number_kind_floating_point) +UNARY_OP_FUNCTOR(tanh, number_kind_floating_point) + +HETERO_BINARY_OP_FUNCTOR(ldexp, int, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR(frexp, int*, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point) +HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point) +BINARY_OP_FUNCTOR(pow, number_kind_floating_point) +BINARY_OP_FUNCTOR(fmod, number_kind_floating_point) +BINARY_OP_FUNCTOR(atan2, number_kind_floating_point) + +// +// Integer functions: +// +BINARY_OP_FUNCTOR(gcd, number_kind_integer) +BINARY_OP_FUNCTOR(lcm, number_kind_integer) +HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer) + +#undef BINARY_OP_FUNCTOR +#undef UNARY_OP_FUNCTOR + +} //namespace multiprecision + +namespace math{ +// +// Overload of Boost.Math functions that find the wrong overload when used with number: +// +namespace detail{ + template T sinc_pi_imp(T); + template T sinhc_pi_imp(T); +} +template +inline multiprecision::number sinc_pi(const multiprecision::number& x) +{ + return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); +} + +template +inline multiprecision::number sinc_pi(const multiprecision::number& x, const Policy&) +{ + return BOOST_MP_MOVE(detail::sinc_pi_imp(x)); +} + +template +inline multiprecision::number sinhc_pi(const multiprecision::number& x) +{ + return BOOST_MP_MOVE(detail::sinhc_pi_imp(x)); +} + +template +inline multiprecision::number sinhc_pi(const multiprecision::number& x, const Policy&) +{ + return BOOST_MP_MOVE(boost::math::sinhc_pi(x)); +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} // namespace math +} // namespace boost + +// +// This has to come last of all: +// +#include +#include + +#endif + diff --git a/include/boost/multiprecision/detail/digits.hpp b/include/boost/multiprecision/detail/digits.hpp new file mode 100644 index 00000000..8752f5b5 --- /dev/null +++ b/include/boost/multiprecision/detail/digits.hpp @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_DIGITS_HPP +#define BOOST_MP_DIGITS_HPP + +namespace boost{ namespace multiprecision{ namespace detail{ + +inline unsigned long digits10_2_2(unsigned long d10) +{ + return (d10 * 1000uL) / 301uL + ((d10 * 1000uL) % 301 ? 2u : 1u); +} + +inline unsigned long digits2_2_10(unsigned long d2) +{ + return (d2 * 301uL) / 1000uL; +} + +}}} // namespaces + +#endif diff --git a/include/boost/multiprecision/detail/et_ops.hpp b/include/boost/multiprecision/detail/et_ops.hpp new file mode 100644 index 00000000..9808a6aa --- /dev/null +++ b/include/boost/multiprecision/detail/et_ops.hpp @@ -0,0 +1,759 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_ET_OPS_HPP +#define BOOST_MP_ET_OPS_HPP + +namespace boost{ namespace multiprecision{ + +// +// Non-member operators for number: +// +// Unary operators first: +// +template +inline const number& operator + (const number& v) { return v; } +template +inline const detail::expression& operator + (const detail::expression& v) { return v; } +template +inline detail::expression > operator - (const number& v) +{ + BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); + return detail::expression >(v); +} +template +inline detail::expression > operator - (const detail::expression& v) +{ + BOOST_STATIC_ASSERT_MSG((is_signed_number::result_type>::value), "Negating an unsigned type results in ill-defined behavior."); + return detail::expression >(v); +} +template +inline detail::expression > operator ~ (const number& v) { return detail::expression >(v); } +template +inline detail::expression > operator ~ (const detail::expression& v) { return detail::expression >(v); } +// +// Then addition: +// +template +inline detail::expression, number > + operator + (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator + (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator + (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator + (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator + (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator + (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator + (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator + (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Fused multiply add: +// +template +inline typename enable_if::result_type>, + detail::expression::left_type, typename detail::expression::right_type, V> >::type + operator + (const V& a, const detail::expression& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a); +} +template +inline typename enable_if::result_type>, + detail::expression::left_type, typename detail::expression::right_type, V> >::type + operator + (const detail::expression& a, const V& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); +} +template +inline detail::expression::left_type, typename detail::expression::right_type, number > + operator + (const number& a, const detail::expression& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a); +} +template +inline detail::expression::left_type, typename detail::expression::right_type, number > + operator + (const detail::expression& a, const number& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); +} +// +// Fused multiply subtract: +// +template +inline typename enable_if::result_type>, + detail::expression::left_type, typename detail::expression::right_type, V> > >::type + operator - (const V& a, const detail::expression& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, V> > + (detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a)); +} +template +inline typename enable_if::result_type>, + detail::expression::left_type, typename detail::expression::right_type, V> >::type + operator - (const detail::expression& a, const V& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); +} +template +inline detail::expression::left_type, typename detail::expression::right_type, number > > + operator - (const number& a, const detail::expression& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, number > > + (detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a)); +} +template +inline detail::expression::left_type, typename detail::expression::right_type, number > + operator - (const detail::expression& a, const number& b) +{ + return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > + operator + (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); +} +template +inline detail::expression, typename detail::expression::left_type > + operator + (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type >(b, a.left_ref()); +} +template +inline detail::expression, number > + operator + (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > + operator + (const detail::expression >& a, const number& b) +{ + return detail::expression, number >(b, a.left_ref()); +} +template +inline typename enable_if >, detail::expression > >::type + operator + (const detail::expression >& a, const V& b) +{ + return detail::expression >(b, a.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator + (const detail::expression >& a, const number& b) +{ + return detail::expression, number >(b, a.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator + (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > > + operator + (const detail::expression >& a, const detail::expression >& b) +{ + return detail::expression, number > >(detail::expression, number >(a.left_ref(), b.left_ref())); +} +// +// Subtraction: +// +template +inline detail::expression, number > + operator - (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator - (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator - (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator - (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator - (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator - (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator - (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator - (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > + operator - (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); +} +template +inline detail::expression, typename detail::expression::left_type > > + operator - (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(b, a.left_ref())); +} +template +inline detail::expression, number > + operator - (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > > + operator - (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(b, a.left_ref())); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator - (const detail::expression >& a, const V& b) +{ + return detail::expression, V > >(detail::expression, V >(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator - (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >(detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression > >::type + operator - (const V& a, const detail::expression >& b) +{ + return detail::expression >(a, b.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator - (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +// +// Multiplication: +// +template +inline detail::expression, number > + operator * (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator * (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator * (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator * (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator * (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator * (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator * (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator * (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > > + operator * (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type > (a, b.left_ref())); +} +template +inline detail::expression, typename detail::expression::left_type > > + operator * (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(b, a.left_ref())); +} +template +inline detail::expression, number > > + operator * (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +template +inline detail::expression, number > > + operator * (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(b, a.left_ref())); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator * (const detail::expression >& a, const V& b) +{ + return detail::expression, V > > ( + detail::expression, V >(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator * (const detail::expression >& a, const number& b) +{ + return detail::expression, number > > ( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator * (const V& a, const detail::expression >& b) +{ + return detail::expression, V > >( + detail::expression, V >(b.left_ref(), a)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator * (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(b.left_ref(), a)); +} +// +// Division: +// +template +inline detail::expression, number > + operator / (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator / (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator / (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator / (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator / (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator / (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator / (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator / (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > > + operator / (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(a, b.left_ref())); +} +template +inline detail::expression::left_type, number > > + operator / (const detail::expression& a, const number& b) +{ + return detail::expression::left_type, number > >( + detail::expression::left_type, number >(a.left_ref(), b)); +} +template +inline detail::expression, number > > + operator / (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +template +inline detail::expression, number > > + operator / (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator / (const detail::expression >& a, const V& b) +{ + return detail::expression, V > >( + detail::expression, V>(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator / (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression > > >::type + operator / (const V& a, const detail::expression >& b) +{ + return detail::expression > >( + detail::expression >(a, b.left_ref())); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator / (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +// +// Modulus: +// +template +inline detail::expression, number > + operator % (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator % (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator % (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator % (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator % (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator % (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator % (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator % (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Left shift: +// +template +inline typename enable_if, detail::expression, I > >::type + operator << (const number& a, const I& b) +{ + return detail::expression, I>(a, b); +} +template +inline typename enable_if, detail::expression, I> >::type + operator << (const detail::expression& a, const I& b) +{ + return detail::expression, I>(a, b); +} +// +// Right shift: +// +template +inline typename enable_if, detail::expression, I > >::type + operator >> (const number& a, const I& b) +{ + return detail::expression, I>(a, b); +} +template +inline typename enable_if, detail::expression, I> >::type + operator >> (const detail::expression& a, const I& b) +{ + return detail::expression, I>(a, b); +} +// +// Bitwise AND: +// +template +inline detail::expression, number > + operator & (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator & (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator & (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator & (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator & (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator & (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator & (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator & (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Bitwise OR: +// +template +inline detail::expression, number > + operator| (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator| (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator| (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator| (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator| (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator| (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator| (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator| (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Bitwise XOR: +// +template +inline detail::expression, number > + operator^ (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator^ (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator^ (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator^ (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator^ (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator^ (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator^ (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator^ (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} + +}} // namespaces + +#endif diff --git a/include/boost/multiprecision/detail/functions/constants.hpp b/include/boost/multiprecision/detail/functions/constants.hpp new file mode 100644 index 00000000..b32f3f28 --- /dev/null +++ b/include/boost/multiprecision/detail/functions/constants.hpp @@ -0,0 +1,289 @@ +// Copyright 2011 John Maddock. Distributed under the Boost +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp +// + +template +void calc_log2(T& num, unsigned digits) +{ + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename mpl::front::type si_type; + + // + // String value with 1100 digits: + // + static const char* string_val = "0." + "6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875" + "4200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335" + "0115364497955239120475172681574932065155524734139525882950453007095326366642654104239157814952043740" + "4303855008019441706416715186447128399681717845469570262716310645461502572074024816377733896385506952" + "6066834113727387372292895649354702576265209885969320196505855476470330679365443254763274495125040606" + "9438147104689946506220167720424524529612687946546193165174681392672504103802546259656869144192871608" + "2938031727143677826548775664850856740776484514644399404614226031930967354025744460703080960850474866" + "3852313818167675143866747664789088143714198549423151997354880375165861275352916610007105355824987941" + "4729509293113897155998205654392871700072180857610252368892132449713893203784393530887748259701715591" + "0708823683627589842589185353024363421436706118923678919237231467232172053401649256872747782344535347" + "6481149418642386776774406069562657379600867076257199184734022651462837904883062033061144630073719489"; + // + // Check if we can just construct from string: + // + if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + num = string_val; + return; + } + // + // We calculate log2 from using the formula: + // + // ln(2) = 3/4 SUM[n>=0] ((-1)^n * N!^2 / (2^n(2n+1)!)) + // + // Numerator and denominator are calculated separately and then + // divided at the end, we also precalculate the terms up to n = 5 + // since these fit in a 32-bit integer anyway. + // + // See Gourdon, X., and Sebah, P. The logarithmic constant: log 2, Jan. 2004. + // Also http://www.mpfr.org/algorithms.pdf. + // + num = static_cast(1180509120uL); + T denom, next_term, temp; + denom = static_cast(1277337600uL); + next_term = static_cast(120uL); + si_type sign = -1; + + ui_type limit = digits / 3 + 1; + + for(ui_type n = 6; n < limit; ++n) + { + temp = static_cast(2); + eval_multiply(temp, ui_type(2 * n)); + eval_multiply(temp, ui_type(2 * n + 1)); + eval_multiply(num, temp); + eval_multiply(denom, temp); + sign = -sign; + eval_multiply(next_term, n); + eval_multiply(temp, next_term, next_term); + if(sign < 0) + temp.negate(); + eval_add(num, temp); + } + eval_multiply(denom, ui_type(4)); + eval_multiply(num, ui_type(3)); + INSTRUMENT_BACKEND(denom); + INSTRUMENT_BACKEND(num); + eval_divide(num, denom); + INSTRUMENT_BACKEND(num); +} + +template +void calc_e(T& result, unsigned digits) +{ + typedef typename mpl::front::type ui_type; + typedef typename mpl::front::type real_type; + // + // 1100 digits in string form: + // + const char* string_val = "2." + "7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274" + "2746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901" + "1573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069" + "5517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416" + "9283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312" + "7736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117" + "3012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509" + "9618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496" + "8487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016" + "7683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354" + "0212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508869"; + // + // Check if we can just construct from string: + // + if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + result = string_val; + return; + } + + T lim; + lim = ui_type(1); + eval_ldexp(lim, lim, digits); + + // + // Standard evaluation from the definition of e: http://functions.wolfram.com/Constants/E/02/ + // + result = ui_type(2); + T denom; + denom = ui_type(1); + ui_type i = 2; + do{ + eval_multiply(denom, i); + eval_multiply(result, i); + eval_add(result, ui_type(1)); + ++i; + }while(denom.compare(lim) <= 0); + eval_divide(result, denom); +} + +template +void calc_pi(T& result, unsigned digits) +{ + typedef typename mpl::front::type ui_type; + typedef typename mpl::front::type real_type; + // + // 1100 digits in string form: + // + const char* string_val = "3." + "1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" + "8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196" + "4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273" + "7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094" + "3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912" + "9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132" + "0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235" + "4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859" + "5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303" + "5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989" + "3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913152"; + // + // Check if we can just construct from string: + // + if(digits < 3640) // 3640 binary digits ~ 1100 decimal digits + { + result = string_val; + return; + } + + T a; + a = ui_type(1); + T b; + T A(a); + T B; + B = real_type(0.5f); + T D; + D = real_type(0.25f); + + T lim; + lim = ui_type(1); + eval_ldexp(lim, lim, -(int)digits); + + // + // This algorithm is from: + // Schonhage, A., Grotefeld, A. F. W., and Vetter, E. Fast Algorithms: A Multitape Turing + // Machine Implementation. BI Wissenschaftverlag, 1994. + // Also described in MPFR's algorithm guide: http://www.mpfr.org/algorithms.pdf. + // + // Let: + // a[0] = A[0] = 1 + // B[0] = 1/2 + // D[0] = 1/4 + // Then: + // S[k+1] = (A[k]+B[k]) / 4 + // b[k] = sqrt(B[k]) + // a[k+1] = a[k]^2 + // B[k+1] = 2(A[k+1]-S[k+1]) + // D[k+1] = D[k] - 2^k(A[k+1]-B[k+1]) + // Stop when |A[k]-B[k]| <= 2^(k-p) + // and PI = B[k]/D[k] + + unsigned k = 1; + + do + { + eval_add(result, A, B); + eval_ldexp(result, result, -2); + eval_sqrt(b, B); + eval_add(a, b); + eval_ldexp(a, a, -1); + eval_multiply(A, a, a); + eval_subtract(B, A, result); + eval_ldexp(B, B, 1); + eval_subtract(result, A, B); + bool neg = eval_get_sign(result) < 0; + if(neg) + result.negate(); + if(result.compare(lim) <= 0) + break; + if(neg) + result.negate(); + eval_ldexp(result, result, k - 1); + eval_subtract(D, result); + ++k; + eval_ldexp(lim, lim, 1); + } + while(true); + + eval_divide(result, B, D); +} + +template +struct constant_initializer +{ + static void do_nothing() + { + init.do_nothing(); + } +private: + struct initializer + { + initializer() + { + F(); + } + void do_nothing()const{} + }; + static const initializer init; +}; + +template +typename constant_initializer::initializer const constant_initializer::init; + +template +const T& get_constant_ln2() +{ + static T result; + static bool b = false; + if(!b) + { + calc_log2(result, boost::multiprecision::detail::digits2 >::value); + b = true; + } + + constant_initializer >::do_nothing(); + + return result; +} + +template +const T& get_constant_e() +{ + static T result; + static bool b = false; + if(!b) + { + calc_e(result, boost::multiprecision::detail::digits2 >::value); + b = true; + } + + constant_initializer >::do_nothing(); + + return result; +} + +template +const T& get_constant_pi() +{ + static T result; + static bool b = false; + if(!b) + { + calc_pi(result, boost::multiprecision::detail::digits2 >::value); + b = true; + } + + constant_initializer >::do_nothing(); + + return result; +} + diff --git a/include/boost/multiprecision/detail/functions/pow.hpp b/include/boost/multiprecision/detail/functions/pow.hpp new file mode 100644 index 00000000..2ed9da1d --- /dev/null +++ b/include/boost/multiprecision/detail/functions/pow.hpp @@ -0,0 +1,667 @@ + +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// +// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp +// + +namespace detail{ + +template +inline void pow_imp(T& result, const T& t, const U& p, const mpl::false_&) +{ + // Compute the pure power of typename T t^p. + // Use the S-and-X binary method, as described in + // D. E. Knuth, "The Art of Computer Programming", Vol. 2, + // Section 4.6.3 . The resulting computational complexity + // is order log2[abs(p)]. + + typedef typename boost::multiprecision::detail::canonical::type int_type; + + // This will store the result. + if(U(p % U(2)) != U(0)) + { + result = t; + } + else + result = int_type(1); + + U p2(p); + + // The variable x stores the binary powers of t. + T x(t); + + while(U(p2 /= 2) != U(0)) + { + // Square x for each binary power. + eval_multiply(x, x); + + const bool has_binary_power = (U(p2 % U(2)) != U(0)); + + if(has_binary_power) + { + // Multiply the result with each binary power contained in the exponent. + eval_multiply(result, x); + } + } +} + +template +inline void pow_imp(T& result, const T& t, const U& p, const mpl::true_&) +{ + // Signed integer power, just take care of the sign then call the unsigned version: + typedef typename boost::multiprecision::detail::canonical::type int_type; + typedef typename make_unsigned::type ui_type; + + if(p < 0) + { + T temp; + temp = static_cast(1); + T denom; + pow_imp(denom, t, static_cast(-p), mpl::false_()); + eval_divide(result, temp, denom); + return; + } + pow_imp(result, t, static_cast(p), mpl::false_()); +} + +} // namespace detail + +template +inline typename enable_if >::type eval_pow(T& result, const T& t, const U& p) +{ + detail::pow_imp(result, t, p, boost::is_signed()); +} + +template +void hyp0F0(T& H0F0, const T& x) +{ + // Compute the series representation of Hypergeometric0F0 taken from + // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F0/06/01/ + // There are no checks on input range or parameter boundaries. + + typedef typename mpl::front::type ui_type; + + BOOST_ASSERT(&H0F0 != &x); + long tol = boost::multiprecision::detail::digits2 >::value; + T t; + + T x_pow_n_div_n_fact(x); + + eval_add(H0F0, x_pow_n_div_n_fact, ui_type(1)); + + T lim; + eval_ldexp(lim, H0F0, 1 - tol); + if(eval_get_sign(lim) < 0) + lim.negate(); + + ui_type n; + + // Series expansion of hyperg_0f0(; ; x). + for(n = 2; n < 300; ++n) + { + eval_multiply(x_pow_n_div_n_fact, x); + eval_divide(x_pow_n_div_n_fact, n); + eval_add(H0F0, x_pow_n_div_n_fact); + bool neg = eval_get_sign(x_pow_n_div_n_fact) < 0; + if(neg) + x_pow_n_div_n_fact.negate(); + if(lim.compare(x_pow_n_div_n_fact) > 0) + break; + if(neg) + x_pow_n_div_n_fact.negate(); + } + if(n >= 300) + BOOST_THROW_EXCEPTION(std::runtime_error("H0F0 failed to converge")); +} + +template +void hyp1F0(T& H1F0, const T& a, const T& x) +{ + // Compute the series representation of Hypergeometric1F0 taken from + // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric1F0/06/01/01/ + // and also see the corresponding section for the power function (i.e. x^a). + // There are no checks on input range or parameter boundaries. + + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + BOOST_ASSERT(&H1F0 != &x); + BOOST_ASSERT(&H1F0 != &a); + + T x_pow_n_div_n_fact(x); + T pochham_a (a); + T ap (a); + + eval_multiply(H1F0, pochham_a, x_pow_n_div_n_fact); + eval_add(H1F0, si_type(1)); + T lim; + eval_ldexp(lim, H1F0, 1 - boost::multiprecision::detail::digits2 >::value); + if(eval_get_sign(lim) < 0) + lim.negate(); + + si_type n; + T term, part; + + // Series expansion of hyperg_1f0(a; ; x). + for(n = 2; n < boost::multiprecision::detail::digits2 >::value + 10; n++) + { + eval_multiply(x_pow_n_div_n_fact, x); + eval_divide(x_pow_n_div_n_fact, n); + eval_increment(ap); + eval_multiply(pochham_a, ap); + eval_multiply(term, pochham_a, x_pow_n_div_n_fact); + eval_add(H1F0, term); + if(eval_get_sign(term) < 0) + term.negate(); + if(lim.compare(term) >= 0) + break; + } + if(n >= boost::multiprecision::detail::digits2 >::value + 10) + BOOST_THROW_EXCEPTION(std::runtime_error("H1F0 failed to converge")); +} + +template +void eval_exp(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The exp function is only valid for floating point types."); + if(&x == &result) + { + T temp; + eval_exp(temp, x); + result = temp; + return; + } + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename boost::multiprecision::detail::canonical::type float_type; + + // Handle special arguments. + int type = eval_fpclassify(x); + bool isneg = eval_get_sign(x) < 0; + if(type == FP_NAN) + { + result = std::numeric_limits >::quiet_NaN().backend(); + return; + } + else if(type == FP_INFINITE) + { + result = x; + if(isneg) + result = ui_type(0u); + else + result = x; + return; + } + else if(type == FP_ZERO) + { + result = ui_type(1); + return; + } + + // Get local copy of argument and force it to be positive. + T xx = x; + T exp_series; + if(isneg) + xx.negate(); + + // Check the range of the argument. + static const canonical_exp_type maximum_arg_for_exp = std::numeric_limits >::max_exponent == 0 ? (std::numeric_limits::max)() : std::numeric_limits >::max_exponent; + + if(xx.compare(maximum_arg_for_exp) >= 0) + { + // Overflow / underflow + if(isneg) + result = ui_type(0); + else + result = std::numeric_limits >::has_infinity ? std::numeric_limits >::infinity().backend() : (std::numeric_limits >::max)().backend(); + return; + } + if(xx.compare(si_type(1)) <= 0) + { + // + // Use series for exp(x) - 1: + // + T lim = std::numeric_limits >::epsilon().backend(); + unsigned k = 2; + exp_series = xx; + result = si_type(1); + if(isneg) + eval_subtract(result, exp_series); + else + eval_add(result, exp_series); + eval_multiply(exp_series, xx); + eval_divide(exp_series, ui_type(k)); + eval_add(result, exp_series); + while(exp_series.compare(lim) > 0) + { + ++k; + eval_multiply(exp_series, xx); + eval_divide(exp_series, ui_type(k)); + if(isneg && (k&1)) + eval_subtract(result, exp_series); + else + eval_add(result, exp_series); + } + return; + } + + // Check for pure-integer arguments which can be either signed or unsigned. + typename boost::multiprecision::detail::canonical::type ll; + eval_trunc(exp_series, x); + eval_convert_to(&ll, exp_series); + if(x.compare(ll) == 0) + { + detail::pow_imp(result, get_constant_e(), ll, mpl::true_()); + return; + } + + // The algorithm for exp has been taken from MPFUN. + // exp(t) = [ (1 + r + r^2/2! + r^3/3! + r^4/4! ...)^p2 ] * 2^n + // where p2 is a power of 2 such as 2048, r = t_prime / p2, and + // t_prime = t - n*ln2, with n chosen to minimize the absolute + // value of t_prime. In the resulting Taylor series, which is + // implemented as a hypergeometric function, |r| is bounded by + // ln2 / p2. For small arguments, no scaling is done. + + // Compute the exponential series of the (possibly) scaled argument. + + eval_divide(result, xx, get_constant_ln2()); + exp_type n; + eval_convert_to(&n, result); + + // The scaling is 2^11 = 2048. + static const si_type p2 = static_cast(si_type(1) << 11); + + eval_multiply(exp_series, get_constant_ln2(), static_cast(n)); + eval_subtract(exp_series, xx); + eval_divide(exp_series, p2); + exp_series.negate(); + hyp0F0(result, exp_series); + + detail::pow_imp(exp_series, result, p2, mpl::true_()); + result = ui_type(1); + eval_ldexp(result, result, n); + eval_multiply(exp_series, result); + + if(isneg) + eval_divide(result, ui_type(1), exp_series); + else + result = exp_series; +} + +template +void eval_log(T& result, const T& arg) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The log function is only valid for floating point types."); + // + // We use a variation of http://dlmf.nist.gov/4.45#i + // using frexp to reduce the argument to x * 2^n, + // then let y = x - 1 and compute: + // log(x) = log(2) * n + log1p(1 + y) + // + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + exp_type e; + T t; + eval_frexp(t, arg, &e); + bool alternate = false; + + if(t.compare(fp_type(2) / fp_type(3)) <= 0) + { + alternate = true; + eval_ldexp(t, t, 1); + --e; + } + + eval_multiply(result, get_constant_ln2(), canonical_exp_type(e)); + INSTRUMENT_BACKEND(result); + eval_subtract(t, ui_type(1)); /* -0.3 <= t <= 0.3 */ + if(!alternate) + t.negate(); /* 0 <= t <= 0.33333 */ + T pow = t; + T lim; + T t2; + + if(alternate) + eval_add(result, t); + else + eval_subtract(result, t); + + eval_multiply(lim, result, std::numeric_limits >::epsilon().backend()); + if(eval_get_sign(lim) < 0) + lim.negate(); + INSTRUMENT_BACKEND(lim); + + ui_type k = 1; + do + { + ++k; + eval_multiply(pow, t); + eval_divide(t2, pow, k); + INSTRUMENT_BACKEND(t2); + if(alternate && ((k & 1) != 0)) + eval_add(result, t2); + else + eval_subtract(result, t2); + INSTRUMENT_BACKEND(result); + }while(lim.compare(t2) < 0); +} + +template +const T& get_constant_log10() +{ + static T result; + static bool b = false; + if(!b) + { + typedef typename boost::multiprecision::detail::canonical::type ui_type; + T ten; + ten = ui_type(10u); + eval_log(result, ten); + } + + constant_initializer >::do_nothing(); + + return result; +} + +template +void eval_log10(T& result, const T& arg) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The log10 function is only valid for floating point types."); + eval_log(result, arg); + eval_divide(result, get_constant_log10()); +} + +template +inline void eval_pow(T& result, const T& x, const T& a) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The pow function is only valid for floating point types."); + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + if((&result == &x) || (&result == &a)) + { + T t; + eval_pow(t, x, a); + result = t; + } + + if(a.compare(si_type(1)) == 0) + { + result = x; + return; + } + + int type = eval_fpclassify(x); + + switch(type) + { + case FP_INFINITE: + result = x; + return; + case FP_ZERO: + result = si_type(1); + return; + case FP_NAN: + result = x; + return; + default: ; + } + + if(eval_get_sign(a) == 0) + { + result = si_type(1); + return; + } + + if(a.compare(si_type(-1)) < 0) + { + T t, da; + t = a; + t.negate(); + eval_pow(da, x, t); + eval_divide(result, si_type(1), da); + return; + } + + bool bo_a_isint = false; + typename boost::multiprecision::detail::canonical::type an; + T fa; + try + { + eval_convert_to(&an, a); + if(a.compare(an) == 0) + { + detail::pow_imp(result, x, an, mpl::true_()); + return; + } + } + catch(const std::exception&) + { + // conversion failed, just fall through, value is not an integer. + an = (std::numeric_limits::max)(); + } + + if((eval_get_sign(x) < 0) && !bo_a_isint) + { + result = std::numeric_limits >::quiet_NaN().backend(); + } + + T t, da; + + eval_subtract(da, a, an); + + if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0)) + { + if(a.compare(fp_type(1e-5f)) <= 0) + { + // Series expansion for small a. + eval_log(t, x); + eval_multiply(t, a); + hyp0F0(result, t); + return; + } + else + { + // Series expansion for moderately sized x. Note that for large power of a, + // the power of the integer part of a is calculated using the pown function. + if(an) + { + da.negate(); + t = si_type(1); + eval_subtract(t, x); + hyp1F0(result, da, t); + detail::pow_imp(t, x, an, mpl::true_()); + eval_multiply(result, t); + } + else + { + da = a; + da.negate(); + t = si_type(1); + eval_subtract(t, x); + hyp1F0(result, da, t); + } + } + } + else + { + // Series expansion for pow(x, a). Note that for large power of a, the power + // of the integer part of a is calculated using the pown function. + if(an) + { + eval_log(t, x); + eval_multiply(t, da); + eval_exp(result, t); + detail::pow_imp(t, x, an, mpl::true_()); + eval_multiply(result, t); + } + else + { + eval_log(t, x); + eval_multiply(t, a); + eval_exp(result, t); + } + } +} + +template +inline typename enable_if, void>::type eval_pow(T& result, const T& x, const A& a) +{ + // Note this one is resticted to float arguments since pow.hpp already has a version for + // integer powers.... + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = a; + eval_pow(result, x, c); +} + +template +inline typename enable_if, void>::type eval_pow(T& result, const A& x, const T& a) +{ + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = x; + eval_pow(result, c, a); +} + +namespace detail{ + + template + void small_sinh_series(T x, T& result) + { + typedef typename boost::multiprecision::detail::canonical::type ui_type; + bool neg = eval_get_sign(x) < 0; + if(neg) + x.negate(); + T p(x); + T mult(x); + eval_multiply(mult, x); + result = x; + ui_type k = 1; + + T lim(x); + eval_ldexp(lim, lim, 1 - boost::multiprecision::detail::digits2 >::value); + + do + { + eval_multiply(p, mult); + eval_divide(p, ++k); + eval_divide(p, ++k); + eval_add(result, p); + }while(p.compare(lim) >= 0); + if(neg) + result.negate(); + } + + template + void sinhcosh(const T& x, T* p_sinh, T* p_cosh) + { + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + switch(eval_fpclassify(x)) + { + case FP_NAN: + case FP_INFINITE: + if(p_sinh) + *p_sinh = x; + if(p_cosh) + { + *p_cosh = x; + if(eval_get_sign(x) < 0) + p_cosh->negate(); + } + return; + case FP_ZERO: + if(p_sinh) + *p_sinh = x; + if(p_cosh) + *p_cosh = ui_type(1); + return; + default: ; + } + + bool small_sinh = eval_get_sign(x) < 0 ? x.compare(fp_type(-0.5)) > 0 : x.compare(fp_type(0.5)) < 0; + + if(p_cosh || !small_sinh) + { + T e_px, e_mx; + eval_exp(e_px, x); + eval_divide(e_mx, ui_type(1), e_px); + + if(p_sinh) + { + if(small_sinh) + { + small_sinh_series(x, *p_sinh); + } + else + { + eval_subtract(*p_sinh, e_px, e_mx); + eval_ldexp(*p_sinh, *p_sinh, -1); + } + } + if(p_cosh) + { + eval_add(*p_cosh, e_px, e_mx); + eval_ldexp(*p_cosh, *p_cosh, -1); + } + } + else + { + small_sinh_series(x, *p_sinh); + } + } + +} // namespace detail + +template +inline void eval_sinh(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The sinh function is only valid for floating point types."); + detail::sinhcosh(x, &result, static_cast(0)); +} + +template +inline void eval_cosh(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The cosh function is only valid for floating point types."); + detail::sinhcosh(x, static_cast(0), &result); +} + +template +inline void eval_tanh(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The tanh function is only valid for floating point types."); + T c; + detail::sinhcosh(x, &result, &c); + eval_divide(result, c); +} + diff --git a/include/boost/multiprecision/detail/functions/trig.hpp b/include/boost/multiprecision/detail/functions/trig.hpp new file mode 100644 index 00000000..e4086427 --- /dev/null +++ b/include/boost/multiprecision/detail/functions/trig.hpp @@ -0,0 +1,788 @@ + +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 +// +// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp +// + +template +void hyp0F1(T& result, const T& b, const T& x) +{ + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + // Compute the series representation of Hypergeometric0F1 taken from + // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F1/06/01/01/ + // There are no checks on input range or parameter boundaries. + + T x_pow_n_div_n_fact(x); + T pochham_b (b); + T bp (b); + + eval_divide(result, x_pow_n_div_n_fact, pochham_b); + eval_add(result, ui_type(1)); + + si_type n; + + T tol; + tol = ui_type(1); + eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2 >::value); + eval_multiply(tol, result); + if(eval_get_sign(tol) < 0) + tol.negate(); + T term; + + // Series expansion of hyperg_0f1(; b; x). + for(n = 2; n < 300; ++n) + { + eval_multiply(x_pow_n_div_n_fact, x); + eval_divide(x_pow_n_div_n_fact, n); + eval_increment(bp); + eval_multiply(pochham_b, bp); + + eval_divide(term, x_pow_n_div_n_fact, pochham_b); + eval_add(result, term); + + bool neg_term = eval_get_sign(term) < 0; + if(neg_term) + term.negate(); + if(term.compare(tol) <= 0) + break; + } + + if(n >= 300) + BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge")); +} + + +template +void eval_sin(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The sin function is only valid for floating point types."); + if(&result == &x) + { + T temp; + eval_sin(temp, x); + result = temp; + return; + } + + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + switch(eval_fpclassify(x)) + { + case FP_INFINITE: + case FP_NAN: + result = std::numeric_limits >::quiet_NaN().backend(); + return; + case FP_ZERO: + result = ui_type(0); + return; + default: ; + } + + // Local copy of the argument + T xx = x; + + // Analyze and prepare the phase of the argument. + // Make a local, positive copy of the argument, xx. + // The argument xx will be reduced to 0 <= xx <= pi/2. + bool b_negate_sin = false; + + if(eval_get_sign(x) < 0) + { + xx.negate(); + b_negate_sin = !b_negate_sin; + } + + T n_pi, t; + // Remove even multiples of pi. + if(xx.compare(get_constant_pi()) > 0) + { + eval_divide(n_pi, xx, get_constant_pi()); + eval_trunc(n_pi, n_pi); + t = ui_type(2); + eval_fmod(t, n_pi, t); + const bool b_n_pi_is_even = eval_get_sign(t) == 0; + eval_multiply(n_pi, get_constant_pi()); + eval_subtract(xx, n_pi); + + BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); + BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific)); + + // Adjust signs if the multiple of pi is not even. + if(!b_n_pi_is_even) + { + b_negate_sin = !b_negate_sin; + } + } + + // Reduce the argument to 0 <= xx <= pi/2. + eval_ldexp(t, get_constant_pi(), -1); + if(xx.compare(t) > 0) + { + eval_subtract(xx, get_constant_pi(), xx); + BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); + } + + eval_subtract(t, xx); + const bool b_zero = eval_get_sign(xx) == 0; + const bool b_pi_half = eval_get_sign(t) == 0; + + // Check if the reduced argument is very close to 0 or pi/2. + const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0; + const bool b_near_pi_half = t.compare(fp_type(1e-1)) < 0;; + + if(b_zero) + { + result = ui_type(0); + } + else if(b_pi_half) + { + result = ui_type(1); + } + else if(b_near_zero) + { + eval_multiply(t, xx, xx); + eval_divide(t, si_type(-4)); + T t2; + t2 = fp_type(1.5); + hyp0F1(result, t2, t); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + eval_multiply(result, xx); + } + else if(b_near_pi_half) + { + eval_multiply(t, t); + eval_divide(t, si_type(-4)); + T t2; + t2 = fp_type(0.5); + hyp0F1(result, t2, t); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + } + else + { + // Scale to a small argument for an efficient Taylor series, + // implemented as a hypergeometric function. Use a standard + // divide by three identity a certain number of times. + // Here we use division by 3^9 --> (19683 = 3^9). + + static const si_type n_scale = 9; + static const si_type n_three_pow_scale = static_cast(19683L); + + eval_divide(xx, n_three_pow_scale); + + // Now with small arguments, we are ready for a series expansion. + eval_multiply(t, xx, xx); + eval_divide(t, si_type(-4)); + T t2; + t2 = fp_type(1.5); + hyp0F1(result, t2, t); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + eval_multiply(result, xx); + + // Convert back using multiple angle identity. + for(boost::int32_t k = static_cast(0); k < n_scale; k++) + { + // Rescale the cosine value using the multiple angle identity. + eval_multiply(t2, result, ui_type(3)); + eval_multiply(t, result, result); + eval_multiply(t, result); + eval_multiply(t, ui_type(4)); + eval_subtract(result, t2, t); + } + } + + if(b_negate_sin) + result.negate(); +} + +template +void eval_cos(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The cos function is only valid for floating point types."); + if(&result == &x) + { + T temp; + eval_sin(temp, x); + result = temp; + return; + } + + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + switch(eval_fpclassify(x)) + { + case FP_INFINITE: + case FP_NAN: + result = std::numeric_limits >::quiet_NaN().backend(); + return; + case FP_ZERO: + result = ui_type(1); + return; + default: ; + } + + // Local copy of the argument + T xx = x; + + // Analyze and prepare the phase of the argument. + // Make a local, positive copy of the argument, xx. + // The argument xx will be reduced to 0 <= xx <= pi/2. + bool b_negate_cos = false; + + if(eval_get_sign(x) < 0) + { + xx.negate(); + } + + T n_pi, t; + // Remove even multiples of pi. + if(xx.compare(get_constant_pi()) > 0) + { + eval_divide(t, xx, get_constant_pi()); + eval_trunc(n_pi, t); + BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific)); + eval_multiply(t, n_pi, get_constant_pi()); + BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific)); + eval_subtract(xx, t); + BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); + + // Adjust signs if the multiple of pi is not even. + t = ui_type(2); + eval_fmod(t, n_pi, t); + const bool b_n_pi_is_even = eval_get_sign(t) == 0; + + if(!b_n_pi_is_even) + { + b_negate_cos = !b_negate_cos; + } + } + + // Reduce the argument to 0 <= xx <= pi/2. + eval_ldexp(t, get_constant_pi(), -1); + int com = xx.compare(t); + if(com > 0) + { + eval_subtract(xx, get_constant_pi(), xx); + b_negate_cos = !b_negate_cos; + BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); + } + + const bool b_zero = eval_get_sign(xx) == 0; + const bool b_pi_half = com == 0; + + // Check if the reduced argument is very close to 0 or pi/2. + const bool b_near_zero = xx.compare(fp_type(1e-4)) < 0; + eval_subtract(t, xx); + const bool b_near_pi_half = t.compare(fp_type(1e-4)) < 0; + + if(b_zero) + { + result = si_type(1); + } + else if(b_pi_half) + { + result = si_type(0); + } + else if(b_near_zero) + { + eval_multiply(t, xx, xx); + eval_divide(t, si_type(-4)); + n_pi = fp_type(0.5f); + hyp0F1(result, n_pi, t); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + } + else if(b_near_pi_half) + { + T t2(t); + eval_multiply(t, t); + eval_divide(t, si_type(-4)); + n_pi = fp_type(1.5f); + hyp0F1(result, n_pi, t); + eval_multiply(result, t2); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + } + else + { + // Scale to a small argument for an efficient Taylor series, + // implemented as a hypergeometric function. Use a standard + // divide by three identity a certain number of times. + // Here we use division by 3^9 --> (19683 = 3^9). + + static const ui_type n_scale = 9; + static const ui_type n_three_pow_scale = 19683; + eval_divide(xx, n_three_pow_scale); + + eval_multiply(t, xx, xx); + eval_divide(t, si_type(-4)); + n_pi = fp_type(0.5f); + + // Now with small arguments, we are ready for a series expansion. + hyp0F1(result, n_pi, t); + BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific)); + + // Convert back using multiple angle identity. + for(ui_type k = 0; k < n_scale; k++) + { + eval_multiply(t, result, result); + eval_multiply(t, result); + eval_multiply(t, ui_type(4)); + eval_multiply(result, si_type(-3)); + eval_add(result, t); + } + } + if(b_negate_cos) + result.negate(); +} + +template +void eval_tan(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The tan function is only valid for floating point types."); + T t; + eval_sin(result, x); + eval_cos(t, x); + eval_divide(result, t); +} + +template +void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x) +{ + // Compute the series representation of hyperg_2f1 taken from + // Abramowitz and Stegun 15.1.1. + // There are no checks on input range or parameter boundaries. + + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + T x_pow_n_div_n_fact(x); + T pochham_a (a); + T pochham_b (b); + T pochham_c (c); + T ap (a); + T bp (b); + T cp (c); + + eval_multiply(result, pochham_a, pochham_b); + eval_divide(result, pochham_c); + eval_multiply(result, x_pow_n_div_n_fact); + eval_add(result, ui_type(1)); + + T lim; + eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2 >::value); + + if(eval_get_sign(lim) < 0) + lim.negate(); + + ui_type n; + T term; + + // Series expansion of hyperg_2f1(a, b; c; x). + for(n = 2; n < 300; ++n) + { + eval_multiply(x_pow_n_div_n_fact, x); + eval_divide(x_pow_n_div_n_fact, n); + + eval_increment(ap); + eval_multiply(pochham_a, ap); + eval_increment(bp); + eval_multiply(pochham_b, bp); + eval_increment(cp); + eval_multiply(pochham_c, cp); + + eval_multiply(term, pochham_a, pochham_b); + eval_divide(term, pochham_c); + eval_multiply(term, x_pow_n_div_n_fact); + eval_add(result, term); + + if(eval_get_sign(term) < 0) + term.negate(); + if(lim.compare(term) >= 0) + break; + } + if(n > 300) + BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge.")); +} + +template +void eval_asin(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The asin function is only valid for floating point types."); + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + if(&result == &x) + { + T t(x); + eval_asin(result, t); + return; + } + + switch(eval_fpclassify(x)) + { + case FP_NAN: + case FP_INFINITE: + result = std::numeric_limits >::quiet_NaN().backend(); + return; + case FP_ZERO: + result = ui_type(0); + return; + default: ; + } + + const bool b_neg = eval_get_sign(x) < 0; + + T xx(x); + if(b_neg) + xx.negate(); + + int c = xx.compare(ui_type(1)); + if(c > 0) + { + result = std::numeric_limits >::quiet_NaN().backend(); + return; + } + else if(c == 0) + { + result = get_constant_pi(); + eval_ldexp(result, result, -1); + if(b_neg) + result.negate(); + return; + } + + if(xx.compare(fp_type(1e-4)) < 0) + { + // http://functions.wolfram.com/ElementaryFunctions/ArcSin/26/01/01/ + eval_multiply(xx, xx); + T t1, t2; + t1 = fp_type(0.5f); + t2 = fp_type(1.5f); + hyp2F1(result, t1, t1, t2, xx); + eval_multiply(result, x); + return; + } + else if(xx.compare(fp_type(1 - 1e-4f)) > 0) + { + T dx1; + T t1, t2; + eval_subtract(dx1, ui_type(1), xx); + t1 = fp_type(0.5f); + t2 = fp_type(1.5f); + eval_ldexp(dx1, dx1, -1); + hyp2F1(result, t1, t1, t2, dx1); + eval_ldexp(dx1, dx1, 2); + eval_sqrt(t1, dx1); + eval_multiply(result, t1); + eval_ldexp(t1, get_constant_pi(), -1); + result.negate(); + eval_add(result, t1); + if(b_neg) + result.negate(); + return; + } + + // Get initial estimate using standard math function asin. + double dd; + eval_convert_to(&dd, xx); + + result = fp_type(std::asin(dd)); + + // Newton-Raphson iteration + while(true) + { + T s, c; + eval_sin(s, result); + eval_cos(c, result); + eval_subtract(s, xx); + eval_divide(s, c); + eval_subtract(result, s); + + T lim; + eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2 >::value); + if(eval_get_sign(s) < 0) + s.negate(); + if(eval_get_sign(lim) < 0) + lim.negate(); + if(lim.compare(s) >= 0) + break; + } + if(b_neg) + result.negate(); +} + +template +inline void eval_acos(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The acos function is only valid for floating point types."); + typedef typename boost::multiprecision::detail::canonical::type ui_type; + + switch(eval_fpclassify(x)) + { + case FP_NAN: + case FP_INFINITE: + result = std::numeric_limits >::quiet_NaN().backend(); + return; + case FP_ZERO: + result = get_constant_pi(); + eval_ldexp(result, result, -1); // divide by two. + return; + } + + eval_abs(result, x); + int c = result.compare(ui_type(1)); + + if(c > 0) + { + result = std::numeric_limits >::quiet_NaN().backend(); + return; + } + else if(c == 0) + { + if(eval_get_sign(x) < 0) + result = get_constant_pi(); + else + result = ui_type(0); + return; + } + + eval_asin(result, x); + T t; + eval_ldexp(t, get_constant_pi(), -1); + eval_subtract(result, t); + result.negate(); +} + +template +void eval_atan(T& result, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The atan function is only valid for floating point types."); + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + switch(eval_fpclassify(x)) + { + case FP_NAN: + result = std::numeric_limits >::quiet_NaN().backend(); + return; + case FP_ZERO: + result = ui_type(0); + return; + case FP_INFINITE: + if(eval_get_sign(x) < 0) + { + eval_ldexp(result, get_constant_pi(), -1); + result.negate(); + } + else + eval_ldexp(result, get_constant_pi(), -1); + return; + default: ; + } + + const bool b_neg = eval_get_sign(x) < 0; + + T xx(x); + if(b_neg) + xx.negate(); + + if(xx.compare(fp_type(0.1)) < 0) + { + T t1, t2, t3; + t1 = ui_type(1); + t2 = fp_type(0.5f); + t3 = fp_type(1.5f); + eval_multiply(xx, xx); + xx.negate(); + hyp2F1(result, t1, t2, t3, xx); + eval_multiply(result, x); + return; + } + + if(xx.compare(fp_type(10)) > 0) + { + T t1, t2, t3; + t1 = fp_type(0.5f); + t2 = ui_type(1u); + t3 = fp_type(1.5f); + eval_multiply(xx, xx); + eval_divide(xx, si_type(-1), xx); + hyp2F1(result, t1, t2, t3, xx); + eval_divide(result, x); + if(!b_neg) + result.negate(); + eval_ldexp(t1, get_constant_pi(), -1); + eval_add(result, t1); + if(b_neg) + result.negate(); + return; + } + + + // Get initial estimate using standard math function atan. + fp_type d; + eval_convert_to(&d, xx); + result = fp_type(std::atan(d)); + + // Newton-Raphson iteration + static const boost::int32_t double_digits10_minus_a_few = std::numeric_limits::digits10 - 3; + + T s, c, t; + for(boost::int32_t digits = double_digits10_minus_a_few; digits <= std::numeric_limits >::digits10; digits *= 2) + { + eval_sin(s, result); + eval_cos(c, result); + eval_multiply(t, xx, c); + eval_subtract(t, s); + eval_multiply(s, t, c); + eval_add(result, s); + } + if(b_neg) + result.negate(); +} + +template +void eval_atan2(T& result, const T& y, const T& x) +{ + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_floating_point, "The atan2 function is only valid for floating point types."); + if(&result == &y) + { + T temp(y); + eval_atan2(result, temp, x); + return; + } + else if(&result == &x) + { + T temp(x); + eval_atan2(result, y, temp); + return; + } + + typedef typename boost::multiprecision::detail::canonical::type si_type; + typedef typename boost::multiprecision::detail::canonical::type ui_type; + typedef typename T::exponent_type exp_type; + typedef typename boost::multiprecision::detail::canonical::type canonical_exp_type; + typedef typename mpl::front::type fp_type; + + switch(eval_fpclassify(y)) + { + case FP_NAN: + result = y; + return; + case FP_ZERO: + { + int c = eval_get_sign(x); + if(c < 0) + result = get_constant_pi(); + else if(c >= 0) + result = ui_type(0); // Note we allow atan2(0,0) to be zero, even though it's mathematically undefined + return; + } + case FP_INFINITE: + { + if(eval_fpclassify(x) == FP_INFINITE) + { + result = std::numeric_limits >::quiet_NaN().backend(); + } + else + { + eval_ldexp(result, get_constant_pi(), -1); + if(eval_get_sign(y) < 0) + result.negate(); + } + return; + } + } + + switch(eval_fpclassify(x)) + { + case FP_NAN: + result = x; + return; + case FP_ZERO: + { + eval_ldexp(result, get_constant_pi(), -1); + if(eval_get_sign(y) < 0) + result.negate(); + return; + } + case FP_INFINITE: + if(eval_get_sign(x) > 0) + result = ui_type(0); + else + result = get_constant_pi(); + if(eval_get_sign(y) < 0) + result.negate(); + return; + } + + T xx; + eval_divide(xx, y, x); + if(eval_get_sign(xx) < 0) + xx.negate(); + + eval_atan(result, xx); + + // Determine quadrant (sign) based on signs of x, y + const bool y_neg = eval_get_sign(y) < 0; + const bool x_neg = eval_get_sign(x) < 0; + + if(y_neg != x_neg) + result.negate(); + + if(x_neg) + { + if(y_neg) + eval_subtract(result, get_constant_pi()); + else + eval_add(result, get_constant_pi()); + } +} +template +inline typename enable_if, void>::type eval_atan2(T& result, const T& x, const A& a) +{ + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = a; + eval_atan2(result, x, c); +} + +template +inline typename enable_if, void>::type eval_atan2(T& result, const A& x, const T& a) +{ + typedef typename boost::multiprecision::detail::canonical::type canonical_type; + typedef typename mpl::if_, T, canonical_type>::type cast_type; + cast_type c; + c = x; + eval_atan2(result, c, a); +} + diff --git a/include/boost/multiprecision/detail/generic_interconvert.hpp b/include/boost/multiprecision/detail/generic_interconvert.hpp new file mode 100644 index 00000000..63ec0191 --- /dev/null +++ b/include/boost/multiprecision/detail/generic_interconvert.hpp @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_GENERIC_INTERCONVERT_HPP +#define BOOST_MP_GENERIC_INTERCONVERT_HPP + +#include + +namespace boost{ namespace multiprecision{ namespace detail{ + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + using default_ops::eval_get_sign; + using default_ops::eval_bitwise_and; + using default_ops::eval_convert_to; + using default_ops::eval_right_shift; + using default_ops::eval_ldexp; + using default_ops::eval_add; + // smallest unsigned type handled natively by "From" is likely to be it's limb_type: + typedef typename canonical::type limb_type; + // get the corresponding type that we can assign to "To": + typedef typename canonical::type to_type; + From t(from); + bool is_neg = eval_get_sign(t) < 0; + if(is_neg) + t.negate(); + // Pick off the first limb: + limb_type limb; + limb_type mask = ~static_cast(0); + From fl; + eval_bitwise_and(fl, t, mask); + eval_convert_to(&limb, fl); + to = static_cast(limb); + eval_right_shift(t, std::numeric_limits::digits); + // + // Then keep picking off more limbs until "t" is zero: + // + To l; + unsigned shift = std::numeric_limits::digits; + while(!eval_is_zero(t)) + { + eval_bitwise_and(fl, t, mask); + eval_convert_to(&limb, fl); + l = static_cast(limb); + eval_right_shift(t, std::numeric_limits::digits); + eval_ldexp(l, l, shift); + eval_add(to, l); + shift += std::numeric_limits::digits; + } + // + // Finish off by setting the sign: + // + if(is_neg) + to.negate(); +} + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + using default_ops::eval_get_sign; + using default_ops::eval_bitwise_and; + using default_ops::eval_convert_to; + using default_ops::eval_right_shift; + using default_ops::eval_left_shift; + using default_ops::eval_bitwise_or; + using default_ops::eval_is_zero; + // smallest unsigned type handled natively by "From" is likely to be it's limb_type: + typedef typename canonical::type limb_type; + // get the corresponding type that we can assign to "To": + typedef typename canonical::type to_type; + From t(from); + bool is_neg = eval_get_sign(t) < 0; + if(is_neg) + t.negate(); + // Pick off the first limb: + limb_type limb; + limb_type mask = static_cast(~static_cast(0)); + From fl; + eval_bitwise_and(fl, t, mask); + eval_convert_to(&limb, fl); + to = static_cast(limb); + eval_right_shift(t, std::numeric_limits::digits); + // + // Then keep picking off more limbs until "t" is zero: + // + To l; + unsigned shift = std::numeric_limits::digits; + while(!eval_is_zero(t)) + { + eval_bitwise_and(fl, t, mask); + eval_convert_to(&limb, fl); + l = static_cast(limb); + eval_right_shift(t, std::numeric_limits::digits); + eval_left_shift(l, shift); + eval_bitwise_or(to, l); + shift += std::numeric_limits::digits; + } + // + // Finish off by setting the sign: + // + if(is_neg) + to.negate(); +} + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // The code here only works when the radix of "From" is 2, we could try shifting by other + // radixes but it would complicate things.... use a string convertion when the radix is other + // than 2: + // + if(std::numeric_limits >::radix != 2) + { + to = from.str(0, std::ios_base::fmtflags()).c_str(); + return; + } + + + typedef typename canonical::type ui_type; + + using default_ops::eval_fpclassify; + using default_ops::eval_add; + using default_ops::eval_subtract; + using default_ops::eval_convert_to; + + // + // First classify the input, then handle the special cases: + // + int c = eval_fpclassify(from); + + if(c == FP_ZERO) + { + to = ui_type(0); + return; + } + else if(c == FP_NAN) + { + to = "nan"; + return; + } + else if(c == FP_INFINITE) + { + to = "inf"; + if(eval_get_sign(from) < 0) + to.negate(); + return; + } + + typename From::exponent_type e; + From f, term; + to = ui_type(0); + + eval_frexp(f, from, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(!eval_is_zero(f)) + { + // extract int sized bits from f: + eval_ldexp(f, f, shift); + eval_floor(term, f); + e -= shift; + eval_ldexp(to, to, shift); + typename boost::multiprecision::detail::canonical::type ll; + eval_convert_to(&ll, term); + eval_add(to, ll); + eval_subtract(f, term); + } + typedef typename To::exponent_type to_exponent; + if((e > (std::numeric_limits::max)()) || (e < (std::numeric_limits::min)())) + { + to = "inf"; + if(eval_get_sign(from) < 0) + to.negate(); + return; + } + eval_ldexp(to, to, static_cast(e)); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + typedef typename component_type >::type from_component_type; + typedef typename component_type >::type to_component_type; + + number t(from); + to_component_type n(numerator(t)), d(denominator(t)); + using default_ops::assign_components; + assign_components(to, n.backend(), d.backend()); +} + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + typedef typename component_type >::type to_component_type; + + number t(from); + to_component_type n(t), d(1); + using default_ops::assign_components; + assign_components(to, n.backend(), d.backend()); +} + +template +void generic_interconvert(To& to, const From& from, const mpl::int_& /*to_type*/, const mpl::int_& /*from_type*/) +{ + typedef typename component_type >::type from_component_type; + using default_ops::eval_divide; + + number t(from); + from_component_type n(numerator(t)), d(denominator(t)); + number fn(n), fd(d); + eval_divide(to, fn.backend(), fd.backend()); +} + +}}} // namespaces + +#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP + diff --git a/include/boost/multiprecision/detail/integer_ops.hpp b/include/boost/multiprecision/detail/integer_ops.hpp new file mode 100644 index 00000000..06df91ab --- /dev/null +++ b/include/boost/multiprecision/detail/integer_ops.hpp @@ -0,0 +1,447 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_INT_FUNC_HPP +#define BOOST_MP_INT_FUNC_HPP + +#include + +namespace boost{ namespace multiprecision{ + +namespace default_ops +{ + +template +inline void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r) +{ + eval_divide(q, x, y); + eval_modulus(r, x, y); +} + +template +inline Integer eval_integer_modulus(const Backend& x, Integer val) +{ + BOOST_MP_USING_ABS + using default_ops::eval_modulus; + using default_ops::eval_convert_to; + typedef typename boost::multiprecision::detail::canonical::type int_type; + Backend t; + eval_modulus(t, x, static_cast(val)); + Integer result; + eval_convert_to(&result, t); + return abs(result); +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + +template +inline void eval_gcd(B& result, const B& a, const B& b) +{ + using default_ops::eval_lsb; + using default_ops::eval_is_zero; + using default_ops::eval_get_sign; + + int shift; + + B u(a), v(b); + + int s = eval_get_sign(u); + + /* GCD(0,x) := x */ + if(s < 0) + { + u.negate(); + } + else if(s == 0) + { + result = v; + return; + } + s = eval_get_sign(v); + if(s < 0) + { + v.negate(); + } + else if(s == 0) + { + result = u; + return; + } + + /* Let shift := lg K, where K is the greatest power of 2 + dividing both u and v. */ + + unsigned us = eval_lsb(u); + unsigned vs = eval_lsb(v); + shift = (std::min)(us, vs); + eval_right_shift(u, us); + eval_right_shift(v, vs); + + do + { + /* Now u and v are both odd, so diff(u, v) is even. + Let u = min(u, v), v = diff(u, v)/2. */ + if(u.compare(v) > 0) + u.swap(v); + eval_subtract(v, u); + // Termination condition tries not to do a full compare if possible: + if(eval_is_zero(v)) + break; + vs = eval_lsb(v); + eval_right_shift(v, vs); + } + while(true); + + result = u; + eval_left_shift(result, shift); +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +inline void eval_lcm(B& result, const B& a, const B& b) +{ + typedef typename mpl::front::type ui_type; + B t; + eval_gcd(t, a, b); + + if(eval_is_zero(t)) + { + result = static_cast(0); + } + else + { + eval_divide(result, a, t); + eval_multiply(result, b); + } + if(eval_get_sign(result) < 0) + result.negate(); +} + +} + +template +inline typename enable_if_c::value == number_kind_integer>::type + divide_qr(const number& x, const number& y, + number& q, number& r) +{ + using default_ops::eval_qr; + eval_qr(x.backend(), y.backend(), q.backend(), r.backend()); +} + +template +inline typename enable_if_c::value == number_kind_integer>::type + divide_qr(const number& x, const multiprecision::detail::expression& y, + number& q, number& r) +{ + divide_qr(x, number(y), q, r); +} + +template +inline typename enable_if_c::value == number_kind_integer>::type + divide_qr(const multiprecision::detail::expression& x, const number& y, + number& q, number& r) +{ + divide_qr(number(x), y, q, r); +} + +template +inline typename enable_if_c::value == number_kind_integer>::type + divide_qr(const multiprecision::detail::expression& x, const multiprecision::detail::expression& y, + number& q, number& r) +{ + divide_qr(number(x), number(y), q, r); +} + +template +inline typename enable_if, mpl::bool_::value == number_kind_integer> >, Integer>::type + integer_modulus(const number& x, Integer val) +{ + using default_ops::eval_integer_modulus; + return eval_integer_modulus(x.backend(), val); +} + +template +inline typename enable_if, mpl::bool_::result_type>::value == number_kind_integer> >, Integer>::type + integer_modulus(const multiprecision::detail::expression& x, Integer val) +{ + typedef typename multiprecision::detail::expression::result_type result_type; + return integer_modulus(result_type(x), val); +} + +template +inline typename enable_if_c::value == number_kind_integer, unsigned>::type + lsb(const number& x) +{ + using default_ops::eval_lsb; + return eval_lsb(x.backend()); +} + +template +inline typename enable_if_c::result_type>::value == number_kind_integer, unsigned>::type + lsb(const multiprecision::detail::expression& x) +{ + typedef typename multiprecision::detail::expression::result_type number_type; + number_type n(x); + using default_ops::eval_lsb; + return eval_lsb(n.backend()); +} + +template +inline typename enable_if_c::value == number_kind_integer, bool>::type + bit_test(const number& x, unsigned index) +{ + using default_ops::eval_bit_test; + return eval_bit_test(x.backend(), index); +} + +template +inline typename enable_if_c::result_type>::value == number_kind_integer, bool>::type + bit_test(const multiprecision::detail::expression& x, unsigned index) +{ + typedef typename multiprecision::detail::expression::result_type number_type; + number_type n(x); + using default_ops::eval_bit_test; + return eval_bit_test(n.backend(), index); +} + +template +inline typename enable_if_c::value == number_kind_integer, number&>::type + bit_set(number& x, unsigned index) +{ + using default_ops::eval_bit_set; + eval_bit_set(x.backend(), index); + return x; +} + +template +inline typename enable_if_c::value == number_kind_integer, number&>::type + bit_unset(number& x, unsigned index) +{ + using default_ops::eval_bit_unset; + eval_bit_unset(x.backend(), index); + return x; +} + +template +inline typename enable_if_c::value == number_kind_integer, number&>::type + bit_flip(number& x, unsigned index) +{ + using default_ops::eval_bit_flip; + eval_bit_flip(x.backend(), index); + return x; +} + +namespace detail{ + +// +// Within powm, we need a type with twice as many digits as the argument type, define +// a traits class to obtain that type: +// +template +struct double_precision_type +{ + typedef Backend type; +}; + +// +// Calculate (a^p)%c: +// +template +void eval_powm(Backend& result, const Backend& a, const Backend& p, const Backend& c) +{ + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + + typedef typename double_precision_type::type double_type; + typedef typename canonical::type ui_type; + + double_type x, y(a), b(p), t; + x = ui_type(1u); + + while(eval_get_sign(b) > 0) + { + if(eval_bit_test(b, 0)) + { + eval_multiply(t, x, y); + eval_modulus(x, t, c); + } + eval_multiply(t, y, y); + eval_modulus(y, t, c); + eval_right_shift(b, ui_type(1)); + } + Backend x2(x); + eval_modulus(result, x2, c); +} + +template +void eval_powm(Backend& result, const Backend& a, const Backend& p, Integer c) +{ + typedef typename double_precision_type::type double_type; + typedef typename canonical::type ui_type; + typedef typename canonical::type i1_type; + typedef typename canonical::type i2_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + + if(eval_get_sign(p) < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + + double_type x, y(a), b(p), t; + x = ui_type(1u); + + while(eval_get_sign(b) > 0) + { + if(eval_bit_test(b, 0)) + { + eval_multiply(t, x, y); + eval_modulus(x, t, static_cast(c)); + } + eval_multiply(t, y, y); + eval_modulus(y, t, static_cast(c)); + eval_right_shift(b, ui_type(1)); + } + Backend x2(x); + eval_modulus(result, x2, static_cast(c)); +} + +template +typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c) +{ + typedef typename double_precision_type::type double_type; + typedef typename canonical::type ui_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + + double_type x, y(a), t; + x = ui_type(1u); + + while(b > 0) + { + if(b & 1) + { + eval_multiply(t, x, y); + eval_modulus(x, t, c); + } + eval_multiply(t, y, y); + eval_modulus(y, t, c); + b >>= 1; + } + Backend x2(x); + eval_modulus(result, x2, c); +} + +template +typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer b, const Backend& c) +{ + if(b < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + eval_powm(result, a, static_cast::type>(b), c); +} + +template +typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c) +{ + typedef typename double_precision_type::type double_type; + typedef typename canonical::type ui_type; + typedef typename canonical::type i1_type; + typedef typename canonical::type i2_type; + + using default_ops::eval_bit_test; + using default_ops::eval_get_sign; + using default_ops::eval_multiply; + using default_ops::eval_modulus; + using default_ops::eval_right_shift; + + double_type x, y(a), t; + x = ui_type(1u); + + while(b > 0) + { + if(b & 1) + { + eval_multiply(t, x, y); + eval_modulus(x, t, static_cast(c)); + } + eval_multiply(t, y, y); + eval_modulus(y, t, static_cast(c)); + b >>= 1; + } + Backend x2(x); + eval_modulus(result, x2, static_cast(c)); +} + +template +typename enable_if >::type eval_powm(Backend& result, const Backend& a, Integer1 b, Integer2 c) +{ + if(b < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + eval_powm(result, a, static_cast::type>(b), c); +} + +struct powm_func +{ + template + void operator()(T& result, const T& b, const U& p, const V& m)const + { + eval_powm(result, b, p, m); + } +}; + +} + +template +inline typename enable_if< + mpl::and_< + mpl::bool_::value == number_kind_integer>, + mpl::or_< + is_number, + is_number_expression + >, + mpl::or_< + is_number, + is_number_expression, + is_integral + >, + mpl::or_< + is_number, + is_number_expression, + is_integral + > + >, + detail::expression >::type + powm(const T& b, const U& p, const V& mod) +{ + return detail::expression( + detail::powm_func(), b, p, mod); +} + +}} //namespaces + +#endif + + diff --git a/include/boost/multiprecision/detail/no_et_ops.hpp b/include/boost/multiprecision/detail/no_et_ops.hpp new file mode 100644 index 00000000..1b80da79 --- /dev/null +++ b/include/boost/multiprecision/detail/no_et_ops.hpp @@ -0,0 +1,615 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_NO_ET_OPS_HPP +#define BOOST_MP_NO_ET_OPS_HPP + +namespace boost{ +namespace multiprecision{ + +// +// Operators for non-expression template enabled number. +// NOTE: this is not a complete header - really just a suffix to default_ops.hpp. +// NOTE: these operators have to be defined after the methods in default_ops.hpp. +// +template +BOOST_FORCEINLINE number operator - (const number& v) +{ + BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); + number result(v); + result.backend().negate(); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE number operator ~ (const number& v) +{ + number result; + eval_complement(result.backend(), v.backend()); + return BOOST_MP_MOVE(result); +} +// +// Addition: +// +template +BOOST_FORCEINLINE number operator + (const number& a, const number& b) +{ + number result; + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator + (const number& a, const V& b) +{ + number result; + using default_ops::eval_add; + eval_add(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator + (const V& a, const number& b) +{ + number result; + using default_ops::eval_add; + eval_add(result.backend(), b.backend(), number::canonical_value(a)); + return BOOST_MP_MOVE(result); +} +// +// Subtraction: +// +template +BOOST_FORCEINLINE number operator - (const number& a, const number& b) +{ + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator - (const number& a, const V& b) +{ + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator - (const V& a, const number& b) +{ + number result; + using default_ops::eval_subtract; + eval_subtract(result.backend(), number::canonical_value(a), b.backend()); + return BOOST_MP_MOVE(result); +} +// +// Multiply: +// +template +BOOST_FORCEINLINE number operator * (const number& a, const number& b) +{ + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator * (const number& a, const V& b) +{ + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator * (const V& a, const number& b) +{ + number result; + using default_ops::eval_multiply; + eval_multiply(result.backend(), b.backend(), number::canonical_value(a)); + return BOOST_MP_MOVE(result); +} +// +// divide: +// +template +BOOST_FORCEINLINE number operator / (const number& a, const number& b) +{ + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator / (const number& a, const V& b) +{ + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator / (const V& a, const number& b) +{ + number result; + using default_ops::eval_divide; + eval_divide(result.backend(), number::canonical_value(a), b.backend()); + return BOOST_MP_MOVE(result); +} +// +// modulus: +// +template +BOOST_FORCEINLINE number operator % (const number& a, const number& b) +{ + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator % (const number& a, const V& b) +{ + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator % (const V& a, const number& b) +{ + number result; + using default_ops::eval_modulus; + eval_modulus(result.backend(), number::canonical_value(a), b.backend()); + return BOOST_MP_MOVE(result); +} +// +// Bitwise or: +// +template +BOOST_FORCEINLINE number operator | (const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator | (const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator | (const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_or; + eval_bitwise_or(result.backend(), b.backend(), number::canonical_value(a)); + return BOOST_MP_MOVE(result); +} +// +// Bitwise xor: +// +template +BOOST_FORCEINLINE number operator ^ (const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator ^ (const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator ^ (const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(result.backend(), b.backend(), number::canonical_value(a)); + return BOOST_MP_MOVE(result); +} +// +// Bitwise and: +// +template +BOOST_FORCEINLINE number operator & (const number& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), a.backend(), b.backend()); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator & (const number& a, const V& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), a.backend(), number::canonical_value(b)); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator & (const V& a, const number& b) +{ + number result; + using default_ops::eval_bitwise_and; + eval_bitwise_and(result.backend(), b.backend(), number::canonical_value(a)); + return BOOST_MP_MOVE(result); +} +// +// shifts: +// +template +BOOST_FORCEINLINE typename enable_if, number >::type + operator << (const number& a, const I& b) +{ + number result(a); + using default_ops::eval_left_shift; + detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed()); + eval_left_shift(result.backend(), b); + return BOOST_MP_MOVE(result); +} +template +BOOST_FORCEINLINE typename enable_if, number >::type + operator >> (const number& a, const I& b) +{ + number result(a); + using default_ops::eval_right_shift; + detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed()); + eval_right_shift(result.backend(), b); + return BOOST_MP_MOVE(result); +} + +#ifndef BOOST_NO_RVALUE_REFERENCES +// +// If we have rvalue references go all over again with rvalue ref overloads and move semantics. +// Note that while it would be tempting to implement these so they return an rvalue reference +// (and indeed this would be optimally efficient), this is unsafe due to users propensity to +// write: +// +// const T& t = a * b; +// +// which would lead to a dangling reference if we didn't return by value. Of course move +// semantics help a great deal in return by value, so performance is still pretty good... +// +template +BOOST_FORCEINLINE number operator - (number&& v) +{ + BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); + v.backend().negate(); + return static_cast&&>(v); +} +template +BOOST_FORCEINLINE number operator ~ (number&& v) +{ + eval_complement(v.backend(), v.backend()); + return static_cast&&>(v); +} +// +// Addition: +// +template +BOOST_FORCEINLINE number operator + (number&& a, const number& b) +{ + using default_ops::eval_add; + eval_add(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE number operator + (const number& a, number&& b) +{ + using default_ops::eval_add; + eval_add(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator + (number&& a, number&& b) +{ + using default_ops::eval_add; + eval_add(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator + (number&& a, const V& b) +{ + using default_ops::eval_add; + eval_add(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator + (const V& a, number&& b) +{ + using default_ops::eval_add; + eval_add(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Subtraction: +// +template +BOOST_FORCEINLINE number operator - (number&& a, const number& b) +{ + using default_ops::eval_subtract; + eval_subtract(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if, number >::type operator - (const number& a, number&& b) +{ + using default_ops::eval_subtract; + eval_subtract(b.backend(), a.backend()); + b.backend().negate(); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator - (number&& a, number&& b) +{ + using default_ops::eval_subtract; + eval_subtract(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator - (number&& a, const V& b) +{ + using default_ops::eval_subtract; + eval_subtract(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if_c<(is_compatible_arithmetic_type >::value && is_signed_number::value), number >::type + operator - (const V& a, number&& b) +{ + using default_ops::eval_subtract; + eval_subtract(b.backend(), number::canonical_value(a)); + b.backend().negate(); + return static_cast&&>(b); +} +// +// Multiply: +// +template +BOOST_FORCEINLINE number operator * (number&& a, const number& b) +{ + using default_ops::eval_multiply; + eval_multiply(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE number operator * (const number& a, number&& b) +{ + using default_ops::eval_multiply; + eval_multiply(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator * (number&& a, number&& b) +{ + using default_ops::eval_multiply; + eval_multiply(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator * (number&& a, const V& b) +{ + using default_ops::eval_multiply; + eval_multiply(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator * (const V& a, number&& b) +{ + using default_ops::eval_multiply; + eval_multiply(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// divide: +// +template +BOOST_FORCEINLINE number operator / (number&& a, const number& b) +{ + using default_ops::eval_divide; + eval_divide(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator / (number&& a, const V& b) +{ + using default_ops::eval_divide; + eval_divide(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +// +// modulus: +// +template +BOOST_FORCEINLINE number operator % (number&& a, const number& b) +{ + using default_ops::eval_modulus; + eval_modulus(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator % (number&& a, const V& b) +{ + using default_ops::eval_modulus; + eval_modulus(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +// +// Bitwise or: +// +template +BOOST_FORCEINLINE number operator | (number&& a, const number& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE number operator | (const number& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator | (number&& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator | (number&& a, const V& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator | (const V& a, number&& b) +{ + using default_ops::eval_bitwise_or; + eval_bitwise_or(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Bitwise xor: +// +template +BOOST_FORCEINLINE number operator ^ (number&& a, const number& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE number operator ^ (const number& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator ^ (number&& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator ^ (number&& a, const V& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator ^ (const V& a, number&& b) +{ + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// Bitwise and: +// +template +BOOST_FORCEINLINE number operator & (number&& a, const number& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE number operator & (const number& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(b.backend(), a.backend()); + return static_cast&&>(b); +} +template +BOOST_FORCEINLINE number operator & (number&& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), b.backend()); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator & (number&& a, const V& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(a.backend(), number::canonical_value(b)); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if >, number >::type + operator & (const V& a, number&& b) +{ + using default_ops::eval_bitwise_and; + eval_bitwise_and(b.backend(), number::canonical_value(a)); + return static_cast&&>(b); +} +// +// shifts: +// +template +BOOST_FORCEINLINE typename enable_if, number >::type + operator << (number&& a, const I& b) +{ + using default_ops::eval_left_shift; + eval_left_shift(a.backend(), b); + return static_cast&&>(a); +} +template +BOOST_FORCEINLINE typename enable_if, number >::type + operator >> (number&& a, const I& b) +{ + using default_ops::eval_right_shift; + eval_right_shift(a.backend(), b); + return static_cast&&>(a); +} + +#endif + +}} // namespaces + +#endif // BOOST_MP_NO_ET_OPS_HPP diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp new file mode 100644 index 00000000..54afe583 --- /dev/null +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -0,0 +1,730 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BIG_NUM_BASE_HPP +#define BOOST_MATH_BIG_NUM_BASE_HPP + +#include +#include +#include +#include +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4307) +#endif +#include +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +namespace boost{ namespace multiprecision{ + +enum expression_template_option +{ + et_off = 0, + et_on = 1 +}; + +template +struct expression_template_default +{ + static const expression_template_option value = et_on; +}; + +template ::value> +class number; + +template +struct is_number : public mpl::false_ {}; + +template +struct is_number > : public mpl::true_ {}; + +namespace detail{ + +// Forward-declare an expression wrapper +template +struct expression; + +} // namespace detail + +template +struct is_number_expression : public mpl::false_ {}; + +template +struct is_number_expression > : public mpl::true_ {}; + +template +struct is_compatible_arithmetic_type + : public mpl::bool_< + is_convertible::value + && !is_same::value + && !is_number_expression::value> +{}; + +namespace detail{ +// +// Workaround for missing abs(long long) and abs(__int128) on some compilers: +// +template +typename enable_if_c<(is_signed::value || is_floating_point::value), T>::type abs(T t) BOOST_NOEXCEPT +{ + return t < 0 ? -t : t; +} +template +typename enable_if_c<(is_unsigned::value), T>::type abs(T t) BOOST_NOEXCEPT +{ + return t; +} + +#define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs; + +// +// Move support: +// +#ifndef BOOST_NO_RVALUE_REFERENCES +# define BOOST_MP_MOVE(x) std::move(x) +#else +# define BOOST_MP_MOVE(x) x +#endif + +template +struct bits_of +{ + BOOST_STATIC_ASSERT(is_integral::value || std::numeric_limits::is_specialized); + static const unsigned value = + std::numeric_limits::is_specialized ? + std::numeric_limits::digits + : sizeof(T) * CHAR_BIT - (is_signed::value ? 1 : 0); +}; + +template +struct has_enough_bits +{ + template + struct type : public mpl::bool_::value>= b>{}; +}; + +template +struct canonical_imp +{ + typedef typename remove_cv::type>::type type; +}; +template +struct canonical_imp, Backend, Tag> +{ + typedef B type; +}; +template +struct canonical_imp, Backend, Tag> +{ + typedef B type; +}; +template +struct canonical_imp > +{ + typedef typename has_enough_bits::value>::template type pred_type; + typedef typename mpl::find_if< + typename Backend::signed_types, + pred_type + >::type iter_type; + typedef typename mpl::deref::type type; +}; +template +struct canonical_imp > +{ + typedef typename has_enough_bits::value>::template type pred_type; + typedef typename mpl::find_if< + typename Backend::unsigned_types, + pred_type + >::type iter_type; + typedef typename mpl::deref::type type; +}; +template +struct canonical_imp > +{ + typedef typename has_enough_bits::value>::template type pred_type; + typedef typename mpl::find_if< + typename Backend::float_types, + pred_type + >::type iter_type; + typedef typename mpl::deref::type type; +}; +template +struct canonical_imp > +{ + typedef const char* type; +}; + +template +struct canonical +{ + typedef typename mpl::if_< + is_signed, + mpl::int_<0>, + typename mpl::if_< + is_unsigned, + mpl::int_<1>, + typename mpl::if_< + is_floating_point, + mpl::int_<2>, + typename mpl::if_< + mpl::or_< + is_convertible, + is_same + >, + mpl::int_<3>, + mpl::int_<4> + >::type + >::type + >::type + >::type tag_type; + + typedef typename canonical_imp::type type; +}; + +struct terminal{}; +struct negate{}; +struct plus{}; +struct minus{}; +struct multiplies{}; +struct divides{}; +struct modulus{}; +struct shift_left{}; +struct shift_right{}; +struct bitwise_and{}; +struct bitwise_or{}; +struct bitwise_xor{}; +struct bitwise_complement{}; +struct add_immediates{}; +struct subtract_immediates{}; +struct multiply_immediates{}; +struct divide_immediates{}; +struct modulus_immediates{}; +struct bitwise_and_immediates{}; +struct bitwise_or_immediates{}; +struct bitwise_xor_immediates{}; +struct complement_immediates{}; +struct function{}; +struct multiply_add{}; +struct multiply_subtract{}; + +template +struct backend_type; + +template +struct backend_type > +{ + typedef T type; +}; + +template +struct backend_type > +{ + typedef typename backend_type::result_type>::type type; +}; + + +template +struct combine_expression +{ +#ifdef BOOST_NO_DECLTYPE + typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type; +#else + typedef decltype(T1() + T2()) type; +#endif +}; + +template +struct combine_expression, T2> +{ + typedef number type; +}; + +template +struct combine_expression > +{ + typedef number type; +}; + +template +struct combine_expression, number > +{ + typedef number type; +}; + +template +struct combine_expression, number > +{ + typedef typename mpl::if_c< + is_convertible, number >::value, + number, + number + >::type type; +}; + +template +struct arg_type +{ + typedef expression type; +}; + +template +struct arg_type > +{ + typedef expression type; +}; + +template +struct unmentionable +{ + static void proc(){} +}; + +typedef void (*unmentionable_type)(); + +template +struct expression_storage +{ + typedef const T& type; +}; + +template +struct expression_storage +{ + typedef T* type; +}; + +template +struct expression_storage +{ + typedef const T* type; +}; + +template +struct expression_storage > +{ + typedef expression type; +}; + +template +struct expression +{ + typedef mpl::int_<1> arity; + typedef typename arg_type::type left_type; + typedef typename left_type::result_type result_type; + typedef tag tag_type; + + explicit expression(const Arg1& a) : arg(a) {} + + left_type left()const { return left_type(arg); } + + const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; } + + static const unsigned depth = left_type::depth + 1; + + operator unmentionable_type()const + { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } + +private: + typename expression_storage::type arg; + expression& operator=(const expression&); +}; + +template +struct expression +{ + typedef mpl::int_<0> arity; + typedef Arg1 result_type; + typedef terminal tag_type; + + explicit expression(const Arg1& a) : arg(a) {} + + const Arg1& value()const BOOST_NOEXCEPT { return arg; } + + static const unsigned depth = 0; + + operator unmentionable_type()const + { + return arg ? &unmentionable::proc : 0; + } + +private: + typename expression_storage::type arg; + expression& operator=(const expression&); +}; + +template +struct expression +{ + typedef mpl::int_<2> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression::type result_type; + typedef tag tag_type; + + expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {} + + left_type left()const { return left_type(arg1); } + right_type right()const { return right_type(arg2); } + const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } + const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; } + + operator unmentionable_type()const + { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + static const unsigned depth = left_depth > right_depth ? left_depth : right_depth; +private: + typename expression_storage::type arg1; + typename expression_storage::type arg2; + expression& operator=(const expression&); +}; + +template +struct expression +{ + typedef mpl::int_<3> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type middle_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename middle_type::result_type middle_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression< + left_result_type, + typename combine_expression::type + >::type result_type; + typedef tag tag_type; + + expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {} + + left_type left()const { return left_type(arg1); } + middle_type middle()const { return middle_type(arg2); } + right_type right()const { return right_type(arg3); } + const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } + const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; } + const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; } + + operator unmentionable_type()const + { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned middle_depth = middle_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth); +private: + typename expression_storage::type arg1; + typename expression_storage::type arg2; + typename expression_storage::type arg3; + expression& operator=(const expression&); +}; + +template +struct expression +{ + typedef mpl::int_<4> arity; + typedef typename arg_type::type left_type; + typedef typename arg_type::type left_middle_type; + typedef typename arg_type::type right_middle_type; + typedef typename arg_type::type right_type; + typedef typename left_type::result_type left_result_type; + typedef typename left_middle_type::result_type left_middle_result_type; + typedef typename right_middle_type::result_type right_middle_result_type; + typedef typename right_type::result_type right_result_type; + typedef typename combine_expression< + typename combine_expression< + typename combine_expression::type, + right_middle_result_type + >::type, + right_result_type + >::type result_type; + typedef tag tag_type; + + expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {} + + left_type left()const { return left_type(arg1); } + left_middle_type left_middle()const { return left_middle_type(arg2); } + right_middle_type right_middle()const { return right_middle_type(arg3); } + right_type right()const { return right_type(arg4); } + const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } + const Arg2& left_middle_ref()const BOOST_NOEXCEPT { return arg2; } + const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; } + const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; } + + operator unmentionable_type()const + { + result_type r(*this); + return r ? &unmentionable::proc : 0; + } + + static const unsigned left_depth = left_type::depth + 1; + static const unsigned left_middle_depth = left_middle_type::depth + 1; + static const unsigned right_middle_depth = right_middle_type::depth + 1; + static const unsigned right_depth = right_type::depth + 1; + + static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth; + static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth; + + static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth; +private: + typename expression_storage::type arg1; + typename expression_storage::type arg2; + typename expression_storage::type arg3; + typename expression_storage::type arg4; + expression& operator=(const expression&); +}; + +template +struct digits2 +{ + BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); + BOOST_STATIC_ASSERT((std::numeric_limits::radix == 2) || (std::numeric_limits::radix == 10)); + // If we really have so many digits that this fails, then we're probably going to hit other problems anyway: + BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits::digits + 1)); + static const long value = std::numeric_limits::radix == 10 ? (((std::numeric_limits::digits + 1) * 1000L) / 301L) : std::numeric_limits::digits; +}; + +#ifndef BOOST_MP_MIN_EXPONENT_DIGITS +#ifdef _MSC_VER +# define BOOST_MP_MIN_EXPONENT_DIGITS 2 +#else +# define BOOST_MP_MIN_EXPONENT_DIGITS 2 +#endif +#endif + +template +void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero) +{ + typedef typename S::size_type size_type; + bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint; + bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos; + + bool neg = str.size() && (str[0] == '-'); + + if(neg) + str.erase(0, 1); + + if(digits == 0) + { + digits = (std::max)(str.size(), size_type(16)); + } + + if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos)) + { + // We will be printing zero, even though the value might not + // actually be zero (it just may have been rounded to zero). + str = "0"; + if(scientific || fixed) + { + str.append(1, '.'); + str.append(size_type(digits), '0'); + if(scientific) + str.append("e+00"); + } + else + { + if(showpoint) + { + str.append(1, '.'); + if(digits > 1) + str.append(size_type(digits - 1), '0'); + } + } + if(neg) + str.insert(0, 1, '-'); + else if(showpos) + str.insert(0, 1, '+'); + return; + } + + if(!fixed && !scientific && !showpoint) + { + // + // Suppress trailing zeros: + // + std::string::iterator pos = str.end(); + while(pos != str.begin() && *--pos == '0'){} + if(pos != str.end()) + ++pos; + str.erase(pos, str.end()); + if(str.empty()) + str = '0'; + } + else if(!fixed || (my_exp >= 0)) + { + // + // Pad out the end with zero's if we need to: + // + boost::intmax_t chars = str.size(); + chars = digits - chars; + if(scientific) + ++chars; + if(chars > 0) + { + str.append(static_cast(chars), '0'); + } + } + + if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits))) + { + if(1 + my_exp > static_cast(str.size())) + { + // Just pad out the end with zeros: + str.append(static_cast(1 + my_exp - str.size()), '0'); + if(showpoint || fixed) + str.append("."); + } + else if(my_exp + 1 < static_cast(str.size())) + { + if(my_exp < 0) + { + str.insert(0, static_cast(-1 - my_exp), '0'); + str.insert(0, "0."); + } + else + { + // Insert the decimal point: + str.insert(static_cast(my_exp + 1), 1, '.'); + } + } + else if(showpoint || fixed) // we have exactly the digits we require to left of the point + str += "."; + + if(fixed) + { + // We may need to add trailing zeros: + boost::intmax_t l = str.find('.') + 1; + l = digits - (str.size() - l); + if(l > 0) + str.append(size_type(l), '0'); + } + } + else + { + BOOST_MP_USING_ABS + // Scientific format: + if(showpoint || (str.size() > 1)) + str.insert(1, 1, '.'); + str.append(1, 'e'); + S e = boost::lexical_cast(abs(my_exp)); + if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS) + e.insert(0, BOOST_MP_MIN_EXPONENT_DIGITS-e.size(), '0'); + if(my_exp < 0) + e.insert(0, 1, '-'); + else + e.insert(0, 1, '+'); + str.append(e); + } + if(neg) + str.insert(0, 1, '-'); + else if(showpos) + str.insert(0, 1, '+'); +} + +template +void check_shift_range(V val, const mpl::true_&, const mpl::true_&) +{ + if(val > (std::numeric_limits::max)()) + BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); + if(val < 0) + BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); +} +template +void check_shift_range(V val, const mpl::false_&, const mpl::true_&) +{ + if(val < 0) + BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); +} +template +void check_shift_range(V val, const mpl::true_&, const mpl::false_&) +{ + if(val > (std::numeric_limits::max)()) + BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); +} +template +void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{} + +} // namespace detail + +// +// Traits class, lets us know what kind of number we have, defaults to a floating point type: +// +enum number_category_type +{ + number_kind_unknown = -1, + number_kind_integer = 0, + number_kind_floating_point = 1, + number_kind_rational = 2, + number_kind_fixed_point = 3 +}; + +template +struct number_category : public mpl::int_::is_integer ? number_kind_integer : (std::numeric_limits::max_exponent ? number_kind_floating_point : number_kind_unknown)> {}; +template +struct number_category > : public number_category{}; +template +struct number_category > : public number_category::result_type>{}; + +template +struct component_type; +template +struct component_type > : public component_type{}; +template +struct component_type > : public component_type::result_type>{}; + +template +struct is_unsigned_number : public mpl::false_{}; +template +struct is_unsigned_number > : public is_unsigned_number {}; +template +struct is_signed_number : public mpl::bool_::value> {}; + +}} // namespaces + +namespace boost{ namespace math{ namespace tools{ + +template +struct promote_arg; + +template +struct promote_arg > +{ + typedef typename boost::multiprecision::detail::expression::result_type type; +}; + +template +inline R real_cast(const boost::multiprecision::number& val) +{ + return val.template convert_to(); +} + +template +inline R real_cast(const boost::multiprecision::detail::expression& val) +{ + typedef typename boost::multiprecision::detail::expression::result_type val_type; + return val_type(val).template convert_to(); +} + + +}}} + +#endif // BOOST_MATH_BIG_NUM_BASE_HPP + + diff --git a/include/boost/multiprecision/detail/number_compare.hpp b/include/boost/multiprecision/detail/number_compare.hpp new file mode 100644 index 00000000..bd01c3d6 --- /dev/null +++ b/include/boost/multiprecision/detail/number_compare.hpp @@ -0,0 +1,388 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_COMPARE_HPP +#define BOOST_MP_COMPARE_HPP + +// +// Comparison operators for number. +// + +namespace boost{ namespace multiprecision{ + +namespace default_ops{ + +template +inline bool eval_eq(const B& a, const B& b) +{ + return a.compare(b) == 0; +} +// +// For the default version which compares to some arbitrary type convertible to +// our number type, we don't know what value the ExpressionTemplates parameter to +// class number should be. We generally prefer ExpressionTemplates to be enabled +// in case type A is itself an expression template, but we need to test both options +// with is_convertible in case A has an implicit conversion operator to number. +// This is the case with many uBlas types for example. +// +template +inline bool eval_eq(const B& a, const A& b) +{ + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; + mp_type t(b); + return eval_eq(a, t.backend()); +} + +template +inline bool eval_lt(const B& a, const B& b) +{ + return a.compare(b) < 0; +} +template +inline bool eval_lt(const B& a, const A& b) +{ + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; + mp_type t(b); + return eval_lt(a, t.backend()); +} + +template +inline bool eval_gt(const B& a, const B& b) +{ + return a.compare(b) > 0; +} +template +inline bool eval_gt(const B& a, const A& b) +{ + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; + mp_type t(b); + return eval_gt(a, t.backend()); +} + +} // namespace default_ops + +namespace detail{ + +template +struct is_valid_mixed_compare : public mpl::false_ {}; + +template +struct is_valid_mixed_compare, Val> : public is_convertible > {}; + +template +struct is_valid_mixed_compare, number > : public mpl::false_ {}; + +template +struct is_valid_mixed_compare, expression > + : public mpl::bool_, number >::value> {}; + +template +struct is_valid_mixed_compare, number > + : public mpl::bool_, number >::value> {}; + +} + +template +inline bool operator == (const number& a, const number& b) +{ + using default_ops::eval_eq; + return eval_eq(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator == (const number& a, const Arithmetic& b) +{ + using default_ops::eval_eq; + return eval_eq(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator == (const Arithmetic& a, const number& b) +{ + using default_ops::eval_eq; + return eval_eq(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator == (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_eq; + result_type t(b); + return eval_eq(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator == (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_eq; + result_type t(a); + return eval_eq(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator == (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_eq; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return eval_eq(t.backend(), t2.backend()); +} + +template +inline bool operator != (const number& a, const number& b) +{ + using default_ops::eval_eq; + return !eval_eq(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator != (const number& a, const Arithmetic& b) +{ + using default_ops::eval_eq; + return !eval_eq(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator != (const Arithmetic& a, const number& b) +{ + using default_ops::eval_eq; + return !eval_eq(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator != (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_eq; + result_type t(b); + return !eval_eq(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator != (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_eq; + result_type t(a); + return !eval_eq(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator != (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_eq; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return !eval_eq(t.backend(), t2.backend()); +} + +template +inline bool operator < (const number& a, const number& b) +{ + using default_ops::eval_lt; + return eval_lt(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator < (const number& a, const Arithmetic& b) +{ + using default_ops::eval_lt; + return eval_lt(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator < (const Arithmetic& a, const number& b) +{ + using default_ops::eval_gt; + return eval_gt(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator < (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_gt; + result_type t(b); + return eval_gt(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator < (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_lt; + result_type t(a); + return eval_lt(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator < (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_lt; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return eval_lt(t.backend(), t2.backend()); +} + +template +inline bool operator > (const number& a, const number& b) +{ + using default_ops::eval_gt; + return eval_gt(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator > (const number& a, const Arithmetic& b) +{ + using default_ops::eval_gt; + return eval_gt(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator > (const Arithmetic& a, const number& b) +{ + using default_ops::eval_lt; + return eval_lt(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator > (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_lt; + result_type t(b); + return eval_lt(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator > (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_gt; + result_type t(a); + return eval_gt(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator > (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_gt; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return eval_gt(t.backend(), t2.backend()); +} + +template +inline bool operator <= (const number& a, const number& b) +{ + using default_ops::eval_gt; + return !eval_gt(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator <= (const number& a, const Arithmetic& b) +{ + using default_ops::eval_gt; + return !eval_gt(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator <= (const Arithmetic& a, const number& b) +{ + using default_ops::eval_lt; + return !eval_lt(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator <= (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_lt; + result_type t(b); + return !eval_lt(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator <= (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_gt; + result_type t(a); + return !eval_gt(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator <= (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_gt; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return !eval_gt(t.backend(), t2.backend()); +} + +template +inline bool operator >= (const number& a, const number& b) +{ + using default_ops::eval_lt; + return !eval_lt(a.backend(), b.backend()); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator >= (const number& a, const Arithmetic& b) +{ + using default_ops::eval_lt; + return !eval_lt(a.backend(), number::canonical_value(b)); +} +template +inline typename enable_if_c, Arithmetic>::value, bool>::type + operator >= (const Arithmetic& a, const number& b) +{ + using default_ops::eval_gt; + return !eval_gt(b.backend(), number::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator >= (const Arithmetic& a, const detail::expression& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_gt; + result_type t(b); + return !eval_gt(t.backend(), result_type::canonical_value(a)); +} +template +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type + operator >= (const detail::expression& a, const Arithmetic& b) +{ + typedef typename detail::expression::result_type result_type; + using default_ops::eval_lt; + result_type t(a); + return !eval_lt(t.backend(), result_type::canonical_value(b)); +} +template +inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type + operator >= (const detail::expression& a, const detail::expression& b) +{ + using default_ops::eval_lt; + typename detail::expression::result_type t(a); + typename detail::expression::result_type t2(b); + return !eval_lt(t.backend(), t2.backend()); +} + + +}} // namespaces + +#endif // BOOST_MP_COMPARE_HPP + diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp new file mode 100644 index 00000000..e09c2bdc --- /dev/null +++ b/include/boost/multiprecision/gmp.hpp @@ -0,0 +1,2603 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_ER_GMP_BACKEND_HPP +#define BOOST_MATH_ER_GMP_BACKEND_HPP + +#include +#include +#include +#include +#include +#include +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4127) +#endif +#include +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +#include +#include +#include + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +#ifdef BOOST_MSVC +// warning C4127: conditional expression is constant +#pragma warning(push) +#pragma warning(disable:4127) +#endif + +template +struct gmp_float; +struct gmp_int; +struct gmp_rational; + +} // namespace backends + +template<> +struct number_category : public mpl::int_{}; +template<> +struct number_category : public mpl::int_{}; +template +struct number_category > : public mpl::int_{}; + +namespace backends{ +// +// Within this file, the only functions we mark as noexcept are those that manipulate +// (but don't create) an mpf_t. All other types may allocate at pretty much any time +// via a user-supplied allocator, and therefore throw. +// +namespace detail{ + +template +struct gmp_float_imp +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef long exponent_type; + + gmp_float_imp() BOOST_NOEXCEPT {} + + gmp_float_imp(const gmp_float_imp& o) + { + // + // We have to do an init followed by a set here, otherwise *this may be at + // a lower precision than o: seems like mpf_init_set copies just enough bits + // to get the right value, but if it's then used in further calculations + // things go badly wrong!! + // + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(o.m_data[0]._mp_d) + mpf_set(m_data, o.m_data); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT + { + m_data[0] = o.m_data[0]; + o.m_data[0]._mp_d = 0; + } +#endif + gmp_float_imp& operator = (const gmp_float_imp& o) + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(o.m_data[0]._mp_d) + mpf_set(m_data, o.m_data); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float_imp& operator = (gmp_float_imp&& o) BOOST_NOEXCEPT + { + mpf_swap(m_data, o.m_data); + return *this; + } +#endif + gmp_float_imp& operator = (unsigned long long i) + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + mpf_t t; + mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpf_set_ui(m_data, 0); + while(i) + { + mpf_set_ui(t, static_cast(i & mask)); + if(shift) + mpf_mul_2exp(t, t, shift); + mpf_add(m_data, m_data, t); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpf_clear(t); + return *this; + } + gmp_float_imp& operator = (long long i) + { + BOOST_MP_USING_ABS + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + mpf_neg(m_data, m_data); + return *this; + } + gmp_float_imp& operator = (unsigned long i) BOOST_NOEXCEPT + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpf_set_ui(m_data, i); + return *this; + } + gmp_float_imp& operator = (long i) BOOST_NOEXCEPT + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpf_set_si(m_data, i); + return *this; + } + gmp_float_imp& operator = (double d) BOOST_NOEXCEPT + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpf_set_d(m_data, d); + return *this; + } + gmp_float_imp& operator = (long double a) + { + using std::frexp; + using std::ldexp; + using std::floor; + + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + + if (a == 0) { + mpf_set_si(m_data, 0); + return *this; + } + + if (a == 1) { + mpf_set_si(m_data, 1); + return *this; + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + mpf_init_set_ui(m_data, 0u); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpf_mul_2exp(m_data, m_data, shift); + if(term > 0) + mpf_add_ui(m_data, m_data, static_cast(term)); + else + mpf_sub_ui(m_data, m_data, static_cast(-term)); + f -= term; + } + if(e > 0) + mpf_mul_2exp(m_data, m_data, e); + else if(e < 0) + mpf_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_float_imp& operator = (const char* s) + { + if(m_data[0]._mp_d == 0) + mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(0 != mpf_set_str(m_data, s, 10)) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number."))); + return *this; + } + void swap(gmp_float_imp& o) BOOST_NOEXCEPT + { + mpf_swap(m_data, o.m_data); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + BOOST_ASSERT(m_data[0]._mp_d); + + bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + std::streamsize org_digits(digits); + + if(scientific && digits) + ++digits; + + std::string result; + mp_exp_t e; + void *(*alloc_func_ptr) (size_t); + void *(*realloc_func_ptr) (void *, size_t, size_t); + void (*free_func_ptr) (void *, size_t); + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + + if(mpf_sgn(m_data) == 0) + { + e = 0; + result = "0"; + if(fixed && digits) + ++digits; + } + else + { + char* ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); + --e; // To match with what our formatter expects. + if(fixed && e != -1) + { + // Oops we actually need a different number of digits to what we asked for: + (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); + digits += e + 1; + if(digits == 0) + { + // We need to get *all* the digits and then possibly round up, + // we end up with either "0" or "1" as the result. + ps = mpf_get_str (0, &e, 10, 0, m_data); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + if(ps[offset] > '5') + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else if(ps[offset] == '5') + { + unsigned i = offset + 1; + bool round_up = false; + while(ps[i] != 0) + { + if(ps[i] != '0') + { + round_up = true; + break; + } + } + if(round_up) + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else if(digits > 0) + { + ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); + --e; // To match with what our formatter expects. + } + else + { + ps = mpf_get_str (0, &e, 10, 1, m_data); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + result = ps; + (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); + } + boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0); + return result; + } + ~gmp_float_imp() BOOST_NOEXCEPT + { + if(m_data[0]._mp_d) + mpf_clear(m_data); + } + void negate() BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d); + mpf_neg(m_data, m_data); + } + int compare(const gmp_float& o)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); + return mpf_cmp(m_data, o.m_data); + } + int compare(long i)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d); + return mpf_cmp_si(m_data, i); + } + int compare(unsigned long i)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d); + return mpf_cmp_ui(m_data, i); + } + template + typename enable_if, int>::type compare(V v)const + { + gmp_float d; + d = v; + return compare(d); + } + mpf_t& data() BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + const mpf_t& data()const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } +protected: + mpf_t m_data; + static unsigned& get_default_precision() BOOST_NOEXCEPT + { + static unsigned val = 50; + return val; + } +}; + +} // namespace detail + +struct gmp_int; +struct gmp_rational; + +template +struct gmp_float : public detail::gmp_float_imp +{ + gmp_float() + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + } + gmp_float(const gmp_float& o) : detail::gmp_float_imp(o) {} + template + gmp_float(const gmp_float& o, typename enable_if_c::type* = 0); + template + explicit gmp_float(const gmp_float& o, typename disable_if_c::type* = 0); + gmp_float(const gmp_int& o); + gmp_float(const gmp_rational& o); + gmp_float(const mpf_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, val); + } + gmp_float(const mpz_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_z(this->m_data, val); + } + gmp_float(const mpq_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_q(this->m_data, val); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp(static_cast&&>(o)) {} +#endif + gmp_float& operator=(const gmp_float& o) + { + *static_cast*>(this) = static_cast const&>(o); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT + { + *static_cast*>(this) = static_cast&&>(o); + return *this; + } +#endif + template + gmp_float& operator=(const gmp_float& o); + gmp_float& operator=(const gmp_int& o); + gmp_float& operator=(const gmp_rational& o); + gmp_float& operator=(const mpf_t val) BOOST_NOEXCEPT + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, val); + return *this; + } + gmp_float& operator=(const mpz_t val) BOOST_NOEXCEPT + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_z(this->m_data, val); + return *this; + } + gmp_float& operator=(const mpq_t val) BOOST_NOEXCEPT + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set_q(this->m_data, val); + return *this; + } + template + gmp_float& operator=(const V& v) + { + *static_cast*>(this) = v; + return *this; + } +}; + +template <> +struct gmp_float<0> : public detail::gmp_float_imp<0> +{ + gmp_float() + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + } + gmp_float(const mpf_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set(this->m_data, val); + } + gmp_float(const mpz_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->m_data, val); + } + gmp_float(const mpq_t val) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->m_data, val); + } + gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o) {} + template + gmp_float(const gmp_float& o) + { + mpf_init2(this->m_data, mpf_get_prec(o.data())); + mpf_set(this->m_data, o.data()); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast&&>(o)) {} +#endif + gmp_float(const gmp_int& o); + gmp_float(const gmp_rational& o); + gmp_float(const gmp_float& o, unsigned digits10) + { + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + mpf_set(this->m_data, o.data()); + } + + gmp_float& operator=(const gmp_float& o) + { + *static_cast*>(this) = static_cast const&>(o); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT + { + *static_cast*>(this) = static_cast &&>(o); + return *this; + } +#endif + template + gmp_float& operator=(const gmp_float& o) + { + if(this->m_data[0]._mp_d == 0) + { + mpf_init2(this->m_data, mpf_get_prec(o.data())); + } + else + { + mpf_set_prec(this->m_data, mpf_get_prec(o.data())); + } + mpf_set(this->m_data, o.data()); + return *this; + } + gmp_float& operator=(const gmp_int& o); + gmp_float& operator=(const gmp_rational& o); + gmp_float& operator=(const mpf_t val) + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set(this->m_data, val); + return *this; + } + gmp_float& operator=(const mpz_t val) + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->m_data, val); + return *this; + } + gmp_float& operator=(const mpq_t val) + { + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->m_data, val); + return *this; + } + template + gmp_float& operator=(const V& v) + { + *static_cast*>(this) = v; + return *this; + } + static unsigned default_precision() BOOST_NOEXCEPT + { + return get_default_precision(); + } + static void default_precision(unsigned v) BOOST_NOEXCEPT + { + get_default_precision() = v; + } + unsigned precision()const BOOST_NOEXCEPT + { + return multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data)); + } + void precision(unsigned digits10) BOOST_NOEXCEPT + { + mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(digits10)); + } +}; + +template +inline typename enable_if_c::value, bool>::type eval_eq(const gmp_float& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) == 0; +} +template +inline typename enable_if_c::value, bool>::type eval_lt(const gmp_float& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) < 0; +} +template +inline typename enable_if_c::value, bool>::type eval_gt(const gmp_float& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) > 0; +} + +template +inline void eval_add(gmp_float& result, const gmp_float& o) BOOST_NOEXCEPT +{ + mpf_add(result.data(), result.data(), o.data()); +} +template +inline void eval_subtract(gmp_float& result, const gmp_float& o) BOOST_NOEXCEPT +{ + mpf_sub(result.data(), result.data(), o.data()); +} +template +inline void eval_multiply(gmp_float& result, const gmp_float& o) BOOST_NOEXCEPT +{ + mpf_mul(result.data(), result.data(), o.data()); +} +template +inline bool eval_is_zero(const gmp_float& val) BOOST_NOEXCEPT +{ + return mpf_sgn(val.data()) == 0; +} +template +inline void eval_divide(gmp_float& result, const gmp_float& o) +{ + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div(result.data(), result.data(), o.data()); +} +template +inline void eval_add(gmp_float& result, unsigned long i) BOOST_NOEXCEPT +{ + mpf_add_ui(result.data(), result.data(), i); +} +template +inline void eval_subtract(gmp_float& result, unsigned long i) BOOST_NOEXCEPT +{ + mpf_sub_ui(result.data(), result.data(), i); +} +template +inline void eval_multiply(gmp_float& result, unsigned long i) BOOST_NOEXCEPT +{ + mpf_mul_ui(result.data(), result.data(), i); +} +template +inline void eval_divide(gmp_float& result, unsigned long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(result.data(), result.data(), i); +} +template +inline void eval_add(gmp_float& result, long i) BOOST_NOEXCEPT +{ + if(i > 0) + mpf_add_ui(result.data(), result.data(), i); + else + mpf_sub_ui(result.data(), result.data(), std::abs(i)); +} +template +inline void eval_subtract(gmp_float& result, long i) BOOST_NOEXCEPT +{ + if(i > 0) + mpf_sub_ui(result.data(), result.data(), i); + else + mpf_add_ui(result.data(), result.data(), std::abs(i)); +} +template +inline void eval_multiply(gmp_float& result, long i) BOOST_NOEXCEPT +{ + mpf_mul_ui(result.data(), result.data(), std::abs(i)); + if(i < 0) + mpf_neg(result.data(), result.data()); +} +template +inline void eval_divide(gmp_float& result, long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(result.data(), result.data(), std::abs(i)); + if(i < 0) + mpf_neg(result.data(), result.data()); +} +// +// Specialised 3 arg versions of the basic operators: +// +template +inline void eval_add(gmp_float& a, const gmp_float& x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_add(a.data(), x.data(), y.data()); +} +template +inline void eval_add(gmp_float& a, const gmp_float& x, unsigned long y) BOOST_NOEXCEPT +{ + mpf_add_ui(a.data(), x.data(), y); +} +template +inline void eval_add(gmp_float& a, const gmp_float& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + mpf_sub_ui(a.data(), x.data(), -y); + else + mpf_add_ui(a.data(), x.data(), y); +} +template +inline void eval_add(gmp_float& a, unsigned long x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_add_ui(a.data(), y.data(), x); +} +template +inline void eval_add(gmp_float& a, long x, const gmp_float& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpf_ui_sub(a.data(), -x, y.data()); + mpf_neg(a.data(), a.data()); + } + else + mpf_add_ui(a.data(), y.data(), x); +} +template +inline void eval_subtract(gmp_float& a, const gmp_float& x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_sub(a.data(), x.data(), y.data()); +} +template +inline void eval_subtract(gmp_float& a, const gmp_float& x, unsigned long y) BOOST_NOEXCEPT +{ + mpf_sub_ui(a.data(), x.data(), y); +} +template +inline void eval_subtract(gmp_float& a, const gmp_float& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + mpf_add_ui(a.data(), x.data(), -y); + else + mpf_sub_ui(a.data(), x.data(), y); +} +template +inline void eval_subtract(gmp_float& a, unsigned long x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_ui_sub(a.data(), x, y.data()); +} +template +inline void eval_subtract(gmp_float& a, long x, const gmp_float& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpf_add_ui(a.data(), y.data(), -x); + mpf_neg(a.data(), a.data()); + } + else + mpf_ui_sub(a.data(), x, y.data()); +} + +template +inline void eval_multiply(gmp_float& a, const gmp_float& x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_mul(a.data(), x.data(), y.data()); +} +template +inline void eval_multiply(gmp_float& a, const gmp_float& x, unsigned long y) BOOST_NOEXCEPT +{ + mpf_mul_ui(a.data(), x.data(), y); +} +template +inline void eval_multiply(gmp_float& a, const gmp_float& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + { + mpf_mul_ui(a.data(), x.data(), -y); + a.negate(); + } + else + mpf_mul_ui(a.data(), x.data(), y); +} +template +inline void eval_multiply(gmp_float& a, unsigned long x, const gmp_float& y) BOOST_NOEXCEPT +{ + mpf_mul_ui(a.data(), y.data(), x); +} +template +inline void eval_multiply(gmp_float& a, long x, const gmp_float& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpf_mul_ui(a.data(), y.data(), -x); + mpf_neg(a.data(), a.data()); + } + else + mpf_mul_ui(a.data(), y.data(), x); +} + +template +inline void eval_divide(gmp_float& a, const gmp_float& x, const gmp_float& y) +{ + if(eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div(a.data(), x.data(), y.data()); +} +template +inline void eval_divide(gmp_float& a, const gmp_float& x, unsigned long y) +{ + if(y == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_div_ui(a.data(), x.data(), y); +} +template +inline void eval_divide(gmp_float& a, const gmp_float& x, long y) +{ + if(y == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + if(y < 0) + { + mpf_div_ui(a.data(), x.data(), -y); + a.negate(); + } + else + mpf_div_ui(a.data(), x.data(), y); +} +template +inline void eval_divide(gmp_float& a, unsigned long x, const gmp_float& y) +{ + if(eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpf_ui_div(a.data(), x, y.data()); +} +template +inline void eval_divide(gmp_float& a, long x, const gmp_float& y) +{ + if(eval_is_zero(y)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + if(x < 0) + { + mpf_ui_div(a.data(), -x, y.data()); + mpf_neg(a.data(), a.data()); + } + else + mpf_ui_div(a.data(), x, y.data()); +} + +template +inline int eval_get_sign(const gmp_float& val) BOOST_NOEXCEPT +{ + return mpf_sgn(val.data()); +} + +template +inline void eval_convert_to(unsigned long* result, const gmp_float& val) BOOST_NOEXCEPT +{ + if(0 == mpf_fits_ulong_p(val.data())) + *result = (std::numeric_limits::max)(); + else + *result = mpf_get_ui(val.data()); +} +template +inline void eval_convert_to(long* result, const gmp_float& val) BOOST_NOEXCEPT +{ + if(0 == mpf_fits_slong_p(val.data())) + { + *result = (std::numeric_limits::max)(); + *result *= mpf_sgn(val.data()); + } + else + *result = mpf_get_si(val.data()); +} +template +inline void eval_convert_to(double* result, const gmp_float& val) BOOST_NOEXCEPT +{ + *result = mpf_get_d(val.data()); +} +#ifdef BOOST_HAS_LONG_LONG +template +inline void eval_convert_to(long long* result, const gmp_float& val) +{ + gmp_float t(val); + if(eval_get_sign(t) < 0) + t.negate(); + + long digits = std::numeric_limits::digits - std::numeric_limits::digits; + + if(digits > 0) + mpf_div_2exp(t.data(), t.data(), digits); + + if(!mpf_fits_slong_p(t.data())) + { + if(eval_get_sign(val) < 0) + *result = (std::numeric_limits::min)(); + else + *result = (std::numeric_limits::max)(); + return; + }; + + *result = mpf_get_si(t.data()); + while(digits > 0) + { + *result <<= digits; + digits -= std::numeric_limits::digits; + mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); + unsigned long l = mpf_get_ui(t.data()); + if(digits < 0) + l >>= -digits; + *result |= l; + } + if(eval_get_sign(val) < 0) + *result = -*result; +} +template +inline void eval_convert_to(unsigned long long* result, const gmp_float& val) +{ + gmp_float t(val); + + long digits = std::numeric_limits::digits - std::numeric_limits::digits; + + if(digits > 0) + mpf_div_2exp(t.data(), t.data(), digits); + + if(!mpf_fits_ulong_p(t.data())) + { + *result = (std::numeric_limits::max)(); + return; + } + + *result = mpf_get_ui(t.data()); + while(digits > 0) + { + *result <<= digits; + digits -= std::numeric_limits::digits; + mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); + unsigned long l = mpf_get_ui(t.data()); + if(digits < 0) + l >>= -digits; + *result |= l; + } +} +#endif + +// +// Native non-member operations: +// +template +inline void eval_sqrt(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_sqrt(result.data(), val.data()); +} + +template +inline void eval_abs(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_abs(result.data(), val.data()); +} + +template +inline void eval_fabs(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_abs(result.data(), val.data()); +} +template +inline void eval_ceil(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_ceil(result.data(), val.data()); +} +template +inline void eval_floor(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_floor(result.data(), val.data()); +} +template +inline void eval_trunc(gmp_float& result, const gmp_float& val) BOOST_NOEXCEPT +{ + mpf_trunc(result.data(), val.data()); +} +template +inline void eval_ldexp(gmp_float& result, const gmp_float& val, long e) BOOST_NOEXCEPT +{ + if(e > 0) + mpf_mul_2exp(result.data(), val.data(), e); + else if(e < 0) + mpf_div_2exp(result.data(), val.data(), -e); + else + result = val; +} +template +inline void eval_frexp(gmp_float& result, const gmp_float& val, int* e) BOOST_NOEXCEPT +{ + long v; + mpf_get_d_2exp(&v, val.data()); + *e = v; + eval_ldexp(result, val, -v); +} +template +inline void eval_frexp(gmp_float& result, const gmp_float& val, long* e) BOOST_NOEXCEPT +{ + mpf_get_d_2exp(e, val.data()); + eval_ldexp(result, val, -*e); +} + +struct gmp_int +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + + gmp_int() + { + mpz_init(this->m_data); + } + gmp_int(const gmp_int& o) + { + if(o.m_data[0]._mp_d) + mpz_init_set(m_data, o.m_data); + else + mpz_init(this->m_data); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_int(gmp_int&& o) BOOST_NOEXCEPT + { + m_data[0] = o.m_data[0]; + o.m_data[0]._mp_d = 0; + } +#endif + explicit gmp_int(const mpf_t val) + { + mpz_init(this->m_data); + mpz_set_f(this->m_data, val); + } + gmp_int(const mpz_t val) + { + mpz_init_set(this->m_data, val); + } + explicit gmp_int(const mpq_t val) + { + mpz_init(this->m_data); + mpz_set_q(this->m_data, val); + } + template + explicit gmp_int(const gmp_float& o) + { + mpz_init(this->m_data); + mpz_set_f(this->m_data, o.data()); + } + explicit gmp_int(const gmp_rational& o); + gmp_int& operator = (const gmp_int& o) + { + if(o.m_data[0]._mp_d) + mpz_set(m_data, o.m_data); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_int& operator = (gmp_int&& o) BOOST_NOEXCEPT + { + mpz_swap(m_data, o.m_data); + return *this; + } +#endif + gmp_int& operator = (unsigned long long i) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + mpz_t t; + mpz_set_ui(m_data, 0); + mpz_init_set_ui(t, 0); + while(i) + { + mpz_set_ui(t, static_cast(i & mask)); + if(shift) + mpz_mul_2exp(t, t, shift); + mpz_add(m_data, m_data, t); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpz_clear(t); + return *this; + } + gmp_int& operator = (long long i) + { + BOOST_MP_USING_ABS + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + mpz_neg(m_data, m_data); + return *this; + } + gmp_int& operator = (unsigned long i) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_ui(m_data, i); + return *this; + } + gmp_int& operator = (long i) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_si(m_data, i); + return *this; + } + gmp_int& operator = (double d) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_d(m_data, d); + return *this; + } + gmp_int& operator = (long double a) + { + using std::frexp; + using std::ldexp; + using std::floor; + + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + + if (a == 0) { + mpz_set_si(m_data, 0); + return *this; + } + + if (a == 1) { + mpz_set_si(m_data, 1); + return *this; + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + mpz_set_ui(m_data, 0u); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpz_mul_2exp(m_data, m_data, shift); + if(term > 0) + mpz_add_ui(m_data, m_data, static_cast(term)); + else + mpz_sub_ui(m_data, m_data, static_cast(-term)); + f -= term; + } + if(e > 0) + mpz_mul_2exp(m_data, m_data, e); + else if(e < 0) + mpz_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_int& operator = (const char* s) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + std::size_t n = s ? std::strlen(s) : 0; + int radix = 10; + if(n && (*s == '0')) + { + if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) + { + radix = 16; + s +=2; + n -= 2; + } + else + { + radix = 8; + n -= 1; + } + } + if(n) + { + if(0 != mpz_set_str(m_data, s, radix)) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer."))); + } + else + mpz_set_ui(m_data, 0); + return *this; + } + gmp_int& operator=(const mpf_t val) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_f(this->m_data, val); + return *this; + } + gmp_int& operator=(const mpz_t val) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set(this->m_data, val); + return *this; + } + gmp_int& operator=(const mpq_t val) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_q(this->m_data, val); + return *this; + } + template + gmp_int& operator=(const gmp_float& o) + { + if(m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_f(this->m_data, o.data()); + return *this; + } + gmp_int& operator=(const gmp_rational& o); + void swap(gmp_int& o) + { + mpz_swap(m_data, o.m_data); + } + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const + { + BOOST_ASSERT(m_data[0]._mp_d); + + int base = 10; + if((f & std::ios_base::oct) == std::ios_base::oct) + base = 8; + else if((f & std::ios_base::hex) == std::ios_base::hex) + base = 16; + // + // sanity check, bases 8 and 16 are only available for positive numbers: + // + if((base != 10) && (mpz_sgn(m_data) < 0)) + BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); + void *(*alloc_func_ptr) (size_t); + void *(*realloc_func_ptr) (void *, size_t, size_t); + void (*free_func_ptr) (void *, size_t); + const char* ps = mpz_get_str (0, base, m_data); + std::string s = ps; + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); + + if((base != 10) && (f & std::ios_base::showbase)) + { + int pos = s[0] == '-' ? 1 : 0; + const char* pp = base == 8 ? "0" : "0x"; + s.insert(pos, pp); + } + if((f & std::ios_base::showpos) && (s[0] != '-')) + s.insert(0, 1, '+'); + + return s; + } + ~gmp_int() + { + if(m_data[0]._mp_d) + mpz_clear(m_data); + } + void negate() + { + BOOST_ASSERT(m_data[0]._mp_d); + mpz_neg(m_data, m_data); + } + int compare(const gmp_int& o)const + { + BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); + return mpz_cmp(m_data, o.m_data); + } + int compare(long i)const + { + BOOST_ASSERT(m_data[0]._mp_d); + return mpz_cmp_si(m_data, i); + } + int compare(unsigned long i)const + { + BOOST_ASSERT(m_data[0]._mp_d); + return mpz_cmp_ui(m_data, i); + } + template + int compare(V v)const + { + gmp_int d; + d = v; + return compare(d); + } + mpz_t& data() + { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } + const mpz_t& data()const + { + BOOST_ASSERT(m_data[0]._mp_d); + return m_data; + } +protected: + mpz_t m_data; +}; + +template +inline typename enable_if, bool>::type eval_eq(const gmp_int& a, const T& b) +{ + return a.compare(b) == 0; +} +template +inline typename enable_if, bool>::type eval_lt(const gmp_int& a, const T& b) +{ + return a.compare(b) < 0; +} +template +inline typename enable_if, bool>::type eval_gt(const gmp_int& a, const T& b) +{ + return a.compare(b) > 0; +} + +inline bool eval_is_zero(const gmp_int& val) +{ + return mpz_sgn(val.data()) == 0; +} +inline void eval_add(gmp_int& t, const gmp_int& o) +{ + mpz_add(t.data(), t.data(), o.data()); +} +inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b) +{ + mpz_addmul(t.data(), a.data(), b.data()); +} +inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b) +{ + mpz_submul(t.data(), a.data(), b.data()); +} +inline void eval_subtract(gmp_int& t, const gmp_int& o) +{ + mpz_sub(t.data(), t.data(), o.data()); +} +inline void eval_multiply(gmp_int& t, const gmp_int& o) +{ + mpz_mul(t.data(), t.data(), o.data()); +} +inline void eval_divide(gmp_int& t, const gmp_int& o) +{ + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q(t.data(), t.data(), o.data()); +} +inline void eval_modulus(gmp_int& t, const gmp_int& o) +{ + mpz_tdiv_r(t.data(), t.data(), o.data()); +} +inline void eval_add(gmp_int& t, unsigned long i) +{ + mpz_add_ui(t.data(), t.data(), i); +} +inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i) +{ + mpz_addmul_ui(t.data(), a.data(), i); +} +inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i) +{ + mpz_submul_ui(t.data(), a.data(), i); +} +inline void eval_subtract(gmp_int& t, unsigned long i) +{ + mpz_sub_ui(t.data(), t.data(), i); +} +inline void eval_multiply(gmp_int& t, unsigned long i) +{ + mpz_mul_ui(t.data(), t.data(), i); +} +inline void eval_modulus(gmp_int& t, unsigned long i) +{ + mpz_tdiv_r_ui(t.data(), t.data(), i); +} +inline void eval_divide(gmp_int& t, unsigned long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), t.data(), i); +} +inline void eval_add(gmp_int& t, long i) +{ + if(i > 0) + mpz_add_ui(t.data(), t.data(), i); + else + mpz_sub_ui(t.data(), t.data(), -i); +} +inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i) +{ + if(i > 0) + mpz_addmul_ui(t.data(), a.data(), i); + else + mpz_submul_ui(t.data(), a.data(), -i); +} +inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i) +{ + if(i > 0) + mpz_submul_ui(t.data(), a.data(), i); + else + mpz_addmul_ui(t.data(), a.data(), -i); +} +inline void eval_subtract(gmp_int& t, long i) +{ + if(i > 0) + mpz_sub_ui(t.data(), t.data(), i); + else + mpz_add_ui(t.data(), t.data(), -i); +} +inline void eval_multiply(gmp_int& t, long i) +{ + mpz_mul_ui(t.data(), t.data(), std::abs(i)); + if(i < 0) + mpz_neg(t.data(), t.data()); +} +inline void eval_modulus(gmp_int& t, long i) +{ + mpz_tdiv_r_ui(t.data(), t.data(), std::abs(i)); +} +inline void eval_divide(gmp_int& t, long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), t.data(), std::abs(i)); + if(i < 0) + mpz_neg(t.data(), t.data()); +} +template +inline void eval_left_shift(gmp_int& t, UI i) +{ + mpz_mul_2exp(t.data(), t.data(), static_cast(i)); +} +template +inline void eval_right_shift(gmp_int& t, UI i) +{ + mpz_fdiv_q_2exp(t.data(), t.data(), static_cast(i)); +} +template +inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i) +{ + mpz_mul_2exp(t.data(), v.data(), static_cast(i)); +} +template +inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i) +{ + mpz_fdiv_q_2exp(t.data(), v.data(), static_cast(i)); +} + +inline void eval_bitwise_and(gmp_int& result, const gmp_int& v) +{ + mpz_and(result.data(), result.data(), v.data()); +} + +inline void eval_bitwise_or(gmp_int& result, const gmp_int& v) +{ + mpz_ior(result.data(), result.data(), v.data()); +} + +inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v) +{ + mpz_xor(result.data(), result.data(), v.data()); +} + +inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o) +{ + mpz_add(t.data(), p.data(), o.data()); +} +inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o) +{ + mpz_sub(t.data(), p.data(), o.data()); +} +inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o) +{ + mpz_mul(t.data(), p.data(), o.data()); +} +inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o) +{ + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q(t.data(), p.data(), o.data()); +} +inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o) +{ + mpz_tdiv_r(t.data(), p.data(), o.data()); +} +inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i) +{ + mpz_add_ui(t.data(), p.data(), i); +} +inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i) +{ + mpz_sub_ui(t.data(), p.data(), i); +} +inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i) +{ + mpz_mul_ui(t.data(), p.data(), i); +} +inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i) +{ + mpz_tdiv_r_ui(t.data(), p.data(), i); +} +inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), p.data(), i); +} +inline void eval_add(gmp_int& t, const gmp_int& p, long i) +{ + if(i > 0) + mpz_add_ui(t.data(), p.data(), i); + else + mpz_sub_ui(t.data(), p.data(), -i); +} +inline void eval_subtract(gmp_int& t, const gmp_int& p, long i) +{ + if(i > 0) + mpz_sub_ui(t.data(), p.data(), i); + else + mpz_add_ui(t.data(), p.data(), -i); +} +inline void eval_multiply(gmp_int& t, const gmp_int& p, long i) +{ + mpz_mul_ui(t.data(), p.data(), std::abs(i)); + if(i < 0) + mpz_neg(t.data(), t.data()); +} +inline void eval_modulus(gmp_int& t, const gmp_int& p, long i) +{ + mpz_tdiv_r_ui(t.data(), p.data(), std::abs(i)); +} +inline void eval_divide(gmp_int& t, const gmp_int& p, long i) +{ + if(i == 0) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpz_tdiv_q_ui(t.data(), p.data(), std::abs(i)); + if(i < 0) + mpz_neg(t.data(), t.data()); +} + +inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v) +{ + mpz_and(result.data(), u.data(), v.data()); +} + +inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v) +{ + mpz_ior(result.data(), u.data(), v.data()); +} + +inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v) +{ + mpz_xor(result.data(), u.data(), v.data()); +} + +inline void eval_complement(gmp_int& result, const gmp_int& u) +{ + mpz_com(result.data(), u.data()); +} + +inline int eval_get_sign(const gmp_int& val) +{ + return mpz_sgn(val.data()); +} +inline void eval_convert_to(unsigned long* result, const gmp_int& val) +{ + if(0 == mpz_fits_ulong_p(val.data())) + { + *result = (std::numeric_limits::max)(); + } + else + *result = mpz_get_ui(val.data()); +} +inline void eval_convert_to(long* result, const gmp_int& val) +{ + if(0 == mpz_fits_slong_p(val.data())) + { + *result = (std::numeric_limits::max)(); + *result *= mpz_sgn(val.data()); + } + else + *result = mpz_get_si(val.data()); +} +inline void eval_convert_to(double* result, const gmp_int& val) +{ + *result = mpz_get_d(val.data()); +} + +inline void eval_abs(gmp_int& result, const gmp_int& val) +{ + mpz_abs(result.data(), val.data()); +} + +inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b) +{ + mpz_gcd(result.data(), a.data(), b.data()); +} +inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b) +{ + mpz_lcm(result.data(), a.data(), b.data()); +} +template +inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) +{ + mpz_gcd_ui(result.data(), a.data(), b); +} +template +inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) +{ + mpz_lcm_ui(result.data(), a.data(), b); +} +template +inline typename enable_if_c<(is_signed::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) +{ + mpz_gcd_ui(result.data(), a.data(), std::abs(b)); +} +template +inline typename enable_if_c::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) +{ + mpz_lcm_ui(result.data(), a.data(), std::abs(b)); +} + +inline unsigned eval_lsb(const gmp_int& val) +{ + int c = eval_get_sign(val); + if(c == 0) + { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if(c < 0) + { + BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); + } + return mpz_scan1(val.data(), 0); +} + +inline bool eval_bit_test(const gmp_int& val, unsigned index) +{ + return mpz_tstbit(val.data(), index) ? true : false; +} + +inline void eval_bit_set(gmp_int& val, unsigned index) +{ + mpz_setbit(val.data(), index); +} + +inline void eval_bit_unset(gmp_int& val, unsigned index) +{ + mpz_clrbit(val.data(), index); +} + +inline void eval_bit_flip(gmp_int& val, unsigned index) +{ + mpz_combit(val.data(), index); +} + +inline void eval_qr(const gmp_int& x, const gmp_int& y, + gmp_int& q, gmp_int& r) +{ + mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data()); +} + +template +inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) +{ + if((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits::max)())) + { + gmp_int r; + return mpz_tdiv_r_ui(r.data(), x.data(), val); + } + else + { + return default_ops::eval_integer_modulus(x, val); + } +} +template +inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) +{ + typedef typename make_unsigned::type unsigned_type; + return eval_integer_modulus(x, static_cast(std::abs(val))); +} +inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m) +{ + if(eval_get_sign(p) < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + mpz_powm(result.data(), base.data(), p.data(), m.data()); +} + +template +inline typename enable_if< + mpl::and_< + is_unsigned, + mpl::bool_ + > +>::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) +{ + mpz_powm_ui(result.data(), base.data(), p, m.data()); +} +template +inline typename enable_if< + mpl::and_< + is_signed, + mpl::bool_ + > +>::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) +{ + if(p < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + mpz_powm_ui(result.data(), base.data(), p, m.data()); +} + +struct gmp_rational; +void eval_add(gmp_rational& t, const gmp_rational& o); + +struct gmp_rational +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + + gmp_rational() + { + mpq_init(this->m_data); + } + gmp_rational(const gmp_rational& o) + { + mpq_init(m_data); + if(o.m_data[0]._mp_num._mp_d) + mpq_set(m_data, o.m_data); + } + gmp_rational(const gmp_int& o) + { + mpq_init(m_data); + mpq_set_z(m_data, o.data()); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT + { + m_data[0]._mp_num = o.data()[0]._mp_num; + m_data[0]._mp_den = o.data()[0]._mp_den; + o.m_data[0]._mp_num._mp_d = 0; + o.m_data[0]._mp_den._mp_d = 0; + } +#endif + gmp_rational(const mpq_t o) + { + mpq_init(m_data); + mpq_set(m_data, o); + } + gmp_rational(const mpz_t o) + { + mpq_init(m_data); + mpq_set_z(m_data, o); + } + gmp_rational& operator = (const gmp_rational& o) + { + if(o.m_data[0]._mp_num._mp_d) + mpq_set(m_data, o.m_data); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + gmp_rational& operator = (gmp_rational&& o) BOOST_NOEXCEPT + { + mpq_swap(m_data, o.m_data); + return *this; + } +#endif + gmp_rational& operator = (unsigned long long i) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + mpq_t t; + mpq_set_ui(m_data, 0, 1); + mpq_init(t); + while(i) + { + mpq_set_ui(t, static_cast(i & mask), 1); + if(shift) + mpq_mul_2exp(t, t, shift); + mpq_add(m_data, m_data, t); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpq_clear(t); + return *this; + } + gmp_rational& operator = (long long i) + { + BOOST_MP_USING_ABS + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + mpq_neg(m_data, m_data); + return *this; + } + gmp_rational& operator = (unsigned long i) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_ui(m_data, i, 1); + return *this; + } + gmp_rational& operator = (long i) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_si(m_data, i, 1); + return *this; + } + gmp_rational& operator = (double d) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_d(m_data, d); + return *this; + } + gmp_rational& operator = (long double a) + { + using std::frexp; + using std::ldexp; + using std::floor; + using default_ops::eval_add; + using default_ops::eval_subtract; + + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + + if (a == 0) { + mpq_set_si(m_data, 0, 1); + return *this; + } + + if (a == 1) { + mpq_set_si(m_data, 1, 1); + return *this; + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + mpq_set_ui(m_data, 0, 1); + mpq_set_ui(m_data, 0u, 1); + gmp_rational t; + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + mpq_mul_2exp(m_data, m_data, shift); + t = static_cast(term); + eval_add(*this, t); + f -= term; + } + if(e > 0) + mpq_mul_2exp(m_data, m_data, e); + else if(e < 0) + mpq_div_2exp(m_data, m_data, -e); + return *this; + } + gmp_rational& operator = (const char* s) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + if(0 != mpq_set_str(m_data, s, 10)) + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number."))); + return *this; + } + gmp_rational& operator=(const gmp_int& o) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_z(m_data, o.data()); + return *this; + } + gmp_rational& operator=(const mpq_t o) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set(m_data, o); + return *this; + } + gmp_rational& operator=(const mpz_t o) + { + if(m_data[0]._mp_den._mp_d == 0) + mpq_init(m_data); + mpq_set_z(m_data, o); + return *this; + } + void swap(gmp_rational& o) + { + mpq_swap(m_data, o.m_data); + } + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/)const + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + // TODO make a better job of this including handling of f!! + void *(*alloc_func_ptr) (size_t); + void *(*realloc_func_ptr) (void *, size_t, size_t); + void (*free_func_ptr) (void *, size_t); + const char* ps = mpq_get_str (0, 10, m_data); + std::string s = ps; + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); + return s; + } + ~gmp_rational() + { + if(m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d) + mpq_clear(m_data); + } + void negate() + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + mpq_neg(m_data, m_data); + } + int compare(const gmp_rational& o)const + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d); + return mpq_cmp(m_data, o.m_data); + } + template + int compare(V v)const + { + gmp_rational d; + d = v; + return compare(d); + } + int compare(unsigned long v)const + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return mpq_cmp_ui(m_data, v, 1); + } + int compare(long v)const + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return mpq_cmp_si(m_data, v, 1); + } + mpq_t& data() + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return m_data; + } + const mpq_t& data()const + { + BOOST_ASSERT(m_data[0]._mp_num._mp_d); + return m_data; + } +protected: + mpq_t m_data; +}; + +inline bool eval_is_zero(const gmp_rational& val) +{ + return mpq_sgn(val.data()) == 0; +} +template +inline bool eval_eq(gmp_rational& a, const T& b) +{ + return a.compare(b) == 0; +} +template +inline bool eval_lt(gmp_rational& a, const T& b) +{ + return a.compare(b) < 0; +} +template +inline bool eval_gt(gmp_rational& a, const T& b) +{ + return a.compare(b) > 0; +} + +inline void eval_add(gmp_rational& t, const gmp_rational& o) +{ + mpq_add(t.data(), t.data(), o.data()); +} +inline void eval_subtract(gmp_rational& t, const gmp_rational& o) +{ + mpq_sub(t.data(), t.data(), o.data()); +} +inline void eval_multiply(gmp_rational& t, const gmp_rational& o) +{ + mpq_mul(t.data(), t.data(), o.data()); +} +inline void eval_divide(gmp_rational& t, const gmp_rational& o) +{ + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpq_div(t.data(), t.data(), o.data()); +} +inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) +{ + mpq_add(t.data(), p.data(), o.data()); +} +inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) +{ + mpq_sub(t.data(), p.data(), o.data()); +} +inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) +{ + mpq_mul(t.data(), p.data(), o.data()); +} +inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) +{ + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); + mpq_div(t.data(), p.data(), o.data()); +} + +inline int eval_get_sign(const gmp_rational& val) +{ + return mpq_sgn(val.data()); +} +inline void eval_convert_to(double* result, const gmp_rational& val) +{ + *result = mpq_get_d(val.data()); +} + +inline void eval_convert_to(long* result, const gmp_rational& val) +{ + double r; + eval_convert_to(&r, val); + *result = static_cast(r); +} + +inline void eval_convert_to(unsigned long* result, const gmp_rational& val) +{ + double r; + eval_convert_to(&r, val); + *result = static_cast(r); +} + +inline void eval_abs(gmp_rational& result, const gmp_rational& val) +{ + mpq_abs(result.data(), val.data()); +} + +inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2) +{ + mpq_set_ui(result.data(), v1, v2); + mpq_canonicalize(result.data()); +} +inline void assign_components(gmp_rational& result, long v1, long v2) +{ + mpq_set_si(result.data(), v1, v2); + mpq_canonicalize(result.data()); +} +inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2) +{ + mpz_set(mpq_numref(result.data()), v1.data()); + mpz_set(mpq_denref(result.data()), v2.data()); + mpq_canonicalize(result.data()); +} + +// +// Some member functions that are dependent upon previous code go here: +// +template +template +inline gmp_float::gmp_float(const gmp_float& o, typename enable_if_c::type*) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); +} +template +template +inline gmp_float::gmp_float(const gmp_float& o, typename disable_if_c::type*) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); +} +template +inline gmp_float::gmp_float(const gmp_int& o) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_z(this->data(), o.data()); +} +template +inline gmp_float::gmp_float(const gmp_rational& o) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_q(this->data(), o.data()); +} +template +template +inline gmp_float& gmp_float::operator=(const gmp_float& o) +{ + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set(this->m_data, o.data()); + return *this; +} +template +inline gmp_float& gmp_float::operator=(const gmp_int& o) +{ + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_z(this->data(), o.data()); + return *this; +} +template +inline gmp_float& gmp_float::operator=(const gmp_rational& o) +{ + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); + mpf_set_q(this->data(), o.data()); + return *this; +} +inline gmp_float<0>::gmp_float(const gmp_int& o) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_z(this->data(), o.data()); +} +inline gmp_float<0>::gmp_float(const gmp_rational& o) +{ + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); + mpf_set_q(this->data(), o.data()); +} +inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o) +{ + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); + mpf_set_z(this->data(), o.data()); + return *this; +} +inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o) +{ + if(this->m_data[0]._mp_d == 0) + mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); + mpf_set_q(this->data(), o.data()); + return *this; +} +inline gmp_int::gmp_int(const gmp_rational& o) +{ + mpz_init(this->m_data); + mpz_set_q(this->m_data, o.data()); +} +inline gmp_int& gmp_int::operator=(const gmp_rational& o) +{ + if(this->m_data[0]._mp_d == 0) + mpz_init(this->m_data); + mpz_set_q(this->m_data, o.data()); + return *this; +} + +} //namespace backends + +using boost::multiprecision::backends::gmp_int; +using boost::multiprecision::backends::gmp_rational; +using boost::multiprecision::backends::gmp_float; + +template <> +struct component_type > +{ + typedef number type; +}; + +template +inline number numerator(const number& val) +{ + number result; + mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); + return result; +} +template +inline number denominator(const number& val) +{ + number result; + mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); + return result; +} + +#ifdef BOOST_NO_SFINAE_EXPR + +namespace detail{ + +template<> +struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; +template<> +struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; +template +struct is_explicitly_convertible, gmp_int> : public mpl::true_ {}; +template<> +struct is_explicitly_convertible : public mpl::true_ {}; +template +struct is_explicitly_convertible, gmp_float > : public mpl::true_ {}; + +} + +#endif + +template<> +struct number_category::type> : public mpl::int_{}; +template<> +struct number_category::type> : public mpl::int_{}; +template<> +struct number_category >::type> : public mpl::int_{}; + + +typedef number > mpf_float_50; +typedef number > mpf_float_100; +typedef number > mpf_float_500; +typedef number > mpf_float_1000; +typedef number > mpf_float; +typedef number mpz_int; +typedef number mpq_rational; + +}} // namespaces + +namespace std{ + +// +// numeric_limits [partial] specializations for the types declared in this header: +// +template +class numeric_limits, ExpressionTemplates> > +{ + typedef boost::multiprecision::number, ExpressionTemplates> number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // min and max values chosen so as to not cause segfaults when calling + // mpf_get_str on 64-bit Linux builds. Possibly we could use larger + // exponent values elsewhere. + // + BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT + { + return -(max)(); + } + BOOST_STATIC_CONSTEXPR int digits = static_cast((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1)); + BOOST_STATIC_CONSTEXPR int digits10 = Digits10; + // Have to allow for a possible extra limb inside the gmp data structure: + BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 2 + ((GMP_LIMB_BITS * 301L) / 1000L); + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 2; + BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits::digits - 1); + } + return value.second; + } + // What value should this be???? + BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT + { + // returns epsilon/2 + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), digits); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN; + BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L; + BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX; + BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = true; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest; + +private: + struct data_initializer + { + data_initializer() + { + std::numeric_limits > >::epsilon(); + std::numeric_limits > >::round_error(); + (std::numeric_limits > >::min)(); + (std::numeric_limits > >::max)(); + } + void do_nothing()const{} + }; + static const data_initializer initializer; +}; + +template +const typename numeric_limits, ExpressionTemplates> >::data_initializer numeric_limits, ExpressionTemplates> >::initializer; + +template +class numeric_limits, ExpressionTemplates> > +{ + typedef boost::multiprecision::number, ExpressionTemplates> number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = false; + static number_type (min)() BOOST_NOEXCEPT { return number_type(); } + static number_type (max)() BOOST_NOEXCEPT { return number_type(); } + static number_type lowest() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR int digits = 0; + BOOST_STATIC_CONSTEXPR int digits10 = 0; + BOOST_STATIC_CONSTEXPR int max_digits10 = 0; + BOOST_STATIC_CONSTEXPR bool is_signed = false; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 0; + static number_type epsilon() BOOST_NOEXCEPT { return number_type(); } + static number_type round_error() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return number_type(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type denorm_min() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; + +#endif + +template +class numeric_limits > +{ + typedef boost::multiprecision::number number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type (min)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type (max)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type lowest() BOOST_NOEXCEPT { return (min)(); } + BOOST_STATIC_CONSTEXPR int digits = INT_MAX; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() BOOST_NOEXCEPT { return number_type(); } + static number_type round_error() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return number_type(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type denorm_min() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; + +#endif + +template +class numeric_limits > +{ + typedef boost::multiprecision::number number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type (min)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type (max)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type lowest() BOOST_NOEXCEPT { return (min)(); } + // Digits are unbounded, use zero for now: + BOOST_STATIC_CONSTEXPR int digits = INT_MAX; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() BOOST_NOEXCEPT { return number_type(); } + static number_type round_error() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return number_type(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type denorm_min() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; + +#endif + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace std + +#endif diff --git a/include/boost/multiprecision/integer.hpp b/include/boost/multiprecision/integer.hpp new file mode 100644 index 00000000..0e0075fb --- /dev/null +++ b/include/boost/multiprecision/integer.hpp @@ -0,0 +1,174 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_INTEGER_HPP +#define BOOST_MP_INTEGER_HPP + +#include + +namespace boost{ +namespace multiprecision{ + +template +typename enable_if_c::value && is_integral::value, Integer>::type + multiply(Integer& result, const I2& a, const I2& b) +{ + return result = static_cast(a) * static_cast(b); +} +template +typename enable_if_c::value && is_integral::value, Integer>::type + add(Integer& result, const I2& a, const I2& b) +{ + return result = static_cast(a) + static_cast(b); +} +template +typename enable_if_c::value && is_integral::value, Integer>::type + subtract(Integer& result, const I2& a, const I2& b) +{ + return result = static_cast(a) - static_cast(b); +} + +template +typename enable_if_c::value>::type divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r) +{ + q = x / y; + r = x % y; +} + +template +typename enable_if_c::value && is_integral::value, I2>::type integer_modulus(const I1& x, I2 val) +{ + return static_cast(x % val); +} + +namespace detail{ +// +// Figure out the kind of integer that has twice as many bits as some builtin +// integer type I. Use a native type if we can (including types which may not +// be recognised by boost::int_t because they're larger than long long), +// otherwise synthesize a cpp_int to do the job. +// +template +struct double_integer +{ + static const unsigned int_t_digits = + 2 * sizeof(I) <= sizeof(long long) ? std::numeric_limits::digits * 2 : 1; + + typedef typename mpl::if_c< + 2 * sizeof(I) <= sizeof(long long), + typename mpl::if_c< + is_signed::value, + typename boost::int_t::least, + typename boost::uint_t::least + >::type, + typename mpl::if_c< + 2 * sizeof(I) <= sizeof(double_limb_type), + typename mpl::if_c< + is_signed::value, + signed_double_limb_type, + double_limb_type + >::type, + number::value ? signed_magnitude : unsigned_magnitude), unchecked, void> > + >::type + >::type type; +}; + +} + +template +typename enable_if_c::value && is_integral::value && is_integral::value, I1>::type + powm(const I1& a, I2 b, I3 c) +{ + typedef typename detail::double_integer::type double_type; + + I1 x(1), y(a); + double_type result; + + while(b > 0) + { + if(b & 1) + { + multiply(result, x, y); + x = integer_modulus(result, c); + } + multiply(result, y, y); + y = integer_modulus(result, c); + b >>= 1; + } + return x % c; +} + +template +typename enable_if_c::value, unsigned>::type lsb(const Integer& val) +{ + if(val == 0) + { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if(val < 0) + { + BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); + } + unsigned index = 0; + Integer mask = 1; + + while(((mask & val) == 0) && (index < sizeof(Integer) * CHAR_BIT)) + { + ++index; + mask <<= 1; + } + return index; +} + +template +typename enable_if_c::value, bool>::type bit_test(const Integer& val, unsigned index) +{ + Integer mask = 1; + if(index >= sizeof(Integer) * CHAR_BIT) + return 0; + if(index) + mask <<= index; + return val & mask ? true : false; +} + +template +typename enable_if_c::value, Integer&>::type bit_set(Integer& val, unsigned index) +{ + Integer mask = 1; + if(index >= sizeof(Integer) * CHAR_BIT) + return val; + if(index) + mask <<= index; + val |= mask; + return val; +} + +template +typename enable_if_c::value, Integer&>::type bit_unset(Integer& val, unsigned index) +{ + Integer mask = 1; + if(index >= sizeof(Integer) * CHAR_BIT) + return val; + if(index) + mask <<= index; + val &= ~mask; + return val; +} + +template +typename enable_if_c::value, Integer&>::type bit_flip(Integer& val, unsigned index) +{ + Integer mask = 1; + if(index >= sizeof(Integer) * CHAR_BIT) + return val; + if(index) + mask <<= index; + val ^= mask; + return val; +} + +}} // namespaces + +#endif diff --git a/include/boost/multiprecision/miller_rabin.hpp b/include/boost/multiprecision/miller_rabin.hpp new file mode 100644 index 00000000..d62f103f --- /dev/null +++ b/include/boost/multiprecision/miller_rabin.hpp @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_MR_HPP +#define BOOST_MP_MR_HPP + +#include +#include + +namespace boost{ +namespace multiprecision{ +namespace detail{ + +template +bool check_small_factors(const I& n) +{ + static const boost::uint32_t small_factors1[] = { + 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u }; + static const boost::uint32_t pp1 = 223092870u; + + boost::uint32_t m1 = integer_modulus(n, pp1); + + for(unsigned i = 0; i < sizeof(small_factors1) / sizeof(small_factors1[0]); ++i) + { + BOOST_ASSERT(pp1 % small_factors1[i] == 0); + if(m1 % small_factors1[i] == 0) + return false; + } + + static const boost::uint32_t small_factors2[] = { + 29u, 31u, 37u, 41u, 43u, 47u }; + static const boost::uint32_t pp2 = 2756205443u; + + m1 = integer_modulus(n, pp2); + + for(unsigned i = 0; i < sizeof(small_factors2) / sizeof(small_factors2[0]); ++i) + { + BOOST_ASSERT(pp2 % small_factors2[i] == 0); + if(m1 % small_factors2[i] == 0) + return false; + } + + static const boost::uint32_t small_factors3[] = { + 53u, 59u, 61u, 67u, 71u }; + static const boost::uint32_t pp3 = 907383479u; + + m1 = integer_modulus(n, pp3); + + for(unsigned i = 0; i < sizeof(small_factors3) / sizeof(small_factors3[0]); ++i) + { + BOOST_ASSERT(pp3 % small_factors3[i] == 0); + if(m1 % small_factors3[i] == 0) + return false; + } + + static const boost::uint32_t small_factors4[] = { + 73u, 79u, 83u, 89u, 97u }; + static const boost::uint32_t pp4 = 4132280413u; + + m1 = integer_modulus(n, pp4); + + for(unsigned i = 0; i < sizeof(small_factors4) / sizeof(small_factors4[0]); ++i) + { + BOOST_ASSERT(pp4 % small_factors4[i] == 0); + if(m1 % small_factors4[i] == 0) + return false; + } + + static const boost::uint32_t small_factors5[6][4] = { + { 101u, 103u, 107u, 109u }, + { 113u, 127u, 131u, 137u }, + { 139u, 149u, 151u, 157u }, + { 163u, 167u, 173u, 179u }, + { 181u, 191u, 193u, 197u }, + { 199u, 211u, 223u, 227u } + }; + static const boost::uint32_t pp5[6] = + { + 121330189u, + 113u * 127u * 131u * 137u, + 139u * 149u * 151u * 157u, + 163u * 167u * 173u * 179u, + 181u * 191u * 193u * 197u, + 199u * 211u * 223u * 227u + }; + + for(unsigned k = 0; k < sizeof(pp5) / sizeof(*pp5); ++k) + { + m1 = integer_modulus(n, pp5[k]); + + for(unsigned i = 0; i < 4; ++i) + { + BOOST_ASSERT(pp5[k] % small_factors5[k][i] == 0); + if(m1 % small_factors5[k][i] == 0) + return false; + } + } + return true; +} + +inline bool is_small_prime(unsigned n) +{ + static const unsigned char p[] = + { + 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, + 37u, 41u, 43u, 47u, 53u, 59u, 61u, 67u, 71u, 73u, + 79u, 83u, 89u, 97u, 101u, 103u, 107u, 109u, 113u, + 127u, 131u, 137u, 139u, 149u, 151u, 157u, 163u, + 167u, 173u, 179u, 181u, 191u, 193u, 197u, 199u, + 211u, 223u, 227u + }; + for(unsigned i = 0; i < sizeof(p) / sizeof(*p); ++i) + { + if(n == p[i]) + return true; + } + return false; +} + +template +typename enable_if_c::value, unsigned>::type + cast_to_unsigned(const I& val) +{ + return static_cast(val); +} +template +typename disable_if_c::value, unsigned>::type + cast_to_unsigned(const I& val) +{ + return val.template convert_to(); +} + +} // namespace detail + +template +typename enable_if_c::value == number_kind_integer, bool>::type + miller_rabin_test(const I& n, unsigned trials, Engine& gen) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + typedef I number_type; + + if(bit_test(n, 0) == 0) + return false; // n is even + if(n <= 227) + return detail::is_small_prime(detail::cast_to_unsigned(n)); + + if(!detail::check_small_factors(n)) + return false; + + number_type nm1 = n - 1; + // + // Begin with a single Fermat test - it excludes a lot of candidates: + // + number_type q(228), x, y; // We know n is greater than this, as we've excluded small factors + x = powm(q, nm1, n); + if(x != 1u) + return false; + + q = n - 1; + unsigned k = lsb(q); + q >>= k; + + // Declare our random number generator: + boost::random::uniform_int_distribution dist(2, n - 2); + // + // Execute the trials: + // + for(unsigned i = 0; i < trials; ++i) + { + x = dist(gen); + y = powm(x, q, n); + unsigned j = 0; + while(true) + { + if(y == nm1) + break; + if(y == 1) + { + if(j == 0) + break; + return false; // test failed + } + if(++j == k) + return false; // failed + y = powm(y, 2, n); + } + } + return true; // Yeheh! probably prime. +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +typename enable_if_c::value == number_kind_integer, bool>::type + miller_rabin_test(const I& x, unsigned trials) +{ + static mt19937 gen; + return miller_rabin_test(x, trials, gen); +} + +template +bool miller_rabin_test(const detail::expression & n, unsigned trials, Engine& gen) +{ + typedef typename detail::expression::result_type number_type; + return miller_rabin_test(number_type(n), trials, gen); +} + +template +bool miller_rabin_test(const detail::expression & n, unsigned trials) +{ + typedef typename detail::expression::result_type number_type; + return miller_rabin_test(number_type(n), trials); +} + +}} // namespaces + +#endif + diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp new file mode 100644 index 00000000..4ee9e2d7 --- /dev/null +++ b/include/boost/multiprecision/mpfr.hpp @@ -0,0 +1,1666 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_BN_MPFR_HPP +#define BOOST_MATH_BN_MPFR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace multiprecision{ + +enum mpfr_allocation_type +{ + allocate_stack, + allocate_dynamic +}; + +namespace backends{ + +template +struct mpfr_float_backend; + +} // namespace backends + +template +struct number_category > : public mpl::int_{}; + +namespace backends{ + +namespace detail{ + +inline long get_default_precision() { return 50; } + +template +struct mpfr_float_imp; + +template +struct mpfr_float_imp +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef long exponent_type; + + mpfr_float_imp() + { + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + } + mpfr_float_imp(unsigned prec) + { + mpfr_init2(m_data, prec); + } + + mpfr_float_imp(const mpfr_float_imp& o) + { + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(o.m_data[0]._mpfr_d) + mpfr_set(m_data, o.m_data, GMP_RNDN); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_imp(mpfr_float_imp&& o) BOOST_NOEXCEPT + { + m_data[0] = o.m_data[0]; + o.m_data[0]._mpfr_d = 0; + } +#endif + mpfr_float_imp& operator = (const mpfr_float_imp& o) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(o.m_data[0]._mpfr_d) + mpfr_set(m_data, o.m_data, GMP_RNDN); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_imp& operator = (mpfr_float_imp&& o) BOOST_NOEXCEPT + { + mpfr_swap(m_data, o.m_data); + return *this; + } +#endif +#ifdef _MPFR_H_HAVE_INTMAX_T + mpfr_float_imp& operator = (unsigned long long i) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_uj(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long long i) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_sj(m_data, i, GMP_RNDN); + return *this; + } +#else + mpfr_float_imp& operator = (unsigned long long i) + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + mpfr_t t; + mpfr_init2(t, (std::max)(static_cast(std::numeric_limits::digits), static_cast(multiprecision::detail::digits10_2_2(digits10)))); + mpfr_set_ui(m_data, 0, GMP_RNDN); + while(i) + { + mpfr_set_ui(t, static_cast(i & mask), GMP_RNDN); + if(shift) + mpfr_mul_2exp(t, t, shift, GMP_RNDN); + mpfr_add(m_data, m_data, t, GMP_RNDN); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mpfr_clear(t); + return *this; + } + mpfr_float_imp& operator = (long long i) + { + BOOST_MP_USING_ABS + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + mpfr_neg(m_data, m_data, GMP_RNDN); + return *this; + } +#endif + mpfr_float_imp& operator = (unsigned long i) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_ui(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long i) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_si(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (double d) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_d(m_data, d, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long double a) BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + mpfr_set_ld(m_data, a, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (const char* s) + { + if(m_data[0]._mpfr_d == 0) + mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); + if(mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number."))); + } + return *this; + } + void swap(mpfr_float_imp& o) BOOST_NOEXCEPT + { + mpfr_swap(m_data, o.m_data); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + BOOST_ASSERT(m_data[0]._mpfr_d); + + bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + + std::streamsize org_digits(digits); + + if(scientific && digits) + ++digits; + + std::string result; + mp_exp_t e; + if(mpfr_inf_p(m_data)) + { + if(mpfr_sgn(m_data) < 0) + result = "-inf"; + else if(f & std::ios_base::showpos) + result = "+inf"; + else + result = "inf"; + return result; + } + if(mpfr_nan_p(m_data)) + { + result = "nan"; + return result; + } + if(mpfr_zero_p(m_data)) + { + e = 0; + result = "0"; + } + else + { + char* ps = mpfr_get_str (0, &e, 10, static_cast(digits), m_data, GMP_RNDN); + --e; // To match with what our formatter expects. + if(fixed && e != -1) + { + // Oops we actually need a different number of digits to what we asked for: + mpfr_free_str(ps); + digits += e + 1; + if(digits == 0) + { + // We need to get *all* the digits and then possibly round up, + // we end up with either "0" or "1" as the result. + ps = mpfr_get_str (0, &e, 10, 0, m_data, GMP_RNDN); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + if(ps[offset] > '5') + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else if(ps[offset] == '5') + { + unsigned i = offset + 1; + bool round_up = false; + while(ps[i] != 0) + { + if(ps[i] != '0') + { + round_up = true; + break; + } + } + if(round_up) + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else if(digits > 0) + { + ps = mpfr_get_str (0, &e, 10, static_cast(digits), m_data, GMP_RNDN); + --e; // To match with what our formatter expects. + } + else + { + ps = mpfr_get_str (0, &e, 10, 1, m_data, GMP_RNDN); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + result = ps ? ps : "0"; + if(ps) + mpfr_free_str(ps); + } + boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data)); + return result; + } + ~mpfr_float_imp() BOOST_NOEXCEPT + { + if(m_data[0]._mpfr_d) + mpfr_clear(m_data); + } + void negate() BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d); + mpfr_neg(m_data, m_data, GMP_RNDN); + } + template + int compare(const mpfr_float_backend& o)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d && o.m_data[0]._mpfr_d); + return mpfr_cmp(m_data, o.m_data); + } + int compare(long i)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d); + return mpfr_cmp_si(m_data, i); + } + int compare(unsigned long i)const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d); + return mpfr_cmp_ui(m_data, i); + } + template + int compare(V v)const BOOST_NOEXCEPT + { + mpfr_float_backend d; + d = v; + return compare(d); + } + mpfr_t& data() BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d); + return m_data; + } + const mpfr_t& data()const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_data[0]._mpfr_d); + return m_data; + } +protected: + mpfr_t m_data; + static unsigned& get_default_precision() BOOST_NOEXCEPT + { + static unsigned val = 50; + return val; + } +}; + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +template +struct mpfr_float_imp +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef long exponent_type; + + static const unsigned digits2 = (digits10 * 1000uL) / 301uL + ((digits10 * 1000uL) % 301 ? 2u : 1u); + static const unsigned limb_count = mpfr_custom_get_size(digits2) / sizeof(mp_limb_t); + + mpfr_float_imp() + { + mpfr_custom_init(m_buffer, digits2); + mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer); + } + + mpfr_float_imp(const mpfr_float_imp& o) + { + mpfr_custom_init(m_buffer, digits2); + mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer); + mpfr_set(m_data, o.m_data, GMP_RNDN); + } + mpfr_float_imp& operator = (const mpfr_float_imp& o) BOOST_NOEXCEPT + { + mpfr_set(m_data, o.m_data, GMP_RNDN); + return *this; + } +#ifdef _MPFR_H_HAVE_INTMAX_T + mpfr_float_imp& operator = (unsigned long long i) BOOST_NOEXCEPT + { + mpfr_set_uj(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long long i) BOOST_NOEXCEPT + { + mpfr_set_sj(m_data, i, GMP_RNDN); + return *this; + } +#else + mpfr_float_imp& operator = (unsigned long long i) + { + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + mpfr_t t; + mp_limb_t t_limbs[limb_count]; + mpfr_custom_init(t_limbs, digits2); + mpfr_custom_init_set(t, MPFR_NAN_KIND, 0, digits2, t_limbs); + mpfr_set_ui(m_data, 0, GMP_RNDN); + while(i) + { + mpfr_set_ui(t, static_cast(i & mask), GMP_RNDN); + if(shift) + mpfr_mul_2exp(t, t, shift, GMP_RNDN); + mpfr_add(m_data, m_data, t, GMP_RNDN); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + return *this; + } + mpfr_float_imp& operator = (long long i) + { + BOOST_MP_USING_ABS + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + mpfr_neg(m_data, m_data, GMP_RNDN); + return *this; + } +#endif + mpfr_float_imp& operator = (unsigned long i) BOOST_NOEXCEPT + { + mpfr_set_ui(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long i) BOOST_NOEXCEPT + { + mpfr_set_si(m_data, i, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (double d) BOOST_NOEXCEPT + { + mpfr_set_d(m_data, d, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (long double a) BOOST_NOEXCEPT + { + mpfr_set_ld(m_data, a, GMP_RNDN); + return *this; + } + mpfr_float_imp& operator = (const char* s) + { + if(mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number."))); + } + return *this; + } + void swap(mpfr_float_imp& o) BOOST_NOEXCEPT + { + // We have to swap by copying: + mpfr_float_imp t(*this); + *this = o; + o = t; + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + BOOST_ASSERT(m_data[0]._mpfr_d); + + bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; + bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; + + std::streamsize org_digits(digits); + + if(scientific && digits) + ++digits; + + std::string result; + mp_exp_t e; + if(mpfr_inf_p(m_data)) + { + if(mpfr_sgn(m_data) < 0) + result = "-inf"; + else if(f & std::ios_base::showpos) + result = "+inf"; + else + result = "inf"; + return result; + } + if(mpfr_nan_p(m_data)) + { + result = "nan"; + return result; + } + if(mpfr_zero_p(m_data)) + { + e = 0; + result = "0"; + } + else + { + char* ps = mpfr_get_str (0, &e, 10, static_cast(digits), m_data, GMP_RNDN); + --e; // To match with what our formatter expects. + if(fixed && e != -1) + { + // Oops we actually need a different number of digits to what we asked for: + mpfr_free_str(ps); + digits += e + 1; + if(digits == 0) + { + // We need to get *all* the digits and then possibly round up, + // we end up with either "0" or "1" as the result. + ps = mpfr_get_str (0, &e, 10, 0, m_data, GMP_RNDN); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + if(ps[offset] > '5') + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else if(ps[offset] == '5') + { + unsigned i = offset + 1; + bool round_up = false; + while(ps[i] != 0) + { + if(ps[i] != '0') + { + round_up = true; + break; + } + } + if(round_up) + { + ++e; + ps[offset] = '1'; + ps[offset + 1] = 0; + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else + { + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + else if(digits > 0) + { + ps = mpfr_get_str (0, &e, 10, static_cast(digits), m_data, GMP_RNDN); + --e; // To match with what our formatter expects. + } + else + { + ps = mpfr_get_str (0, &e, 10, 1, m_data, GMP_RNDN); + --e; + unsigned offset = *ps == '-' ? 1 : 0; + ps[offset] = '0'; + ps[offset + 1] = 0; + } + } + result = ps ? ps : "0"; + if(ps) + mpfr_free_str(ps); + } + boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data)); + return result; + } + void negate() BOOST_NOEXCEPT + { + mpfr_neg(m_data, m_data, GMP_RNDN); + } + template + int compare(const mpfr_float_backend& o)const BOOST_NOEXCEPT + { + return mpfr_cmp(m_data, o.m_data); + } + int compare(long i)const BOOST_NOEXCEPT + { + return mpfr_cmp_si(m_data, i); + } + int compare(unsigned long i)const BOOST_NOEXCEPT + { + return mpfr_cmp_ui(m_data, i); + } + template + int compare(V v)const BOOST_NOEXCEPT + { + mpfr_float_backend d; + d = v; + return compare(d); + } + mpfr_t& data() BOOST_NOEXCEPT + { + return m_data; + } + const mpfr_t& data()const BOOST_NOEXCEPT + { + return m_data; + } +protected: + mpfr_t m_data; + mp_limb_t m_buffer[limb_count]; +}; + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace detail + +template +struct mpfr_float_backend : public detail::mpfr_float_imp +{ + mpfr_float_backend() : detail::mpfr_float_imp() {} + mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp(o) {} +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_backend(mpfr_float_backend&& o) : detail::mpfr_float_imp(static_cast&&>(o)) {} +#endif + template + mpfr_float_backend(const mpfr_float_backend& val, typename enable_if_c::type* = 0) + : detail::mpfr_float_imp() + { + mpfr_set(this->m_data, val.data(), GMP_RNDN); + } + template + explicit mpfr_float_backend(const mpfr_float_backend& val, typename disable_if_c::type* = 0) + : detail::mpfr_float_imp() + { + mpfr_set(this->m_data, val.data(), GMP_RNDN); + } + template + mpfr_float_backend(const gmp_float& val, typename enable_if_c::type* = 0) + : detail::mpfr_float_imp() + { + mpfr_set_f(this->m_data, val.data(), GMP_RNDN); + } + template + mpfr_float_backend(const gmp_float& val, typename disable_if_c::type* = 0) + : detail::mpfr_float_imp() + { + mpfr_set_f(this->m_data, val.data(), GMP_RNDN); + } + mpfr_float_backend(const gmp_int& val) + : detail::mpfr_float_imp() + { + mpfr_set_z(this->m_data, val.data(), GMP_RNDN); + } + mpfr_float_backend(const gmp_rational& val) + : detail::mpfr_float_imp() + { + mpfr_set_q(this->m_data, val.data(), GMP_RNDN); + } + mpfr_float_backend(const mpfr_t val) + : detail::mpfr_float_imp() + { + mpfr_set(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpf_t val) + : detail::mpfr_float_imp() + { + mpfr_set_f(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpz_t val) + : detail::mpfr_float_imp() + { + mpfr_set_z(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpq_t val) + : detail::mpfr_float_imp() + { + mpfr_set_q(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend& operator=(const mpfr_float_backend& o) + { + *static_cast*>(this) = static_cast const&>(o); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT + { + *static_cast*>(this) = static_cast&&>(o); + return *this; + } +#endif + template + mpfr_float_backend& operator=(const V& v) + { + *static_cast*>(this) = v; + return *this; + } + mpfr_float_backend& operator=(const mpfr_t val)BOOST_NOEXCEPT + { + mpfr_set(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpf_t val)BOOST_NOEXCEPT + { + mpfr_set_f(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpz_t val)BOOST_NOEXCEPT + { + mpfr_set_z(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpq_t val)BOOST_NOEXCEPT + { + mpfr_set_q(this->m_data, val, GMP_RNDN); + return *this; + } + // We don't change our precision here, this is a fixed precision type: + template + mpfr_float_backend& operator=(const mpfr_float_backend& val) BOOST_NOEXCEPT + { + mpfr_set(this->m_data, val.data(), GMP_RNDN); + return *this; + } + template + mpfr_float_backend& operator=(const gmp_float& val) BOOST_NOEXCEPT + { + mpfr_set_f(this->m_data, val.data(), GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const gmp_int& val) BOOST_NOEXCEPT + { + mpfr_set_z(this->m_data, val.data(), GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const gmp_rational& val) BOOST_NOEXCEPT + { + mpfr_set_q(this->m_data, val.data(), GMP_RNDN); + return *this; + } +}; + +template <> +struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0, allocate_dynamic> +{ + mpfr_float_backend() : detail::mpfr_float_imp<0, allocate_dynamic>() {} + mpfr_float_backend(const mpfr_t val) + : detail::mpfr_float_imp<0, allocate_dynamic>(mpfr_get_prec(val)) + { + mpfr_set(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpf_t val) + : detail::mpfr_float_imp<0, allocate_dynamic>(mpf_get_prec(val)) + { + mpfr_set_f(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpz_t val) + : detail::mpfr_float_imp<0, allocate_dynamic>() + { + mpfr_set_z(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpq_t val) + : detail::mpfr_float_imp<0, allocate_dynamic>() + { + mpfr_set_q(this->m_data, val, GMP_RNDN); + } + mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<0, allocate_dynamic>(o) {} +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_backend(mpfr_float_backend&& o) BOOST_NOEXCEPT : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast&&>(o)) {} +#endif + mpfr_float_backend(const mpfr_float_backend& o, unsigned digits10) + : detail::mpfr_float_imp<0, allocate_dynamic>(digits10) + { + *this = o; + } + template + mpfr_float_backend(const mpfr_float_backend& val) + : detail::mpfr_float_imp<0, allocate_dynamic>(mpfr_get_prec(val.data())) + { + mpfr_set(this->m_data, val.data(), GMP_RNDN); + } + template + mpfr_float_backend(const gmp_float& val) + : detail::mpfr_float_imp<0, allocate_dynamic>(mpf_get_prec(val.data())) + { + mpfr_set_f(this->m_data, val.data(), GMP_RNDN); + } + mpfr_float_backend(const gmp_int& val) + : detail::mpfr_float_imp<0, allocate_dynamic>() + { + mpfr_set_z(this->m_data, val.data(), GMP_RNDN); + } + mpfr_float_backend(const gmp_rational& val) + : detail::mpfr_float_imp<0, allocate_dynamic>() + { + mpfr_set_q(this->m_data, val.data(), GMP_RNDN); + } + + mpfr_float_backend& operator=(const mpfr_float_backend& o) + { + mpfr_set_prec(this->m_data, mpfr_get_prec(o.data())); + mpfr_set(this->m_data, o.data(), GMP_RNDN); + return *this; + } +#ifndef BOOST_NO_RVALUE_REFERENCES + mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT + { + *static_cast*>(this) = static_cast &&>(o); + return *this; + } +#endif + template + mpfr_float_backend& operator=(const V& v) + { + *static_cast*>(this) = v; + return *this; + } + mpfr_float_backend& operator=(const mpfr_t val) BOOST_NOEXCEPT + { + mpfr_set_prec(this->m_data, mpfr_get_prec(val)); + mpfr_set(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpf_t val) BOOST_NOEXCEPT + { + mpfr_set_prec(this->m_data, mpf_get_prec(val)); + mpfr_set_f(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpz_t val) BOOST_NOEXCEPT + { + mpfr_set_z(this->m_data, val, GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const mpq_t val) BOOST_NOEXCEPT + { + mpfr_set_q(this->m_data, val, GMP_RNDN); + return *this; + } + template + mpfr_float_backend& operator=(const mpfr_float_backend& val) BOOST_NOEXCEPT + { + mpfr_set_prec(this->m_data, mpfr_get_prec(val.data())); + mpfr_set(this->m_data, val.data(), GMP_RNDN); + return *this; + } + template + mpfr_float_backend& operator=(const gmp_float& val) BOOST_NOEXCEPT + { + mpfr_set_prec(this->m_data, mpf_get_prec(val.data())); + mpfr_set_f(this->m_data, val.data(), GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const gmp_int& val) BOOST_NOEXCEPT + { + mpfr_set_z(this->m_data, val.data(), GMP_RNDN); + return *this; + } + mpfr_float_backend& operator=(const gmp_rational& val) BOOST_NOEXCEPT + { + mpfr_set_q(this->m_data, val.data(), GMP_RNDN); + return *this; + } + static unsigned default_precision() BOOST_NOEXCEPT + { + return get_default_precision(); + } + static void default_precision(unsigned v) BOOST_NOEXCEPT + { + get_default_precision() = v; + } + unsigned precision()const BOOST_NOEXCEPT + { + return multiprecision::detail::digits2_2_10(mpfr_get_prec(this->m_data)); + } + void precision(unsigned digits10) BOOST_NOEXCEPT + { + mpfr_set_prec(this->m_data, multiprecision::detail::digits2_2_10((digits10))); + } +}; + +template +inline typename enable_if, bool>::type eval_eq(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) == 0; +} +template +inline typename enable_if, bool>::type eval_lt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) < 0; +} +template +inline typename enable_if, bool>::type eval_gt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +{ + return a.compare(b) > 0; +} + +template +inline void eval_add(mpfr_float_backend& result, const mpfr_float_backend& o) BOOST_NOEXCEPT +{ + mpfr_add(result.data(), result.data(), o.data(), GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& result, const mpfr_float_backend& o) BOOST_NOEXCEPT +{ + mpfr_sub(result.data(), result.data(), o.data(), GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& result, const mpfr_float_backend& o) BOOST_NOEXCEPT +{ + mpfr_mul(result.data(), result.data(), o.data(), GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& result, const mpfr_float_backend& o) +{ + mpfr_div(result.data(), result.data(), o.data(), GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& result, unsigned long i) BOOST_NOEXCEPT +{ + mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& result, unsigned long i) BOOST_NOEXCEPT +{ + mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& result, unsigned long i) BOOST_NOEXCEPT +{ + mpfr_mul_ui(result.data(), result.data(), i, GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& result, unsigned long i) +{ + mpfr_div_ui(result.data(), result.data(), i, GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& result, long i) BOOST_NOEXCEPT +{ + if(i > 0) + mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN); + else + mpfr_sub_ui(result.data(), result.data(), std::abs(i), GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& result, long i) BOOST_NOEXCEPT +{ + if(i > 0) + mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN); + else + mpfr_add_ui(result.data(), result.data(), std::abs(i), GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& result, long i) BOOST_NOEXCEPT +{ + mpfr_mul_ui(result.data(), result.data(), std::abs(i), GMP_RNDN); + if(i < 0) + mpfr_neg(result.data(), result.data(), GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& result, long i) +{ + mpfr_div_ui(result.data(), result.data(), std::abs(i), GMP_RNDN); + if(i < 0) + mpfr_neg(result.data(), result.data(), GMP_RNDN); +} +// +// Specialised 3 arg versions of the basic operators: +// +template +inline void eval_add(mpfr_float_backend& a, const mpfr_float_backend& x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_add(a.data(), x.data(), y.data(), GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& a, const mpfr_float_backend& x, unsigned long y) BOOST_NOEXCEPT +{ + mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& a, const mpfr_float_backend& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + mpfr_sub_ui(a.data(), x.data(), -y, GMP_RNDN); + else + mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& a, unsigned long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN); +} +template +inline void eval_add(mpfr_float_backend& a, long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpfr_ui_sub(a.data(), -x, y.data(), GMP_RNDN); + mpfr_neg(a.data(), a.data(), GMP_RNDN); + } + else + mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& a, const mpfr_float_backend& x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_sub(a.data(), x.data(), y.data(), GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& a, const mpfr_float_backend& x, unsigned long y) BOOST_NOEXCEPT +{ + mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& a, const mpfr_float_backend& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + mpfr_add_ui(a.data(), x.data(), -y, GMP_RNDN); + else + mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& a, unsigned long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN); +} +template +inline void eval_subtract(mpfr_float_backend& a, long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpfr_add_ui(a.data(), y.data(), -x, GMP_RNDN); + mpfr_neg(a.data(), a.data(), GMP_RNDN); + } + else + mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN); +} + +template +inline void eval_multiply(mpfr_float_backend& a, const mpfr_float_backend& x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_mul(a.data(), x.data(), y.data(), GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& a, const mpfr_float_backend& x, unsigned long y) BOOST_NOEXCEPT +{ + mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& a, const mpfr_float_backend& x, long y) BOOST_NOEXCEPT +{ + if(y < 0) + { + mpfr_mul_ui(a.data(), x.data(), -y, GMP_RNDN); + a.negate(); + } + else + mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& a, unsigned long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN); +} +template +inline void eval_multiply(mpfr_float_backend& a, long x, const mpfr_float_backend& y) BOOST_NOEXCEPT +{ + if(x < 0) + { + mpfr_mul_ui(a.data(), y.data(), -x, GMP_RNDN); + mpfr_neg(a.data(), a.data(), GMP_RNDN); + } + else + mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN); +} + +template +inline void eval_divide(mpfr_float_backend& a, const mpfr_float_backend& x, const mpfr_float_backend& y) +{ + mpfr_div(a.data(), x.data(), y.data(), GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& a, const mpfr_float_backend& x, unsigned long y) +{ + mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& a, const mpfr_float_backend& x, long y) +{ + if(y < 0) + { + mpfr_div_ui(a.data(), x.data(), -y, GMP_RNDN); + a.negate(); + } + else + mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& a, unsigned long x, const mpfr_float_backend& y) +{ + mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN); +} +template +inline void eval_divide(mpfr_float_backend& a, long x, const mpfr_float_backend& y) +{ + if(x < 0) + { + mpfr_ui_div(a.data(), -x, y.data(), GMP_RNDN); + mpfr_neg(a.data(), a.data(), GMP_RNDN); + } + else + mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN); +} + +template +inline bool eval_is_zero(const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + return 0 != mpfr_zero_p(val.data()); +} +template +inline int eval_get_sign(const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + return mpfr_sgn(val.data()); +} + +template +inline void eval_convert_to(unsigned long* result, const mpfr_float_backend& val) +{ + if(mpfr_nan_p(val.data())) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); + } + *result = mpfr_get_ui(val.data(), GMP_RNDN); +} +template +inline void eval_convert_to(long* result, const mpfr_float_backend& val) +{ + if(mpfr_nan_p(val.data())) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); + } + *result = mpfr_get_si(val.data(), GMP_RNDN); +} +#ifdef _MPFR_H_HAVE_INTMAX_T +template +inline void eval_convert_to(unsigned long long* result, const mpfr_float_backend& val) +{ + if(mpfr_nan_p(val.data())) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); + } + *result = mpfr_get_uj(val.data(), GMP_RNDN); +} +template +inline void eval_convert_to(long long* result, const mpfr_float_backend& val) +{ + if(mpfr_nan_p(val.data())) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); + } + *result = mpfr_get_sj(val.data(), GMP_RNDN); +} +#endif +template +inline void eval_convert_to(double* result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + *result = mpfr_get_d(val.data(), GMP_RNDN); +} +template +inline void eval_convert_to(long double* result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + *result = mpfr_get_ld(val.data(), GMP_RNDN); +} + +// +// Native non-member operations: +// +template +inline void eval_sqrt(mpfr_float_backend& result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + mpfr_sqrt(result.data(), val.data(), GMP_RNDN); +} + +template +inline void eval_abs(mpfr_float_backend& result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + mpfr_abs(result.data(), val.data(), GMP_RNDN); +} + +template +inline void eval_fabs(mpfr_float_backend& result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + mpfr_abs(result.data(), val.data(), GMP_RNDN); +} +template +inline void eval_ceil(mpfr_float_backend& result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + mpfr_ceil(result.data(), val.data()); +} +template +inline void eval_floor(mpfr_float_backend& result, const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + mpfr_floor(result.data(), val.data()); +} +template +inline void eval_trunc(mpfr_float_backend& result, const mpfr_float_backend& val) +{ + if(0 == mpfr_number_p(val.data())) + { + result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number >(val), 0, boost::math::policies::policy<>()).backend(); + return; + } + mpfr_trunc(result.data(), val.data()); +} +template +inline void eval_ldexp(mpfr_float_backend& result, const mpfr_float_backend& val, long e) BOOST_NOEXCEPT +{ + if(e > 0) + mpfr_mul_2exp(result.data(), val.data(), e, GMP_RNDN); + else if(e < 0) + mpfr_div_2exp(result.data(), val.data(), -e, GMP_RNDN); + else + result = val; +} +template +inline void eval_frexp(mpfr_float_backend& result, const mpfr_float_backend& val, int* e) BOOST_NOEXCEPT +{ + long v; + mpfr_get_d_2exp(&v, val.data(), GMP_RNDN); + *e = v; + eval_ldexp(result, val, -v); +} +template +inline void eval_frexp(mpfr_float_backend& result, const mpfr_float_backend& val, long* e) BOOST_NOEXCEPT +{ + mpfr_get_d_2exp(e, val.data(), GMP_RNDN); + return eval_ldexp(result, val, -*e); +} + +template +inline int eval_fpclassify(const mpfr_float_backend& val) BOOST_NOEXCEPT +{ + return mpfr_inf_p(val.data()) ? FP_INFINITE : mpfr_nan_p(val.data()) ? FP_NAN : mpfr_zero_p(val.data()) ? FP_ZERO : FP_NORMAL; +} + +template +inline void eval_pow(mpfr_float_backend& result, const mpfr_float_backend& b, const mpfr_float_backend& e) BOOST_NOEXCEPT +{ + mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN); +} + +#ifdef BOOST_MSVC +// +// The enable_if usage below doesn't work with msvc - but only when +// certain other enable_if usages are defined first. It's a capricious +// and rather annoying compiler bug in other words.... +// +# define BOOST_MP_ENABLE_IF_WORKAROUND (Digits10 || !Digits10) && +#else +#define BOOST_MP_ENABLE_IF_WORKAROUND +#endif + +template +inline typename enable_if, mpl::bool_ > >::type eval_pow(mpfr_float_backend& result, const mpfr_float_backend& b, const Integer& e) BOOST_NOEXCEPT +{ + mpfr_pow_si(result.data(), b.data(), e, GMP_RNDN); +} + +template +inline typename enable_if, mpl::bool_ > >::type eval_pow(mpfr_float_backend& result, const mpfr_float_backend& b, const Integer& e) BOOST_NOEXCEPT +{ + mpfr_pow_ui(result.data(), b.data(), e, GMP_RNDN); +} + +#undef BOOST_MP_ENABLE_IF_WORKAROUND + +template +inline void eval_exp(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_exp(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_log(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_log(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_log10(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_log10(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_sin(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_sin(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_cos(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_cos(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_tan(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_tan(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_asin(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_asin(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_acos(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_acos(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_atan(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_atan(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_atan2(mpfr_float_backend& result, const mpfr_float_backend& arg1, const mpfr_float_backend& arg2) BOOST_NOEXCEPT +{ + mpfr_atan2(result.data(), arg1.data(), arg2.data(), GMP_RNDN); +} + +template +inline void eval_sinh(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_sinh(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_cosh(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_cosh(result.data(), arg.data(), GMP_RNDN); +} + +template +inline void eval_tanh(mpfr_float_backend& result, const mpfr_float_backend& arg) BOOST_NOEXCEPT +{ + mpfr_tanh(result.data(), arg.data(), GMP_RNDN); +} + +} // namespace backends + +#ifdef BOOST_NO_SFINAE_EXPR + +namespace detail{ + +template +struct is_explicitly_convertible, backends::mpfr_float_backend > : public mpl::true_ {}; + +} + +#endif + +template<> +struct number_category >::type> : public mpl::int_{}; + +using boost::multiprecision::backends::mpfr_float_backend; + +typedef number > mpfr_float_50; +typedef number > mpfr_float_100; +typedef number > mpfr_float_500; +typedef number > mpfr_float_1000; +typedef number > mpfr_float; + +typedef number > static_mpfr_float_50; +typedef number > static_mpfr_float_100; + +} // namespace multiprecision + +namespace math{ + +namespace tools{ + +template <> +inline int digits() BOOST_NOEXCEPT +{ + return boost::multiprecision::backends::detail::get_default_precision(); +} +template <> +inline int digits, boost::multiprecision::et_off> >() BOOST_NOEXCEPT +{ + return boost::multiprecision::backends::detail::get_default_precision(); +} + +} + +}} // namespaces + +namespace std{ + +// +// numeric_limits [partial] specializations for the types declared in this header: +// +template +class numeric_limits, ExpressionTemplates> > +{ + typedef boost::multiprecision::number, ExpressionTemplates> number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 0.5; + mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), -mpfr_get_emin(), GMP_RNDN); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 0.5; + mpfr_mul_2exp(value.second.backend().data(), value.second.backend().data(), mpfr_get_emax(), GMP_RNDN); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT + { + return -(max)(); + } + BOOST_STATIC_CONSTEXPR int digits = static_cast((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1)); + BOOST_STATIC_CONSTEXPR int digits10 = Digits10; + // Is this really correct??? + BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 2; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 2; + BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT + { + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits::digits - 1, GMP_RNDN); + } + return value.second; + } + // What value should this be???? + BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT + { + // returns epsilon/2 + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), digits, GMP_RNDN); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR long min_exponent = MPFR_EMIN_DEFAULT; + BOOST_STATIC_CONSTEXPR long min_exponent10 = (MPFR_EMIN_DEFAULT / 1000) * 301L; + BOOST_STATIC_CONSTEXPR long max_exponent = MPFR_EMAX_DEFAULT; + BOOST_STATIC_CONSTEXPR long max_exponent10 = (MPFR_EMAX_DEFAULT / 1000) * 301L; + BOOST_STATIC_CONSTEXPR bool has_infinity = true; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT + { + // returns epsilon/2 + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpfr_set_inf(value.second.backend().data(), 1); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT + { + // returns epsilon/2 + initializer.do_nothing(); + static std::pair value; + if(!value.first) + { + value.first = true; + value.second = 1; + mpfr_set_nan(value.second.backend().data()); + } + return value.second; + } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT + { + return number_type(0); + } + BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return number_type(0); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = true; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = true; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest; + +private: + struct data_initializer + { + data_initializer() + { + std::numeric_limits > >::epsilon(); + std::numeric_limits > >::round_error(); + (std::numeric_limits > >::min)(); + (std::numeric_limits > >::max)(); + std::numeric_limits > >::infinity(); + std::numeric_limits > >::quiet_NaN(); + } + void do_nothing()const{} + }; + static const data_initializer initializer; +}; + +template +const typename numeric_limits, ExpressionTemplates> >::data_initializer numeric_limits, ExpressionTemplates> >::initializer; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; + +#endif + + +template +class numeric_limits, ExpressionTemplates> > +{ + typedef boost::multiprecision::number, ExpressionTemplates> number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = false; + static number_type (min)() BOOST_NOEXCEPT { return number_type(0); } + static number_type (max)() BOOST_NOEXCEPT { return number_type(0); } + static number_type lowest() BOOST_NOEXCEPT { return number_type(0); } + BOOST_STATIC_CONSTEXPR int digits = 0; + BOOST_STATIC_CONSTEXPR int digits10 = 0; + BOOST_STATIC_CONSTEXPR int max_digits10 = 0; + BOOST_STATIC_CONSTEXPR bool is_signed = false; + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = false; + BOOST_STATIC_CONSTEXPR int radix = 0; + static number_type epsilon() BOOST_NOEXCEPT { return number_type(0); } + static number_type round_error() BOOST_NOEXCEPT { return number_type(0); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return number_type(0); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(0); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(0); } + static number_type denorm_min() BOOST_NOEXCEPT { return number_type(0); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; + +#endif +} // namespace std +#endif diff --git a/include/boost/multiprecision/number.hpp b/include/boost/multiprecision/number.hpp new file mode 100644 index 00000000..b408a36f --- /dev/null +++ b/include/boost/multiprecision/number.hpp @@ -0,0 +1,1782 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_EXTENDED_REAL_HPP +#define BOOST_MATH_EXTENDED_REAL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // stream operators +#include // EOF + +namespace boost{ namespace multiprecision{ + +#ifdef BOOST_MSVC +// warning C4127: conditional expression is constant +// warning C4714: function marked as __forceinline not inlined +#pragma warning(push) +#pragma warning(disable:4127 4714) +#endif + +template +class number +{ + typedef number self_type; +public: + typedef Backend backend_type; + BOOST_FORCEINLINE BOOST_CONSTEXPR number() BOOST_NOEXCEPT_IF(noexcept(Backend())) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast(std::declval())))) : m_backend(e.m_backend){} + template + BOOST_FORCEINLINE number(const V& v, typename enable_if_c< + (boost::is_arithmetic::value || is_same::value || is_convertible::value) + && !is_convertible::type, Backend>::value + && !detail::is_restricted_conversion::type, Backend>::value + >::type* = 0) + { + m_backend = canonical_value(v); + } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename enable_if_c< + is_convertible::type, Backend>::value + && !detail::is_restricted_conversion::type, Backend>::value + >::type* = 0) + : m_backend(canonical_value(v)) {} + BOOST_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10) + : m_backend(e.m_backend, digits10){} + template + explicit BOOST_FORCEINLINE number(const V& v, typename enable_if_c< + (boost::is_arithmetic::value || is_same::value || is_convertible::value) + && !detail::is_explicitly_convertible::type, Backend>::value + && detail::is_restricted_conversion::type, Backend>::value + >::type* = 0) + { + m_backend = canonical_value(v); + } + template + explicit BOOST_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename enable_if_c< + detail::is_explicitly_convertible::type, Backend>::value + && (detail::is_restricted_conversion::type, Backend>::value + || !is_convertible::type, Backend>::value) + >::type* = 0) + : m_backend(canonical_value(v)) {} + /* + // + // This conflicts with component based initialization (for rational and complex types) + // which is arguably more useful. Disabled for now. + // + template + number(V v, unsigned digits10, typename enable_if, is_same, is_convertible > >::type* dummy1 = 0) + { + m_backend.precision(digits10); + m_backend = canonical_value(v); + } + */ + template + BOOST_FORCEINLINE BOOST_CONSTEXPR number(const number& val) BOOST_NOEXCEPT_IF(noexcept(Backend(static_cast(std::declval())))) : m_backend(val.backend()) {} + + template + BOOST_FORCEINLINE number(const number& val, + typename enable_if_c<(boost::is_convertible::value && !detail::is_restricted_conversion::value)>::type* = 0) + BOOST_NOEXCEPT_IF(noexcept(std::declval() = std::declval())) + : m_backend(val.backend()) {} + + template + explicit number(const number& val, typename enable_if_c< + (!detail::is_explicitly_convertible::value) + >::type* = 0) + { + // + // Attempt a generic interconvertion: + // + detail::generic_interconvert(backend(), val.backend(), number_category(), number_category()); + } + template + explicit BOOST_FORCEINLINE number(const number& val, typename enable_if_c< + (detail::is_explicitly_convertible::value + && (detail::is_restricted_conversion::value || !boost::is_convertible::value)) + >::type* = 0) BOOST_NOEXCEPT_IF(noexcept(Backend(std::declval()))) + : m_backend(val.backend()) {} + + template + BOOST_FORCEINLINE number(V v1, V v2, typename enable_if, is_same, is_convertible > >::type* = 0) + { + using default_ops::assign_components; + assign_components(m_backend, canonical_value(v1), canonical_value(v2)); + } + template + BOOST_FORCEINLINE number(const number& v1, const number& v2, typename enable_if >::type* = 0) + { + using default_ops::assign_components; + assign_components(m_backend, v1.backend(), v2.backend()); + } + + template + typename enable_if::result_type, self_type>, number&>::type operator=(const detail::expression& e) + { + typedef typename is_same::result_type>::type tag_type; + do_assign(e, tag_type()); + return *this; + } + template + number& assign(const detail::expression& e) + { + typedef typename is_same::result_type>::type tag_type; + do_assign(e, tag_type()); + return *this; + } + + BOOST_FORCEINLINE number& operator=(const number& e) BOOST_NOEXCEPT_IF(noexcept(std::declval() = static_cast(std::declval()))) + { + m_backend = e.m_backend; + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number& >::type + operator=(const V& v) BOOST_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type>())) + { + m_backend = canonical_value(v); + return *this; + } + template + BOOST_FORCEINLINE number& assign(const V& v) BOOST_NOEXCEPT_IF(noexcept(std::declval() = std::declval::type>())) + { + m_backend = canonical_value(v); + return *this; + } + template + typename disable_if, number& >::type + assign(const number& v) + { + // + // Attempt a generic interconvertion: + // + detail::generic_interconvert(backend(), v.backend(), number_category(), number_category()); + return *this; + } + + template + number(const detail::expression& e, typename enable_if_c::result_type, self_type>::value>::type* = 0) + { + *this = e; + } + template + explicit number(const detail::expression& e, + typename enable_if_c::result_type, self_type>::value + && boost::multiprecision::detail::is_explicitly_convertible::result_type, self_type>::value>::type* = 0) + { + assign(e); + } + +#ifndef BOOST_NO_RVALUE_REFERENCES + BOOST_FORCEINLINE BOOST_CONSTEXPR number(number&& r) BOOST_NOEXCEPT : m_backend(static_cast(r.m_backend)){} + BOOST_FORCEINLINE number& operator=(number&& r) BOOST_NOEXCEPT + { + m_backend = static_cast(r.m_backend); + return *this; + } +#endif + + number& operator+=(const self_type& val) + { + do_add(detail::expression(val), detail::terminal()); + return *this; + } + + template + number& operator+=(const detail::expression& e) + { + // Create a copy if e contains this, but not if we're just doing a + // x += x + if(contains_self(e) && !is_self(e)) + { + self_type temp(e); + do_add(detail::expression(temp), detail::terminal()); + } + else + { + do_add(e, tag()); + } + return *this; + } + + template + number& operator+=(const detail::expression& e) + { + // + // Fused multiply-add: + // + using default_ops::eval_multiply_add; + eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref())); + return *this; + } + + template + typename enable_if, number& >::type + operator+=(const V& v) + { + using default_ops::eval_add; + eval_add(m_backend, canonical_value(v)); + return *this; + } + + number& operator-=(const self_type& val) + { + do_subtract(detail::expression(val), detail::terminal()); + return *this; + } + + template + number& operator-=(const detail::expression& e) + { + // Create a copy if e contains this: + if(contains_self(e)) + { + self_type temp(e); + do_subtract(detail::expression(temp), detail::terminal()); + } + else + { + do_subtract(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + typename enable_if, number& >::type + operator-=(const V& v) + { + using default_ops::eval_subtract; + eval_subtract(m_backend, canonical_value(v)); + return *this; + } + + template + number& operator-=(const detail::expression& e) + { + // + // Fused multiply-subtract: + // + using default_ops::eval_multiply_subtract; + eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref())); + return *this; + } + + + number& operator *= (const self_type& e) + { + do_multiplies(detail::expression(e), detail::terminal()); + return *this; + } + + template + number& operator*=(const detail::expression& e) + { + // Create a temporary if the RHS references *this, but not + // if we're just doing an x *= x; + if(contains_self(e) && !is_self(e)) + { + self_type temp(e); + do_multiplies(detail::expression(temp), detail::terminal()); + } + else + { + do_multiplies(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + typename enable_if, number& >::type + operator*=(const V& v) + { + using default_ops::eval_multiply; + eval_multiply(m_backend, canonical_value(v)); + return *this; + } + + number& operator%=(const self_type& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + do_modulus(detail::expression(e), detail::terminal()); + return *this; + } + template + number& operator%=(const detail::expression& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + // Create a temporary if the RHS references *this: + if(contains_self(e)) + { + self_type temp(e); + do_modulus(detail::expression(temp), detail::terminal()); + } + else + { + do_modulus(e, typename detail::expression::tag_type()); + } + return *this; + } + template + typename enable_if, number& >::type + operator%=(const V& v) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + using default_ops::eval_modulus; + eval_modulus(m_backend, canonical_value(v)); + return *this; + } + + // + // These operators are *not* proto-ized. + // The issue is that the increment/decrement must happen + // even if the result of the operator *is never used*. + // Possibly we could modify our expression wrapper to + // execute the increment/decrement on destruction, but + // correct implemetation will be tricky, so defered for now... + // + BOOST_FORCEINLINE number& operator++() + { + using default_ops::eval_increment; + eval_increment(m_backend); + return *this; + } + + BOOST_FORCEINLINE number& operator--() + { + using default_ops::eval_decrement; + eval_decrement(m_backend); + return *this; + } + + inline number operator++(int) + { + using default_ops::eval_increment; + self_type temp(*this); + eval_increment(m_backend); + return BOOST_MP_MOVE(temp); + } + + inline number operator--(int) + { + using default_ops::eval_decrement; + self_type temp(*this); + eval_decrement(m_backend); + return BOOST_MP_MOVE(temp); + } + + template + BOOST_FORCEINLINE typename enable_if, number&>::type operator <<= (V val) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left-shift operation is only valid for integer types"); + detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed()); + eval_left_shift(m_backend, canonical_value(val)); + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number&>::type operator >>= (V val) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right-shift operation is only valid for integer types"); + detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed()); + eval_right_shift(m_backend, canonical_value(val)); + return *this; + } + + BOOST_FORCEINLINE number& operator /= (const self_type& e) + { + do_divide(detail::expression(e), detail::terminal()); + return *this; + } + + template + number& operator/=(const detail::expression& e) + { + // Create a temporary if the RHS references *this: + if(contains_self(e)) + { + self_type temp(e); + do_divide(detail::expression(temp), detail::terminal()); + } + else + { + do_divide(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number& >::type + operator/=(const V& v) + { + using default_ops::eval_divide; + eval_divide(m_backend, canonical_value(v)); + return *this; + } + + BOOST_FORCEINLINE number& operator&=(const self_type& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + do_bitwise_and(detail::expression(e), detail::terminal()); + return *this; + } + + template + number& operator&=(const detail::expression& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + // Create a temporary if the RHS references *this, but not + // if we're just doing an x &= x; + if(contains_self(e) && !is_self(e)) + { + self_type temp(e); + do_bitwise_and(detail::expression(temp), detail::terminal()); + } + else + { + do_bitwise_and(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number& >::type + operator&=(const V& v) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + using default_ops::eval_bitwise_and; + eval_bitwise_and(m_backend, canonical_value(v)); + return *this; + } + + BOOST_FORCEINLINE number& operator|=(const self_type& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + do_bitwise_or(detail::expression(e), detail::terminal()); + return *this; + } + + template + number& operator|=(const detail::expression& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + // Create a temporary if the RHS references *this, but not + // if we're just doing an x |= x; + if(contains_self(e) && !is_self(e)) + { + self_type temp(e); + do_bitwise_or(detail::expression(temp), detail::terminal()); + } + else + { + do_bitwise_or(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number& >::type + operator|=(const V& v) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + using default_ops::eval_bitwise_or; + eval_bitwise_or(m_backend, canonical_value(v)); + return *this; + } + + BOOST_FORCEINLINE number& operator^=(const self_type& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + do_bitwise_xor(detail::expression(e), detail::terminal()); + return *this; + } + + template + number& operator^=(const detail::expression& e) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + if(contains_self(e)) + { + self_type temp(e); + do_bitwise_xor(detail::expression(temp), detail::terminal()); + } + else + { + do_bitwise_xor(e, typename detail::expression::tag_type()); + } + return *this; + } + + template + BOOST_FORCEINLINE typename enable_if, number& >::type + operator^=(const V& v) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(m_backend, canonical_value(v)); + return *this; + } + // + // Use in boolean context: + // + typedef bool (self_type::*unmentionable_type)()const; + + BOOST_FORCEINLINE operator unmentionable_type()const + { + return is_zero() ? 0 : &self_type::is_zero; + } + + // + // swap: + // + BOOST_FORCEINLINE void swap(self_type& other) BOOST_NOEXCEPT + { + m_backend.swap(other.backend()); + } + // + // Zero and sign: + // + BOOST_FORCEINLINE bool is_zero()const + { + using default_ops::eval_is_zero; + return eval_is_zero(m_backend); + } + BOOST_FORCEINLINE int sign()const + { + using default_ops::eval_get_sign; + return eval_get_sign(m_backend); + } + // + // String conversion functions: + // + std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0))const + { + return m_backend.str(digits, f); + } +private: + template + void convert_to_imp(T* result)const + { + using default_ops::eval_convert_to; + eval_convert_to(result, m_backend); + } + template + void convert_to_imp(number* result)const + { + result->assign(*this); + } + void convert_to_imp(std::string* result)const + { + *result = this->str(); + } +public: + template + T convert_to()const + { + T result; + convert_to_imp(&result); + return result; + } +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS +#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) + // + // Horrible workaround for gcc-4.6.x which always prefers the non-template + // operator bool() rather than the template operator when converting to + // an arithmetic type: + // + template , int>::type = 0> + explicit operator T ()const + { + using default_ops::eval_is_zero; + return !eval_is_zero(backend()); + } + template , int>::type = 0> + explicit operator T ()const + { + return this->template convert_to(); + } +#else + template + explicit operator T()const + { + return this->template convert_to(); + } + explicit operator bool()const + { + using default_ops::eval_is_zero; + return !eval_is_zero(backend()); + } +#endif +#endif + // + // Default precision: + // + static unsigned default_precision() BOOST_NOEXCEPT + { + return Backend::default_precision(); + } + static void default_precision(unsigned digits10) + { + Backend::default_precision(digits10); + } + unsigned precision()const BOOST_NOEXCEPT + { + return m_backend.precision(); + } + void precision(unsigned digits10) + { + m_backend.precision(digits10); + } + // + // Comparison: + // + BOOST_FORCEINLINE int compare(const number& o)const + BOOST_NOEXCEPT_IF(noexcept(std::declval().compare(std::declval()))) + { + return m_backend.compare(o.m_backend); + } + template + BOOST_FORCEINLINE typename enable_if, int>::type compare(const V& o)const + { + using default_ops::eval_get_sign; + if(o == 0) + return eval_get_sign(m_backend); + return m_backend.compare(canonical_value(o)); + } + BOOST_FORCEINLINE Backend& backend() BOOST_NOEXCEPT + { + return m_backend; + } + BOOST_FORCEINLINE const Backend& backend()const BOOST_NOEXCEPT + { + return m_backend; + } +private: + template + void do_assign(const detail::expression& e, const mpl::true_&) + { + do_assign(e, tag()); + } + template + void do_assign(const detail::expression& e, const mpl::false_&) + { + // The result of the expression isn't the same type as this - + // create a temporary result and assign it to *this: + typedef typename detail::expression::result_type temp_type; + temp_type t(e); + this->assign(t); + } + + + template + void do_assign(const Exp& e, const detail::add_immediates&) + { + using default_ops::eval_add; + eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + template + void do_assign(const Exp& e, const detail::subtract_immediates&) + { + using default_ops::eval_subtract; + eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + template + void do_assign(const Exp& e, const detail::multiply_immediates&) + { + using default_ops::eval_multiply; + eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + template + void do_assign(const Exp& e, const detail::multiply_add&) + { + using default_ops::eval_multiply_add; + eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value())); + } + template + void do_assign(const Exp& e, const detail::multiply_subtract&) + { + using default_ops::eval_multiply_subtract; + eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value())); + } + + template + void do_assign(const Exp& e, const detail::divide_immediates&) + { + using default_ops::eval_divide; + eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + + template + void do_assign(const Exp& e, const detail::negate&) + { + typedef typename Exp::left_type left_type; + do_assign(e.left(), typename left_type::tag_type()); + m_backend.negate(); + } + template + void do_assign(const Exp& e, const detail::plus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_add(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + // Ignore the right node, it's *this, just add the left: + do_add(e.left(), typename left_type::tag_type()); + } + else if(bl && br) + { + self_type temp(e); + temp.m_backend.swap(this->m_backend); + } + else if(!br && (bl || (left_depth >= right_depth))) + { // br is always false, but if bl is true we must take the this branch: + do_assign(e.left(), typename left_type::tag_type()); + do_add(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_add(e.left(), typename left_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::minus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just subtract the right: + do_subtract(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + // Ignore the right node, it's *this, just subtract the left and negate the result: + do_subtract(e.left(), typename left_type::tag_type()); + m_backend.negate(); + } + else if(bl && br) + { + self_type temp(e); + temp.m_backend.swap(this->m_backend); + } + else if(!br && (bl || (left_depth >= right_depth))) + { // br is always false, but if bl is true we must take the this branch: + do_assign(e.left(), typename left_type::tag_type()); + do_subtract(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_subtract(e.left(), typename left_type::tag_type()); + m_backend.negate(); + } + } + template + void do_assign(const Exp& e, const detail::multiplies&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_multiplies(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + // Ignore the right node, it's *this, just add the left: + do_multiplies(e.left(), typename left_type::tag_type()); + } + else if(bl && br) + { + self_type temp(e); + temp.m_backend.swap(this->m_backend); + } + else if(!br && (bl || (left_depth >= right_depth))) + { // br is always false, but if bl is true we must take the this branch: + do_assign(e.left(), typename left_type::tag_type()); + do_multiplies(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_multiplies(e.left(), typename left_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::divides&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_divide(e.right(), typename right_type::tag_type()); + } + else if(br) + { + self_type temp(e); + temp.m_backend.swap(this->m_backend); + } + else + { + do_assign(e.left(), typename left_type::tag_type()); + do_divide(e.right(), typename right_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::modulus&) + { + // + // This operation is only valid for integer backends: + // + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_modulus(e.right(), typename right_type::tag_type()); + } + else if(br) + { + self_type temp(e); + temp.m_backend.swap(this->m_backend); + } + else + { + do_assign(e.left(), typename left_type::tag_type()); + do_modulus(e.right(), typename right_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::modulus_immediates&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + using default_ops::eval_modulus; + eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + + template + void do_assign(const Exp& e, const detail::bitwise_and&) + { + // + // This operation is only valid for integer backends: + // + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_bitwise_and(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + do_bitwise_and(e.left(), typename left_type::tag_type()); + } + else if(!br && (bl || (left_depth >= right_depth))) + { + do_assign(e.left(), typename left_type::tag_type()); + do_bitwise_and(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_bitwise_and(e.left(), typename left_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::bitwise_and_immediates&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + using default_ops::eval_bitwise_and; + eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + + template + void do_assign(const Exp& e, const detail::bitwise_or&) + { + // + // This operation is only valid for integer backends: + // + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_bitwise_or(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + do_bitwise_or(e.left(), typename left_type::tag_type()); + } + else if(!br && (bl || (left_depth >= right_depth))) + { + do_assign(e.left(), typename left_type::tag_type()); + do_bitwise_or(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_bitwise_or(e.left(), typename left_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::bitwise_or_immediates&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + using default_ops::eval_bitwise_or; + eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + + template + void do_assign(const Exp& e, const detail::bitwise_xor&) + { + // + // This operation is only valid for integer backends: + // + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + + static int const left_depth = left_type::depth; + static int const right_depth = right_type::depth; + + bool bl = contains_self(e.left()); + bool br = contains_self(e.right()); + + if(bl && is_self(e.left())) + { + // Ignore the left node, it's *this, just add the right: + do_bitwise_xor(e.right(), typename right_type::tag_type()); + } + else if(br && is_self(e.right())) + { + do_bitwise_xor(e.left(), typename left_type::tag_type()); + } + else if(!br && (bl || (left_depth >= right_depth))) + { + do_assign(e.left(), typename left_type::tag_type()); + do_bitwise_xor(e.right(), typename right_type::tag_type()); + } + else + { + do_assign(e.right(), typename right_type::tag_type()); + do_bitwise_xor(e.left(), typename left_type::tag_type()); + } + } + template + void do_assign(const Exp& e, const detail::bitwise_xor_immediates&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "Bitwise operations are only valid for integer types"); + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value())); + } + template + void do_assign(const Exp& e, const detail::terminal&) + { + if(!is_self(e)) + { + m_backend = canonical_value(e.value()); + } + } + template + void do_assign(const Exp& e, const detail::function&) + { + typedef typename Exp::arity tag_type; + do_assign_function(e, tag_type()); + } + template + void do_assign(const Exp& e, const detail::shift_left&) + { + // We can only shift by an integer value, not an arbitrary expression: + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + typedef typename right_type::arity right_arity; + BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand."); + typedef typename right_type::result_type right_value_type; + BOOST_STATIC_ASSERT_MSG(is_integral::value, "The left shift operator requires an integer value for the shift operand."); + typedef typename left_type::tag_type tag_type; + do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type()); + } + + template + void do_assign(const Exp& e, const detail::shift_right&) + { + // We can only shift by an integer value, not an arbitrary expression: + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + typedef typename right_type::arity right_arity; + BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand."); + typedef typename right_type::result_type right_value_type; + BOOST_STATIC_ASSERT_MSG(is_integral::value, "The left shift operator requires an integer value for the shift operand."); + typedef typename left_type::tag_type tag_type; + do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type()); + } + + template + void do_assign(const Exp& e, const detail::bitwise_complement&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types"); + using default_ops::eval_complement; + self_type temp(e.left()); + eval_complement(m_backend, temp.backend()); + } + + template + void do_assign(const Exp& e, const detail::complement_immediates&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types"); + using default_ops::eval_complement; + eval_complement(m_backend, canonical_value(e.left().value())); + } + + template + void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right shift operation is only valid for integer types"); + using default_ops::eval_right_shift; + detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed()); + eval_right_shift(m_backend, canonical_value(e.value()), val); + } + + template + void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left shift operation is only valid for integer types"); + using default_ops::eval_left_shift; + detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed()); + eval_left_shift(m_backend, canonical_value(e.value()), val); + } + + template + void do_assign_right_shift(const Exp& e, const Val& val, const Tag&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The right shift operation is only valid for integer types"); + using default_ops::eval_right_shift; + self_type temp(e); + detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed()); + eval_right_shift(m_backend, temp.backend(), val); + } + + template + void do_assign_left_shift(const Exp& e, const Val& val, const Tag&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The left shift operation is only valid for integer types"); + using default_ops::eval_left_shift; + self_type temp(e); + detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed()); + eval_left_shift(m_backend, temp.backend(), val); + } + + template + void do_assign_function(const Exp& e, const mpl::int_<1>&) + { + e.left().value()(&m_backend); + } + template + void do_assign_function(const Exp& e, const mpl::int_<2>&) + { + typedef typename Exp::right_type right_type; + typedef typename right_type::tag_type tag_type; + do_assign_function_1(e.left().value(), e.right_ref(), tag_type()); + } + template + void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&) + { + f(m_backend, function_arg_value(val)); + } + template + void do_assign_function_1(const F& f, const Exp& val, const Tag&) + { + number t(val); + f(m_backend, t.backend()); + } + template + void do_assign_function(const Exp& e, const mpl::int_<3>&) + { + typedef typename Exp::middle_type middle_type; + typedef typename middle_type::tag_type tag_type; + typedef typename Exp::right_type end_type; + typedef typename end_type::tag_type end_tag; + do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag()); + } + template + void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&) + { + f(m_backend, function_arg_value(val1), function_arg_value(val2)); + } + template + void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&) + { + self_type temp1(val1); + f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2)); + } + template + void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&) + { + self_type temp2(val2); + f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend())); + } + template + void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&) + { + self_type temp1(val1); + self_type temp2(val2); + f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend())); + } + + template + void do_assign_function(const Exp& e, const mpl::int_<4>&) + { + typedef typename Exp::left_middle_type left_type; + typedef typename left_type::tag_type left_tag_type; + typedef typename Exp::right_middle_type middle_type; + typedef typename middle_type::tag_type middle_tag_type; + typedef typename Exp::right_type right_type; + typedef typename right_type::tag_type right_tag_type; + do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type()); + } + template + void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3) + { + do_assign_function_3b(f, val1, val2, val3, t2, t3); + } + template + void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3) + { + number t(val1); + do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3); + } + template + void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3) + { + do_assign_function_3c(f, val1, val2, val3, t3); + } + template + void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3) + { + number t(val2); + do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3); + } + template + void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&) + { + f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3)); + } + template + void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/) + { + number t(val3); + do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal()); + } + + template + void do_add(const Exp& e, const detail::terminal&) + { + using default_ops::eval_add; + eval_add(m_backend, canonical_value(e.value())); + } + + template + void do_add(const Exp& e, const detail::negate&) + { + typedef typename Exp::left_type left_type; + do_subtract(e.left(), typename left_type::tag_type()); + } + + template + void do_add(const Exp& e, const detail::plus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_add(e.left(), typename left_type::tag_type()); + do_add(e.right(), typename right_type::tag_type()); + } + + template + void do_add(const Exp& e, const detail::minus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_add(e.left(), typename left_type::tag_type()); + do_subtract(e.right(), typename right_type::tag_type()); + } + + template + void do_add(const Exp& e, const unknown&) + { + self_type temp(e); + do_add(detail::expression(temp), detail::terminal()); + } + + template + void do_add(const Exp& e, const detail::add_immediates&) + { + using default_ops::eval_add; + eval_add(m_backend, canonical_value(e.left().value())); + eval_add(m_backend, canonical_value(e.right().value())); + } + template + void do_add(const Exp& e, const detail::subtract_immediates&) + { + using default_ops::eval_add; + using default_ops::eval_subtract; + eval_add(m_backend, canonical_value(e.left().value())); + eval_subtract(m_backend, canonical_value(e.right().value())); + } + template + void do_subtract(const Exp& e, const detail::terminal&) + { + using default_ops::eval_subtract; + eval_subtract(m_backend, canonical_value(e.value())); + } + + template + void do_subtract(const Exp& e, const detail::negate&) + { + typedef typename Exp::left_type left_type; + do_add(e.left(), typename left_type::tag_type()); + } + + template + void do_subtract(const Exp& e, const detail::plus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_subtract(e.left(), typename left_type::tag_type()); + do_subtract(e.right(), typename right_type::tag_type()); + } + + template + void do_subtract(const Exp& e, const detail::minus&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_subtract(e.left(), typename left_type::tag_type()); + do_add(e.right(), typename right_type::tag_type()); + } + template + void do_subtract(const Exp& e, const detail::add_immediates&) + { + using default_ops::eval_subtract; + eval_subtract(m_backend, canonical_value(e.left().value())); + eval_subtract(m_backend, canonical_value(e.right().value())); + } + template + void do_subtract(const Exp& e, const detail::subtract_immediates&) + { + using default_ops::eval_add; + using default_ops::eval_subtract; + eval_subtract(m_backend, canonical_value(e.left().value())); + eval_add(m_backend, canonical_value(e.right().value())); + } + template + void do_subtract(const Exp& e, const unknown&) + { + self_type temp(e); + do_subtract(detail::expression(temp), detail::terminal()); + } + + template + void do_multiplies(const Exp& e, const detail::terminal&) + { + using default_ops::eval_multiply; + eval_multiply(m_backend, canonical_value(e.value())); + } + + template + void do_multiplies(const Exp& e, const detail::negate&) + { + typedef typename Exp::left_type left_type; + do_multiplies(e.left(), typename left_type::tag_type()); + m_backend.negate(); + } + + template + void do_multiplies(const Exp& e, const detail::multiplies&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_multiplies(e.left(), typename left_type::tag_type()); + do_multiplies(e.right(), typename right_type::tag_type()); + } + + template + void do_multiplies(const Exp& e, const detail::divides&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_multiplies(e.left(), typename left_type::tag_type()); + do_divide(e.right(), typename right_type::tag_type()); + } + + template + void do_multiplies(const Exp& e, const detail::multiply_immediates&) + { + using default_ops::eval_multiply; + eval_multiply(m_backend, canonical_value(e.left().value())); + eval_multiply(m_backend, canonical_value(e.right().value())); + } + template + void do_multiplies(const Exp& e, const detail::divide_immediates&) + { + using default_ops::eval_multiply; + using default_ops::eval_divide; + eval_multiply(m_backend, canonical_value(e.left().value())); + eval_divide(m_backend, canonical_value(e.right().value())); + } + template + void do_multiplies(const Exp& e, const unknown&) + { + using default_ops::eval_multiply; + self_type temp(e); + eval_multiply(m_backend, temp.m_backend); + } + + template + void do_divide(const Exp& e, const detail::terminal&) + { + using default_ops::eval_divide; + eval_divide(m_backend, canonical_value(e.value())); + } + + template + void do_divide(const Exp& e, const detail::negate&) + { + typedef typename Exp::left_type left_type; + do_divide(e.left(), typename left_type::tag_type()); + m_backend.negate(); + } + + template + void do_divide(const Exp& e, const detail::multiplies&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_divide(e.left(), typename left_type::tag_type()); + do_divide(e.right(), typename right_type::tag_type()); + } + + template + void do_divide(const Exp& e, const detail::divides&) + { + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_divide(e.left(), typename left_type::tag_type()); + do_multiplies(e.right(), typename right_type::tag_type()); + } + + template + void do_divides(const Exp& e, const detail::multiply_immediates&) + { + using default_ops::eval_divide; + eval_divide(m_backend, canonical_value(e.left().value())); + eval_divide(m_backend, canonical_value(e.right().value())); + } + template + void do_divides(const Exp& e, const detail::divide_immediates&) + { + using default_ops::eval_multiply; + using default_ops::eval_divide; + eval_divide(m_backend, canonical_value(e.left().value())); + mutiply(m_backend, canonical_value(e.right().value())); + } + + template + void do_divide(const Exp& e, const unknown&) + { + using default_ops::eval_multiply; + self_type temp(e); + eval_divide(m_backend, temp.m_backend); + } + + template + void do_modulus(const Exp& e, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + using default_ops::eval_modulus; + eval_modulus(m_backend, canonical_value(e.value())); + } + + template + void do_modulus(const Exp& e, const Unknown&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The modulus operation is only valid for integer types"); + using default_ops::eval_modulus; + self_type temp(e); + eval_modulus(m_backend, canonical_value(temp)); + } + + template + void do_bitwise_and(const Exp& e, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + using default_ops::eval_bitwise_and; + eval_bitwise_and(m_backend, canonical_value(e.value())); + } + template + void do_bitwise_and(const Exp& e, const detail::bitwise_and&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_bitwise_and(e.left(), typename left_type::tag_type()); + do_bitwise_and(e.right(), typename right_type::tag_type()); + } + template + void do_bitwise_and(const Exp& e, const unknown&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise & operation is only valid for integer types"); + using default_ops::eval_bitwise_and; + self_type temp(e); + eval_bitwise_and(m_backend, temp.m_backend); + } + + template + void do_bitwise_or(const Exp& e, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + using default_ops::eval_bitwise_or; + eval_bitwise_or(m_backend, canonical_value(e.value())); + } + template + void do_bitwise_or(const Exp& e, const detail::bitwise_or&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_bitwise_or(e.left(), typename left_type::tag_type()); + do_bitwise_or(e.right(), typename right_type::tag_type()); + } + template + void do_bitwise_or(const Exp& e, const unknown&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise | operation is only valid for integer types"); + using default_ops::eval_bitwise_or; + self_type temp(e); + eval_bitwise_or(m_backend, temp.m_backend); + } + + template + void do_bitwise_xor(const Exp& e, const detail::terminal&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + using default_ops::eval_bitwise_xor; + eval_bitwise_xor(m_backend, canonical_value(e.value())); + } + template + void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + typedef typename Exp::left_type left_type; + typedef typename Exp::right_type right_type; + do_bitwise_xor(e.left(), typename left_type::tag_type()); + do_bitwise_xor(e.right(), typename right_type::tag_type()); + } + template + void do_bitwise_xor(const Exp& e, const unknown&) + { + BOOST_STATIC_ASSERT_MSG(number_category::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types"); + using default_ops::eval_bitwise_xor; + self_type temp(e); + eval_bitwise_xor(m_backend, temp.m_backend); + } + + // Tests if the expression contains a reference to *this: + template + BOOST_FORCEINLINE bool contains_self(const Exp& e)const BOOST_NOEXCEPT + { + return contains_self(e, typename Exp::arity()); + } + template + BOOST_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT + { + return is_realy_self(e.value()); + } + template + BOOST_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<1> const&)const BOOST_NOEXCEPT + { + typedef typename Exp::left_type child_type; + return contains_self(e.left(), typename child_type::arity()); + } + template + BOOST_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<2> const&)const BOOST_NOEXCEPT + { + typedef typename Exp::left_type child0_type; + typedef typename Exp::right_type child1_type; + return contains_self(e.left(), typename child0_type::arity()) + || contains_self(e.right(), typename child1_type::arity()); + } + template + BOOST_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<3> const&)const BOOST_NOEXCEPT + { + typedef typename Exp::left_type child0_type; + typedef typename Exp::middle_type child1_type; + typedef typename Exp::right_type child2_type; + return contains_self(e.left(), typename child0_type::arity()) + || contains_self(e.middle(), typename child1_type::arity()) + || contains_self(e.right(), typename child2_type::arity()); + } + + // Test if the expression is a reference to *this: + template + BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e)const BOOST_NOEXCEPT + { + return is_self(e, typename Exp::arity()); + } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT + { + return is_realy_self(e.value()); + } + template + BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_ const&)const BOOST_NOEXCEPT + { + return false; + } + + template + BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; } + BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; } + + static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; } + template + static BOOST_FORCEINLINE const A1& function_arg_value(const detail::expression& exp) BOOST_NOEXCEPT { return exp.value(); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); } + Backend m_backend; + +public: + // + // These shouldn't really need to be public, or even member functions, but it makes implementing + // the non-member operators way easier if they are: + // + static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number& v) BOOST_NOEXCEPT { return v.backend(); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR typename disable_if::type, V>, typename detail::canonical::type>::type + canonical_value(const V& v) BOOST_NOEXCEPT { return static_cast::type>(v); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR typename enable_if::type, V>, const V&>::type + canonical_value(const V& v) BOOST_NOEXCEPT { return v; } + static BOOST_FORCEINLINE typename detail::canonical::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); } + +}; + +template +inline std::ostream& operator << (std::ostream& os, const number& r) +{ + std::streamsize d = os.precision(); + std::string s = r.str(d, os.flags()); + std::streamsize ss = os.width(); + if(ss > static_cast(s.size())) + { + char fill = os.fill(); + if((os.flags() & std::ios_base::left) == std::ios_base::left) + s.append(static_cast(ss - s.size()), fill); + else + s.insert(0, static_cast(ss - s.size()), fill); + } + return os << s; +} + +namespace detail{ + +template +inline std::ostream& operator << (std::ostream& os, const expression& r) +{ + typedef typename expression::result_type value_type; + value_type temp(r); + return os << temp; +} + +} // namespace detail + +template +inline std::istream& operator >> (std::istream& is, number& r) +{ + std::string s; + is >> s; + r.assign(s); + return is; +} + +template +BOOST_FORCEINLINE void swap(number& a, number& b) +{ + a.swap(b); +} + +} // namespace multipreciion + +template +class rational; + +template +inline std::istream& operator >> (std::istream& is, rational >& r) +{ + std::string s1; + multiprecision::number v1, v2; + char c; + bool have_hex = false; + + while((EOF != (c = static_cast(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + { + if(c == 'x' || c == 'X') + have_hex = true; + s1.append(1, c); + is.get(); + } + v1.assign(s1); + s1.erase(); + if(c == '/') + { + is.get(); + while((EOF != (c = static_cast(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + { + if(c == 'x' || c == 'X') + have_hex = true; + s1.append(1, c); + is.get(); + } + v2.assign(s1); + } + else + v2 = 1; + r.assign(v1, v2); + return is; +} + +template +typename enable_if, bool>::type operator == (const rational >& a, const Arithmetic& b) +{ + return a == multiprecision::number(b); +} + +template +typename enable_if, bool>::type operator == (const Arithmetic& b, const rational >& a) +{ + return a == multiprecision::number(b); +} + +template +typename enable_if, bool>::type operator != (const rational >& a, const Arithmetic& b) +{ + return a != multiprecision::number(b); +} + +template +typename enable_if, bool>::type operator != (const Arithmetic& b, const rational >& a) +{ + return a != multiprecision::number(b); +} + +template +inline multiprecision::number numerator(const rational >& a) +{ + return a.numerator(); +} + +template +inline multiprecision::number denominator(const rational >& a) +{ + return a.denominator(); +} + +namespace numeric { namespace ublas { +// +// uBlas interoperability: +// +template +class sparse_vector_element; + +template +inline bool operator == (const sparse_vector_element& a, const ::boost::multiprecision::number& b) +{ +typedef typename sparse_vector_element::const_reference ref_type; + return static_cast(a) == b; +} + +}} // namespaces + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespaces + +#endif diff --git a/include/boost/multiprecision/random.hpp b/include/boost/multiprecision/random.hpp new file mode 100644 index 00000000..fefba1b9 --- /dev/null +++ b/include/boost/multiprecision/random.hpp @@ -0,0 +1,587 @@ +/////////////////////////////////////////////////////////////// +// Copyright Jens Maurer 2006-1011 +// Copyright Steven Watanabe 2011 +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_RANDOM_HPP +#define BOOST_MP_RANDOM_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + +#include + +namespace boost{ namespace random{ namespace detail{ +// +// This is a horrible hack: this declaration has to appear before the definition of +// uniform_int_distribution, otherwise it won't be used... +// Need to find a better solution, like make Boost.Random safe to use with +// UDT's and depricate/remove this header altogether. +// +template +boost::multiprecision::number + generate_uniform_int(Engine& eng, const boost::multiprecision::number& min_value, const boost::multiprecision::number& max_value); + +}}} + +#include +#include + +namespace boost{ +namespace random{ +namespace detail{ + +template +struct subtract, true> +{ + typedef boost::multiprecision::number result_type; + result_type operator()(result_type const& x, result_type const& y) { return x - y; } +}; + +} + +template +class independent_bits_engine > +{ +public: + typedef Engine base_type; + typedef boost::multiprecision::number result_type; + + static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () + { return 0; } + // This is the only function we modify compared to the primary template: + static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () + { + // This expression allows for the possibility that w == std::numeric_limits::digits: + return (((result_type(1) << (w - 1)) - 1) << 1) + 1; + } + + independent_bits_engine() { } + + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(independent_bits_engine, + result_type, seed_arg) + { + _base.seed(seed_arg); + } + + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(independent_bits_engine, + SeedSeq, seq) + { _base.seed(seq); } + + independent_bits_engine(const base_type& base_arg) : _base(base_arg) {} + + template + independent_bits_engine(It& first, It last) : _base(first, last) { } + + void seed() { _base.seed(); } + + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(independent_bits_engine, + result_type, seed_arg) + { _base.seed(seed_arg); } + + BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(independent_bits_engine, + SeedSeq, seq) + { _base.seed(seq); } + + template void seed(It& first, It last) + { _base.seed(first, last); } + + result_type operator()() + { + // While it may seem wasteful to recalculate this + // every time, both msvc and gcc can propagate + // constants, resolving this at compile time. + base_unsigned range = + detail::subtract()((_base.max)(), (_base.min)()); + std::size_t m = + (range == (std::numeric_limits::max)()) ? + std::numeric_limits::digits : + detail::integer_log2(range + 1); + std::size_t n = (w + m - 1) / m; + std::size_t w0, n0; + base_unsigned y0, y1; + base_unsigned y0_mask, y1_mask; + calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask); + if(base_unsigned(range - y0 + 1) > y0 / n) { + // increment n and try again. + ++n; + calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask); + } + + BOOST_ASSERT(n0*w0 + (n - n0)*(w0 + 1) == w); + + result_type S = 0; + for(std::size_t k = 0; k < n0; ++k) { + base_unsigned u; + do { + u = detail::subtract()(_base(), (_base.min)()); + } while(u > base_unsigned(y0 - 1)); + S = (S << w0) + (u & y0_mask); + } + for(std::size_t k = 0; k < (n - n0); ++k) { + base_unsigned u; + do { + u = detail::subtract()(_base(), (_base.min)()); + } while(u > base_unsigned(y1 - 1)); + S = (S << (w0 + 1)) + (u & y1_mask); + } + return S; + } + + /** Fills a range with random values */ + template + void generate(Iter first, Iter last) + { detail::generate_from_int(*this, first, last); } + + /** Advances the state of the generator by @c z. */ + void discard(boost::uintmax_t z) + { + for(boost::uintmax_t i = 0; i < z; ++i) { + (*this)(); + } + } + + const base_type& base() const { return _base; } + + /** + * Writes the textual representation if the generator to a @c std::ostream. + * The textual representation of the engine is the textual representation + * of the base engine. + */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, independent_bits_engine, r) + { + os << r._base; + return os; + } + + /** + * Reads the state of an @c independent_bits_engine from a + * @c std::istream. + */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, independent_bits_engine, r) + { + is >> r._base; + return is; + } + + /** + * Returns: true iff the two @c independent_bits_engines will + * produce the same sequence of values. + */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(independent_bits_engine, x, y) + { return x._base == y._base; } + /** + * Returns: true iff the two @c independent_bits_engines will + * produce different sequences of values. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(independent_bits_engine) + +private: + + /// \cond show_private + typedef typename base_type::result_type base_result; + typedef typename make_unsigned::type base_unsigned; + + void calc_params( + std::size_t n, base_unsigned range, + std::size_t& w0, std::size_t& n0, + base_unsigned& y0, base_unsigned& y1, + base_unsigned& y0_mask, base_unsigned& y1_mask) + { + BOOST_ASSERT(w >= n); + w0 = w/n; + n0 = n - w % n; + y0_mask = (base_unsigned(2) << (w0 - 1)) - 1; + y1_mask = (y0_mask << 1) | 1; + y0 = (range + 1) & ~y0_mask; + y1 = (range + 1) & ~y1_mask; + BOOST_ASSERT(y0 != 0 || base_unsigned(range + 1) == 0); + } + /// \endcond + + Engine _base; +}; + +template +class uniform_smallint > +{ +public: + typedef boost::multiprecision::number input_type; + typedef boost::multiprecision::number result_type; + + class param_type + { + public: + + typedef uniform_smallint distribution_type; + + /** constructs the parameters of a @c uniform_smallint distribution. */ + param_type(result_type const& min_arg = 0, result_type const& max_arg = 9) + : _min(min_arg), _max(max_arg) + { + BOOST_ASSERT(_min <= _max); + } + + /** Returns the minimum value. */ + result_type a() const { return _min; } + /** Returns the maximum value. */ + result_type b() const { return _max; } + + + /** Writes the parameters to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) + { + os << parm._min << " " << parm._max; + return os; + } + + /** Reads the parameters from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) + { + is >> parm._min >> std::ws >> parm._max; + return is; + } + + /** Returns true if the two sets of parameters are equal. */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) + { return lhs._min == rhs._min && lhs._max == rhs._max; } + + /** Returns true if the two sets of parameters are different. */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) + + private: + result_type _min; + result_type _max; + }; + + /** + * Constructs a @c uniform_smallint. @c min and @c max are the + * lower and upper bounds of the output range, respectively. + */ + explicit uniform_smallint(result_type const& min_arg = 0, result_type const& max_arg = 9) + : _min(min_arg), _max(max_arg) {} + + /** + * Constructs a @c uniform_smallint from its parameters. + */ + explicit uniform_smallint(const param_type& parm) + : _min(parm.a()), _max(parm.b()) {} + + /** Returns the minimum value of the distribution. */ + result_type a() const { return _min; } + /** Returns the maximum value of the distribution. */ + result_type b() const { return _max; } + /** Returns the minimum value of the distribution. */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } + /** Returns the maximum value of the distribution. */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } + + /** Returns the parameters of the distribution. */ + param_type param() const { return param_type(_min, _max); } + /** Sets the parameters of the distribution. */ + void param(const param_type& parm) + { + _min = parm.a(); + _max = parm.b(); + } + + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** Returns a value uniformly distributed in the range [min(), max()]. */ + template + result_type operator()(Engine& eng) const + { + typedef typename Engine::result_type base_result; + return generate(eng, boost::is_integral()); + } + + /** Returns a value uniformly distributed in the range [param.a(), param.b()]. */ + template + result_type operator()(Engine& eng, const param_type& parm) const + { return uniform_smallint(parm)(eng); } + + /** Writes the distribution to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_smallint, ud) + { + os << ud._min << " " << ud._max; + return os; + } + + /** Reads the distribution from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_smallint, ud) + { + is >> ud._min >> std::ws >> ud._max; + return is; + } + + /** + * Returns true if the two distributions will produce identical + * sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_smallint, lhs, rhs) + { return lhs._min == rhs._min && lhs._max == rhs._max; } + + /** + * Returns true if the two distributions may produce different + * sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_smallint) + +private: + + // \cond show_private + template + result_type generate(Engine& eng, boost::mpl::true_) const + { + // equivalent to (eng() - eng.min()) % (_max - _min + 1) + _min, + // but guarantees no overflow. + typedef typename Engine::result_type base_result; + typedef typename boost::make_unsigned::type base_unsigned; + typedef result_type range_type; + range_type range = random::detail::subtract()(_max, _min); + base_unsigned base_range = + random::detail::subtract()((eng.max)(), (eng.min)()); + base_unsigned val = + random::detail::subtract()(eng(), (eng.min)()); + if(range >= base_range) { + return boost::random::detail::add()( + static_cast(val), _min); + } else { + base_unsigned modulus = static_cast(range) + 1; + return boost::random::detail::add()( + static_cast(val % modulus), _min); + } + } + + template + result_type generate(Engine& eng, boost::mpl::false_) const + { + typedef typename Engine::result_type base_result; + typedef result_type range_type; + range_type range = random::detail::subtract()(_max, _min); + base_result val = boost::uniform_01()(eng); + // what is the worst that can possibly happen here? + // base_result may not be able to represent all the values in [0, range] + // exactly. If this happens, it will cause round off error and we + // won't be able to produce all the values in the range. We don't + // care about this because the user has already told us not to by + // using uniform_smallint. However, we do need to be careful + // to clamp the result, or floating point rounding can produce + // an out of range result. + range_type offset = static_cast(val * (range + 1)); + if(offset > range) return _max; + return boost::random::detail::add()(offset , _min); + } + // \endcond + + result_type _min; + result_type _max; +}; + + +namespace detail{ + +template +struct select_uniform_01 > +{ + template + struct apply + { + typedef new_uniform_01 > type; + }; +}; + +template +boost::multiprecision::number + generate_uniform_int( + Engine& eng, const boost::multiprecision::number& min_value, const boost::multiprecision::number& max_value, + boost::mpl::true_ /** is_integral */) +{ + typedef boost::multiprecision::number result_type; + // Since we're using big-numbers, use the result type for all internal calculations: + typedef result_type range_type; + typedef result_type base_result; + typedef result_type base_unsigned; + const range_type range = random::detail::subtract()(max_value, min_value); + const base_result bmin = (eng.min)(); + const base_unsigned brange = + random::detail::subtract()((eng.max)(), (eng.min)()); + + if(range == 0) { + return min_value; + } else if(brange == range) { + // this will probably never happen in real life + // basically nothing to do; just take care we don't overflow / underflow + base_unsigned v = random::detail::subtract()(eng(), bmin); + return random::detail::add()(v, min_value); + } else if(brange < range) { + // use rejection method to handle things like 0..3 --> 0..4 + for(;;) { + // concatenate several invocations of the base RNG + // take extra care to avoid overflows + + // limit == floor((range+1)/(brange+1)) + // Therefore limit*(brange+1) <= range+1 + range_type limit; + if(std::numeric_limits::is_bounded && (range == (std::numeric_limits::max)())) { + limit = range/(range_type(brange)+1); + if(range % (range_type(brange)+1) == range_type(brange)) + ++limit; + } else { + limit = (range+1)/(range_type(brange)+1); + } + + // We consider "result" as expressed to base (brange+1): + // For every power of (brange+1), we determine a random factor + range_type result = range_type(0); + range_type mult = range_type(1); + + // loop invariants: + // result < mult + // mult <= range + while(mult <= limit) { + // Postcondition: result <= range, thus no overflow + // + // limit*(brange+1)<=range+1 def. of limit (1) + // eng()-bmin<=brange eng() post. (2) + // and mult<=limit. loop condition (3) + // Therefore mult*(eng()-bmin+1)<=range+1 by (1),(2),(3) (4) + // Therefore mult*(eng()-bmin)+mult<=range+1 rearranging (4) (5) + // result(random::detail::subtract()(eng(), bmin) * mult); + + // equivalent to (mult * (brange+1)) == range+1, but avoids overflow. + if(mult * range_type(brange) == range - mult + 1) { + // The destination range is an integer power of + // the generator's range. + return(result); + } + + // Postcondition: mult <= range + // + // limit*(brange+1)<=range+1 def. of limit (1) + // mult<=limit loop condition (2) + // Therefore mult*(brange+1)<=range+1 by (1), (2) (3) + // mult*(brange+1)!=range+1 preceding if (4) + // Therefore mult*(brange+1) limit loop condition (1) + // Suppose range/mult >= brange+1 Assumption (2) + // range >= mult*(brange+1) by (2) (3) + // range+1 > mult*(brange+1) by (3) (4) + // range+1 > (limit+1)*(brange+1) by (1), (4) (5) + // (range+1)/(brange+1) > limit+1 by (5) (6) + // limit < floor((range+1)/(brange+1)) by (6) (7) + // limit==floor((range+1)/(brange+1)) def. of limit (8) + // not (2) reductio (9) + // + // loop postcondition: (range/mult)*mult+(mult-1) >= range + // + // (range/mult)*mult + range%mult == range identity (1) + // range%mult < mult def. of % (2) + // (range/mult)*mult+mult > range by (1), (2) (3) + // (range/mult)*mult+(mult-1) >= range by (3) (4) + // + // Note that the maximum value of result at this point is (mult-1), + // so after this final step, we generate numbers that can be + // at least as large as range. We have to really careful to avoid + // overflow in this final addition and in the rejection. Anything + // that overflows is larger than range and can thus be rejected. + + // range/mult < brange+1 -> no endless loop + range_type result_increment = + generate_uniform_int( + eng, + static_cast(0), + static_cast(range/mult), + boost::mpl::true_()); + if(std::numeric_limits::is_bounded && ((std::numeric_limits::max)() / mult < result_increment)) { + // The multiplcation would overflow. Reject immediately. + continue; + } + result_increment *= mult; + // unsigned integers are guaranteed to wrap on overflow. + result += result_increment; + if(result < result_increment) { + // The addition overflowed. Reject. + continue; + } + if(result > range) { + // Too big. Reject. + continue; + } + return random::detail::add()(result, min_value); + } + } else { // brange > range + range_type bucket_size; + // it's safe to add 1 to range, as long as we cast it first, + // because we know that it is less than brange. However, + // we do need to be careful not to cause overflow by adding 1 + // to brange. + if(std::numeric_limits::is_bounded && (brange == (std::numeric_limits::max)())) { + bucket_size = brange / (range+1); + if(brange % (range+1) == range) { + ++bucket_size; + } + } else { + bucket_size = (brange+1) / (range+1); + } + for(;;) { + range_type result = + random::detail::subtract()(eng(), bmin); + result /= bucket_size; + // result and range are non-negative, and result is possibly larger + // than range, so the cast is safe + if(result <= range) + return result + min_value; + } + } +} + +template +inline boost::multiprecision::number + generate_uniform_int(Engine& eng, const boost::multiprecision::number& min_value, const boost::multiprecision::number& max_value) +{ + typedef typename Engine::result_type base_result; + typedef typename mpl::or_, mpl::bool_::value == boost::multiprecision::number_kind_integer> >::type tag_type; + return generate_uniform_int(eng, min_value, max_value, + tag_type()); +} + +} // detail + + +}} // namespaces + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/include/boost/multiprecision/rational_adapter.hpp b/include/boost/multiprecision/rational_adapter.hpp new file mode 100644 index 00000000..d2c5c3b7 --- /dev/null +++ b/include/boost/multiprecision/rational_adapter.hpp @@ -0,0 +1,302 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP +#define BOOST_MATH_RATIONAL_ADAPTER_HPP + +#include +#include +#include +#include +#include +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4512 4127) +#endif +#include +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +template +struct rational_adapter +{ + typedef number integer_type; + typedef boost::rational rational_type; + + typedef typename IntBackend::signed_types signed_types; + typedef typename IntBackend::unsigned_types unsigned_types; + typedef typename IntBackend::float_types float_types; + + rational_adapter(){} + rational_adapter(const rational_adapter& o) + { + m_value = o.m_value; + } + rational_adapter(const IntBackend& o) : m_value(o) {} + + template + rational_adapter(const U& u, typename enable_if_c::value>::type* = 0) + : m_value(IntBackend(u)){} + template + explicit rational_adapter(const U& u, + typename enable_if_c< + boost::multiprecision::detail::is_explicitly_convertible::value && !is_convertible::value + >::type* = 0) + : m_value(IntBackend(u)){} + template + typename enable_if_c<(boost::multiprecision::detail::is_explicitly_convertible::value && !is_arithmetic::value), rational_adapter&>::type operator = (const U& u) + { + m_value = IntBackend(u); + } + +#ifndef BOOST_NO_RVALUE_REFERENCES + rational_adapter(rational_adapter&& o) : m_value(o.m_value) {} + rational_adapter(IntBackend&& o) : m_value(o) {} + rational_adapter& operator = (rational_adapter&& o) + { + m_value = static_cast(o.m_value); + return *this; + } +#endif + rational_adapter& operator = (const rational_adapter& o) + { + m_value = o.m_value; + return *this; + } + rational_adapter& operator = (const IntBackend& o) + { + m_value = o; + return *this; + } + template + typename enable_if, rational_adapter&>::type operator = (Int i) + { + m_value = i; + return *this; + } + template + typename enable_if, rational_adapter&>::type operator = (Float i) + { + int e; + Float f = std::frexp(i, &e); + f = std::ldexp(f, std::numeric_limits::digits); + e -= std::numeric_limits::digits; + integer_type num(f); + integer_type denom(1u); + if(e > 0) + { + num <<= e; + } + else if(e < 0) + { + denom <<= -e; + } + m_value.assign(num, denom); + return *this; + } + rational_adapter& operator = (const char* s) + { + std::string s1; + multiprecision::number v1, v2; + char c; + bool have_hex = false; + const char* p = s; // saved for later + + while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + { + if(c == 'x' || c == 'X') + have_hex = true; + s1.append(1, c); + ++s; + } + v1.assign(s1); + s1.erase(); + if(c == '/') + { + ++s; + while((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')))) + { + if(c == 'x' || c == 'X') + have_hex = true; + s1.append(1, c); + ++s; + } + v2.assign(s1); + } + else + v2 = 1; + if(*s) + { + BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Could parse the string \"") + p + std::string("\" as a valid rational number."))); + } + data().assign(v1, v2); + return *this; + } + void swap(rational_adapter& o) + { + std::swap(m_value, o.m_value); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + // + // We format the string ourselves so we can match what GMP's mpq type does: + // + std::string result = data().numerator().str(digits, f); + if(data().denominator() != 1) + { + result.append(1, '/'); + result.append(data().denominator().str(digits, f)); + } + return result; + } + void negate() + { + m_value = -m_value; + } + int compare(const rational_adapter& o)const + { + return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); + } + template + typename enable_if, int>::type compare(Arithmatic i)const + { + return m_value > i ? 1 : (m_value < i ? -1 : 0); + } + rational_type& data() { return m_value; } + const rational_type& data()const { return m_value; } +private: + rational_type m_value; +}; + +template +inline void eval_add(rational_adapter& result, const rational_adapter& o) +{ + result.data() += o.data(); +} +template +inline void eval_subtract(rational_adapter& result, const rational_adapter& o) +{ + result.data() -= o.data(); +} +template +inline void eval_multiply(rational_adapter& result, const rational_adapter& o) +{ + result.data() *= o.data(); +} +template +inline void eval_divide(rational_adapter& result, const rational_adapter& o) +{ + using default_ops::eval_is_zero; + if(eval_is_zero(o)) + { + BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero.")); + } + result.data() /= o.data(); +} + +template +inline void eval_convert_to(R* result, const rational_adapter& backend) +{ + *result = backend.data().numerator().template convert_to(); + *result /= backend.data().denominator().template convert_to(); +} + +template +inline bool eval_is_zero(const rational_adapter& val) +{ + return eval_is_zero(val.data().numerator().backend()); +} +template +inline int eval_get_sign(const rational_adapter& val) +{ + return eval_get_sign(val.data().numerator().backend()); +} + +template +inline void assign_components(rational_adapter& result, const V& v1, const V& v2) +{ + result.data().assign(v1, v2); +} + +} // namespace backends + +template +struct expression_template_default > : public expression_template_default {}; + +template +struct number_category > : public mpl::int_{}; + +using boost::multiprecision::backends::rational_adapter; + +template +struct component_type > +{ + typedef number type; +}; + +template +inline number numerator(const number, ET>& val) +{ + return val.backend().data().numerator(); +} +template +inline number denominator(const number, ET>& val) +{ + return val.backend().data().denominator(); +} + +#ifdef BOOST_NO_SFINAE_EXPR + +namespace detail{ + +template +struct is_explicitly_convertible > : public is_explicitly_convertible {}; + +} + +#endif + +}} // namespaces + + +namespace std{ + +template +class numeric_limits, ExpressionTemplates> > : public std::numeric_limits > +{ + typedef std::numeric_limits > base_type; + typedef boost::multiprecision::number > number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_integer = false; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } + BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } + BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); } + BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } + BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } + BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } + BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } + BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; + +#endif + + +} + +#endif diff --git a/include/boost/multiprecision/tommath.hpp b/include/boost/multiprecision/tommath.hpp new file mode 100644 index 00000000..d41b84f8 --- /dev/null +++ b/include/boost/multiprecision/tommath.hpp @@ -0,0 +1,748 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_MP_TOMMATH_BACKEND_HPP +#define BOOST_MATH_MP_TOMMATH_BACKEND_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace multiprecision{ namespace backends{ + +namespace detail{ + +inline void check_tommath_result(unsigned v) +{ + if(v != MP_OKAY) + { + BOOST_THROW_EXCEPTION(std::runtime_error(mp_error_to_string(v))); + } +} + +} + +struct tommath_int; + +void eval_multiply(tommath_int& t, const tommath_int& o); +void eval_add(tommath_int& t, const tommath_int& o); + +struct tommath_int +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + + tommath_int() + { + detail::check_tommath_result(mp_init(&m_data)); + } + tommath_int(const tommath_int& o) + { + detail::check_tommath_result(mp_init_copy(&m_data, const_cast< ::mp_int*>(&o.m_data))); + } +#ifndef BOOST_NO_RVALUE_REFERENCES + tommath_int(tommath_int&& o) BOOST_NOEXCEPT + { + m_data = o.m_data; + o.m_data.dp = 0; + } + tommath_int& operator = (tommath_int&& o) + { + mp_exch(&m_data, &o.data()); + return *this; + } +#endif + tommath_int& operator = (const tommath_int& o) + { + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + if(o.m_data.dp) + detail::check_tommath_result(mp_copy(const_cast< ::mp_int*>(&o.m_data), &m_data)); + return *this; + } + tommath_int& operator = (unsigned long long i) + { + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); + unsigned shift = 0; + ::mp_int t; + detail::check_tommath_result(mp_init(&t)); + mp_zero(&m_data); + while(i) + { + detail::check_tommath_result(mp_set_int(&t, static_cast(i & mask))); + if(shift) + detail::check_tommath_result(mp_mul_2d(&t, shift, &t)); + detail::check_tommath_result((mp_add(&m_data, &t, &m_data))); + shift += std::numeric_limits::digits; + i >>= std::numeric_limits::digits; + } + mp_clear(&t); + return *this; + } + tommath_int& operator = (long long i) + { + BOOST_MP_USING_ABS + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + bool neg = i < 0; + *this = static_cast(abs(i)); + if(neg) + detail::check_tommath_result(mp_neg(&m_data, &m_data)); + return *this; + } + // + // Note that although mp_set_int takes an unsigned long as an argument + // it only sets the first 32-bits to the result, and ignores the rest. + // So use uint32_t as the largest type to pass to this function. + // + tommath_int& operator = (boost::uint32_t i) + { + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + detail::check_tommath_result((mp_set_int(&m_data, i))); + return *this; + } + tommath_int& operator = (boost::int32_t i) + { + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + bool neg = i < 0; + *this = static_cast(std::abs(i)); + if(neg) + detail::check_tommath_result(mp_neg(&m_data, &m_data)); + return *this; + } + tommath_int& operator = (long double a) + { + using std::frexp; + using std::ldexp; + using std::floor; + + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + + if (a == 0) { + detail::check_tommath_result(mp_set_int(&m_data, 0)); + return *this; + } + + if (a == 1) { + detail::check_tommath_result(mp_set_int(&m_data, 1)); + return *this; + } + + BOOST_ASSERT(!(boost::math::isinf)(a)); + BOOST_ASSERT(!(boost::math::isnan)(a)); + + int e; + long double f, term; + detail::check_tommath_result(mp_set_int(&m_data, 0u)); + ::mp_int t; + detail::check_tommath_result(mp_init(&t)); + + f = frexp(a, &e); + + static const int shift = std::numeric_limits::digits - 1; + + while(f) + { + // extract int sized bits from f: + f = ldexp(f, shift); + term = floor(f); + e -= shift; + detail::check_tommath_result(mp_mul_2d(&m_data, shift, &m_data)); + if(term > 0) + { + detail::check_tommath_result(mp_set_int(&t, static_cast(term))); + detail::check_tommath_result(mp_add(&m_data, &t, &m_data)); + } + else + { + detail::check_tommath_result(mp_set_int(&t, static_cast(-term))); + detail::check_tommath_result(mp_sub(&m_data, &t, &m_data)); + } + f -= term; + } + if(e > 0) + detail::check_tommath_result(mp_mul_2d(&m_data, e, &m_data)); + else if(e < 0) + { + tommath_int t2; + detail::check_tommath_result(mp_div_2d(&m_data, -e, &m_data, &t2.data())); + } + mp_clear(&t); + return *this; + } + tommath_int& operator = (const char* s) + { + // + // We don't use libtommath's own routine because it doesn't error check the input :-( + // + if(m_data.dp == 0) + detail::check_tommath_result(mp_init(&m_data)); + std::size_t n = s ? std::strlen(s) : 0; + *this = static_cast(0u); + unsigned radix = 10; + bool isneg = false; + if(n && (*s == '-')) + { + --n; + ++s; + isneg = true; + } + if(n && (*s == '0')) + { + if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) + { + radix = 16; + s +=2; + n -= 2; + } + else + { + radix = 8; + n -= 1; + } + } + if(n) + { + if(radix == 8 || radix == 16) + { + unsigned shift = radix == 8 ? 3 : 4; + unsigned block_count = DIGIT_BIT / shift; + unsigned block_shift = shift * block_count; + unsigned long long val, block; + while(*s) + { + block = 0; + for(unsigned i = 0; (i < block_count); ++i) + { + if(*s >= '0' && *s <= '9') + val = *s - '0'; + else if(*s >= 'a' && *s <= 'f') + val = 10 + *s - 'a'; + else if(*s >= 'A' && *s <= 'F') + val = 10 + *s - 'A'; + else + val = 400; + if(val > radix) + { + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); + } + block <<= shift; + block |= val; + if(!*++s) + { + // final shift is different: + block_shift = (i + 1) * shift; + break; + } + } + detail::check_tommath_result(mp_mul_2d(&data(), block_shift, &data())); + if(data().used) + data().dp[0] |= block; + else + *this = block; + } + } + else + { + // Base 10, we extract blocks of size 10^9 at a time, that way + // the number of multiplications is kept to a minimum: + boost::uint32_t block_mult = 1000000000; + while(*s) + { + boost::uint32_t block = 0; + for(unsigned i = 0; i < 9; ++i) + { + boost::uint32_t val; + if(*s >= '0' && *s <= '9') + val = *s - '0'; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input.")); + block *= 10; + block += val; + if(!*++s) + { + static const boost::uint32_t block_multiplier[9] = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + block_mult = block_multiplier[i]; + break; + } + } + tommath_int t; + t = block_mult; + eval_multiply(*this, t); + t = block; + eval_add(*this, t); + } + } + } + if(isneg) + this->negate(); + return *this; + } + std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const + { + BOOST_ASSERT(m_data.dp); + int base = 10; + if((f & std::ios_base::oct) == std::ios_base::oct) + base = 8; + else if((f & std::ios_base::hex) == std::ios_base::hex) + base = 16; + // + // sanity check, bases 8 and 16 are only available for positive numbers: + // + if((base != 10) && m_data.sign) + BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); + int s; + detail::check_tommath_result(mp_radix_size(const_cast< ::mp_int*>(&m_data), base, &s)); + boost::scoped_array a(new char[s+1]); + detail::check_tommath_result(mp_toradix_n(const_cast< ::mp_int*>(&m_data), a.get(), base, s+1)); + std::string result = a.get(); + if((base != 10) && (f & std::ios_base::showbase)) + { + int pos = result[0] == '-' ? 1 : 0; + const char* pp = base == 8 ? "0" : "0x"; + result.insert(pos, pp); + } + if((f & std::ios_base::showpos) && (result[0] != '-')) + result.insert(0, 1, '+'); + return result; + } + ~tommath_int() + { + if(m_data.dp) + mp_clear(&m_data); + } + void negate() + { + BOOST_ASSERT(m_data.dp); + mp_neg(&m_data, &m_data); + } + int compare(const tommath_int& o)const + { + BOOST_ASSERT(m_data.dp && o.m_data.dp); + return mp_cmp(const_cast< ::mp_int*>(&m_data), const_cast< ::mp_int*>(&o.m_data)); + } + template + int compare(V v)const + { + tommath_int d; + tommath_int t(*this); + detail::check_tommath_result(mp_shrink(&t.data())); + d = v; + return t.compare(d); + } + ::mp_int& data() + { + BOOST_ASSERT(m_data.dp); + return m_data; + } + const ::mp_int& data()const + { + BOOST_ASSERT(m_data.dp); + return m_data; + } + void swap(tommath_int& o)BOOST_NOEXCEPT + { + mp_exch(&m_data, &o.data()); + } +protected: + ::mp_int m_data; +}; + +#define BOOST_MP_TOMMATH_BIT_OP_CHECK(x)\ + if(SIGN(&x.data()))\ + BOOST_THROW_EXCEPTION(std::runtime_error("Bitwise operations on libtommath negative valued integers are disabled as they produce unpredictable results")) + +int eval_get_sign(const tommath_int& val); + +inline void eval_add(tommath_int& t, const tommath_int& o) +{ + detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_subtract(tommath_int& t, const tommath_int& o) +{ + detail::check_tommath_result(mp_sub(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_multiply(tommath_int& t, const tommath_int& o) +{ + detail::check_tommath_result(mp_mul(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_divide(tommath_int& t, const tommath_int& o) +{ + using default_ops::eval_is_zero; + tommath_int temp; + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); + detail::check_tommath_result(mp_div(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data(), &temp.data())); +} +inline void eval_modulus(tommath_int& t, const tommath_int& o) +{ + using default_ops::eval_is_zero; + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); + bool neg = eval_get_sign(t) < 0; + bool neg2 = eval_get_sign(o) < 0; + detail::check_tommath_result(mp_mod(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); + if((neg != neg2) && (eval_get_sign(t) != 0)) + { + t.negate(); + detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); + t.negate(); + } + else if(neg && (t.compare(o) == 0)) + { + mp_zero(&t.data()); + } +} +template +inline void eval_left_shift(tommath_int& t, UI i) +{ + detail::check_tommath_result(mp_mul_2d(&t.data(), static_cast(i), &t.data())); +} +template +inline void eval_right_shift(tommath_int& t, UI i) +{ + tommath_int d; + detail::check_tommath_result(mp_div_2d(&t.data(), static_cast(i), &t.data(), &d.data())); +} +template +inline void eval_left_shift(tommath_int& t, const tommath_int& v, UI i) +{ + detail::check_tommath_result(mp_mul_2d(const_cast< ::mp_int*>(&v.data()), static_cast(i), &t.data())); +} +template +inline void eval_right_shift(tommath_int& t, const tommath_int& v, UI i) +{ + tommath_int d; + detail::check_tommath_result(mp_div_2d(const_cast< ::mp_int*>(&v.data()), static_cast(i), &t.data(), &d.data())); +} + +inline void eval_bitwise_and(tommath_int& result, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(result); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_and(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); +} + +inline void eval_bitwise_or(tommath_int& result, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(result); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_or(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); +} + +inline void eval_bitwise_xor(tommath_int& result, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(result); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_xor(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); +} + +inline void eval_add(tommath_int& t, const tommath_int& p, const tommath_int& o) +{ + detail::check_tommath_result(mp_add(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_subtract(tommath_int& t, const tommath_int& p, const tommath_int& o) +{ + detail::check_tommath_result(mp_sub(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_multiply(tommath_int& t, const tommath_int& p, const tommath_int& o) +{ + detail::check_tommath_result(mp_mul(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); +} +inline void eval_divide(tommath_int& t, const tommath_int& p, const tommath_int& o) +{ + using default_ops::eval_is_zero; + tommath_int d; + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); + detail::check_tommath_result(mp_div(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data(), &d.data())); +} +inline void eval_modulus(tommath_int& t, const tommath_int& p, const tommath_int& o) +{ + using default_ops::eval_is_zero; + if(eval_is_zero(o)) + BOOST_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); + bool neg = eval_get_sign(p) < 0; + bool neg2 = eval_get_sign(o) < 0; + detail::check_tommath_result(mp_mod(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); + if((neg != neg2) && (eval_get_sign(t) != 0)) + { + t.negate(); + detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); + t.negate(); + } + else if(neg && (t.compare(o) == 0)) + { + mp_zero(&t.data()); + } +} + +inline void eval_bitwise_and(tommath_int& result, const tommath_int& u, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(u); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_and(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); +} + +inline void eval_bitwise_or(tommath_int& result, const tommath_int& u, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(u); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_or(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); +} + +inline void eval_bitwise_xor(tommath_int& result, const tommath_int& u, const tommath_int& v) +{ + BOOST_MP_TOMMATH_BIT_OP_CHECK(u); + BOOST_MP_TOMMATH_BIT_OP_CHECK(v); + detail::check_tommath_result(mp_xor(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); +} +/* +inline void eval_complement(tommath_int& result, const tommath_int& u) +{ + // + // Although this code works, it doesn't really do what the user might expect.... + // and it's hard to see how it ever could. Disabled for now: + // + result = u; + for(int i = 0; i < result.data().used; ++i) + { + result.data().dp[i] = MP_MASK & ~(result.data().dp[i]); + } + // + // We now need to pad out the left of the value with 1's to round up to a whole number of + // CHAR_BIT * sizeof(mp_digit) units. Otherwise we'll end up with a very strange number of + // bits set! + // + unsigned shift = result.data().used * DIGIT_BIT; // How many bits we're actually using + // How many bits we actually need, reduced by one to account for a mythical sign bit: + int padding = result.data().used * std::numeric_limits::digits - shift - 1; + while(padding >= std::numeric_limits::digits) + padding -= std::numeric_limits::digits; + + // Create a mask providing the extra bits we need and add to result: + tommath_int mask; + mask = static_cast((1u << padding) - 1); + eval_left_shift(mask, shift); + add(result, mask); +} +*/ +inline bool eval_is_zero(const tommath_int& val) +{ + return mp_iszero(&val.data()); +} +inline int eval_get_sign(const tommath_int& val) +{ + return mp_iszero(&val.data()) ? 0 : SIGN(&val.data()) ? -1 : 1; +} +template +inline void eval_convert_to(A* result, const tommath_int& val) +{ + *result = boost::lexical_cast(val.str(0, std::ios_base::fmtflags(0))); +} +inline void eval_convert_to(char* result, const tommath_int& val) +{ + *result = static_cast(boost::lexical_cast(val.str(0, std::ios_base::fmtflags(0)))); +} +inline void eval_convert_to(unsigned char* result, const tommath_int& val) +{ + *result = static_cast(boost::lexical_cast(val.str(0, std::ios_base::fmtflags(0)))); +} +inline void eval_convert_to(signed char* result, const tommath_int& val) +{ + *result = static_cast(boost::lexical_cast(val.str(0, std::ios_base::fmtflags(0)))); +} +inline void eval_abs(tommath_int& result, const tommath_int& val) +{ + detail::check_tommath_result(mp_abs(const_cast< ::mp_int*>(&val.data()), &result.data())); +} +inline void eval_gcd(tommath_int& result, const tommath_int& a, const tommath_int& b) +{ + detail::check_tommath_result(mp_gcd(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); +} +inline void eval_lcm(tommath_int& result, const tommath_int& a, const tommath_int& b) +{ + detail::check_tommath_result(mp_lcm(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); +} +inline void eval_powm(tommath_int& result, const tommath_int& base, const tommath_int& p, const tommath_int& m) +{ + if(eval_get_sign(p) < 0) + { + BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); + } + detail::check_tommath_result(mp_exptmod(const_cast< ::mp_int*>(&base.data()), const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&m.data()), &result.data())); +} + + +inline void eval_qr(const tommath_int& x, const tommath_int& y, + tommath_int& q, tommath_int& r) +{ + detail::check_tommath_result(mp_div(const_cast< ::mp_int*>(&x.data()), const_cast< ::mp_int*>(&y.data()), &q.data(), &r.data())); +} + +inline unsigned eval_lsb(const tommath_int& val) +{ + int c = eval_get_sign(val); + if(c == 0) + { + BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); + } + if(c < 0) + { + BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); + } + return mp_cnt_lsb(const_cast< ::mp_int*>(&val.data())); +} + +template +inline typename enable_if, Integer>::type eval_integer_modulus(const tommath_int& x, Integer val) +{ + static const mp_digit m = (static_cast(1) << DIGIT_BIT) - 1; + if(val <= m) + { + mp_digit d; + detail::check_tommath_result(mp_mod_d(const_cast< ::mp_int*>(&x.data()), static_cast(val), &d)); + return d; + } + else + { + return default_ops::eval_integer_modulus(x, val); + } +} +template +inline typename enable_if, Integer>::type eval_integer_modulus(const tommath_int& x, Integer val) +{ + typedef typename make_unsigned::type unsigned_type; + return eval_integer_modulus(x, static_cast(std::abs(val))); +} + +} // namespace backends + +using boost::multiprecision::backends::tommath_int; + +template<> +struct number_category : public mpl::int_{}; + +typedef number tom_int; +typedef rational_adapter tommath_rational; +typedef number tom_rational; + +}} // namespaces + +namespace std{ + +template +class numeric_limits > +{ + typedef boost::multiprecision::number number_type; +public: + BOOST_STATIC_CONSTEXPR bool is_specialized = true; + // + // Largest and smallest numbers are bounded only by available memory, set + // to zero: + // + static number_type (min)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type (max)() BOOST_NOEXCEPT + { + return number_type(); + } + static number_type lowest() BOOST_NOEXCEPT { return (min)(); } + BOOST_STATIC_CONSTEXPR int digits = INT_MAX; + BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; + BOOST_STATIC_CONSTEXPR bool is_signed = true; + BOOST_STATIC_CONSTEXPR bool is_integer = true; + BOOST_STATIC_CONSTEXPR bool is_exact = true; + BOOST_STATIC_CONSTEXPR int radix = 2; + static number_type epsilon() BOOST_NOEXCEPT { return number_type(); } + static number_type round_error() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR int min_exponent = 0; + BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; + BOOST_STATIC_CONSTEXPR int max_exponent = 0; + BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; + BOOST_STATIC_CONSTEXPR bool has_infinity = false; + BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; + BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; + BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; + static number_type infinity() BOOST_NOEXCEPT { return number_type(); } + static number_type quiet_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type signaling_NaN() BOOST_NOEXCEPT { return number_type(); } + static number_type denorm_min() BOOST_NOEXCEPT { return number_type(); } + BOOST_STATIC_CONSTEXPR bool is_iec559 = false; + BOOST_STATIC_CONSTEXPR bool is_bounded = false; + BOOST_STATIC_CONSTEXPR bool is_modulo = false; + BOOST_STATIC_CONSTEXPR bool traps = false; + BOOST_STATIC_CONSTEXPR bool tinyness_before = false; + BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; +template +BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; +template +BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; +template +BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; +template +BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; + +#endif +} + +#endif diff --git a/include/boost/multiprecision/traits/explicit_conversion.hpp b/include/boost/multiprecision/traits/explicit_conversion.hpp new file mode 100644 index 00000000..b4cd8215 --- /dev/null +++ b/include/boost/multiprecision/traits/explicit_conversion.hpp @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Vicente J. Botet Escriba 2009-2011 +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_EXPLICIT_CONVERTIBLE_HPP +#define BOOST_MP_EXPLICIT_CONVERTIBLE_HPP + +#include +#include + + +namespace boost{ namespace multiprecision{ namespace detail{ + +template +struct dummy_size{}; + +template +struct has_generic_interconversion +{ + typedef typename mpl::if_c< + is_number::value && is_number::value, + typename mpl::if_c< + number_category::value == number_kind_integer, + typename mpl::if_c< + number_category::value == number_kind_integer + || number_category::value == number_kind_floating_point + || number_category::value == number_kind_rational + || number_category::value == number_kind_fixed_point, + mpl::true_, + mpl::false_ + >::type, + typename mpl::if_c< + number_category::value == number_kind_rational, + typename mpl::if_c< + number_category::value == number_kind_rational + || number_category::value == number_kind_rational, + mpl::true_, + mpl::false_ + >::type, + typename mpl::if_c< + number_category::value == number_kind_floating_point, + mpl::true_, + mpl::false_ + >::type + >::type + >::type, + mpl::false_ + >::type type; +}; + +template +struct is_explicitly_convertible_imp +{ +#ifndef BOOST_NO_SFINAE_EXPR + template + static type_traits::yes_type selector(dummy_size(declval()))>*); + + template + static type_traits::no_type selector(...); + + static const bool value = sizeof(selector(0)) == sizeof(type_traits::yes_type); + + typedef boost::integral_constant type; +#else + typedef typename has_generic_interconversion::type gen_type; + typedef mpl::bool_::value || gen_type::value> type; +#endif +}; + +template +struct is_explicitly_convertible : public is_explicitly_convertible_imp::type +{ +}; + +}}} // namespaces + +#endif + diff --git a/include/boost/multiprecision/traits/is_restricted_conversion.hpp b/include/boost/multiprecision/traits/is_restricted_conversion.hpp new file mode 100644 index 00000000..283f15ce --- /dev/null +++ b/include/boost/multiprecision/traits/is_restricted_conversion.hpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Vicente J. Botet Escriba 2009-2011 +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_RESTRICTED_CONVERSION_HPP +#define BOOST_MP_RESTRICTED_CONVERSION_HPP + +#include +#include +#include + +namespace boost{ namespace multiprecision{ namespace detail{ + + +template +struct is_lossy_conversion +{ + typedef typename mpl::if_c< + ((number_category::value == number_kind_floating_point) && (number_category::value == number_kind_integer)) + || ((number_category::value == number_kind_floating_point) && (number_category::value == number_kind_rational)) + || ((number_category::value == number_kind_rational) && (number_category::value == number_kind_integer)) + || ((number_category::value == number_kind_fixed_point) && (number_category::value == number_kind_integer)) + || (number_category::value == number_kind_unknown) + || (number_category::value == number_kind_unknown), + mpl::true_, + mpl::false_ + >::type type; + static const bool value = type::value; +}; + +template +struct is_restricted_conversion +{ + typedef typename mpl::if_c< + ((is_explicitly_convertible::value && !is_convertible::value) + || is_lossy_conversion::value), + mpl::true_, + mpl::false_ + >::type type; + static const bool value = type::value; +}; + +}}} // namespaces + +#endif // BOOST_MP_RESTRICTED_CONVERSION_HPP + diff --git a/performance/Jamfile.v2 b/performance/Jamfile.v2 new file mode 100644 index 00000000..f97fb89c --- /dev/null +++ b/performance/Jamfile.v2 @@ -0,0 +1,127 @@ +# copyright John Maddock 2012 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + +import modules ; +import path ; + +local ntl-path = [ modules.peek : NTL_PATH ] ; +local gmp_path = [ modules.peek : GMP_PATH ] ; +local mpfr_path = [ modules.peek : MPFR_PATH ] ; +local tommath_path = [ modules.peek : TOMMATH_PATH ] ; + +project : requirements + freebsd:"-lrt" + linux:"-lrt" + pgi:"-lrt" + $(gmp_path) + $(gmp_path)/mpfr + $(gmp_path)/gmpfrxx + $(mpfr_path) + $(tommath_path) + ../../.. + $(gmp_path) + $(mpfr_path) + $(mpfr_path)/build.vc10/lib/Win32/Debug + $(tommath_path) + static + BOOST_ALL_NO_LIB + off + ; + + +lib gmp ; +lib mpfr ; + +if $(tommath_path) +{ + TOMMATH = [ GLOB $(tommath_path) : *.c ] ; +} +else +{ + lib tommath ; + TOMMATH = tommath ; +} + +exe performance_test : performance_test.cpp /boost/system//boost_system + : release + [ check-target-builds ../config//has_gmp : TEST_MPF TEST_MPZ gmp : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR mpfr : ] + [ check-target-builds ../config//has_tommath : TEST_TOMMATH $(TOMMATH) : ] + TEST_CPP_DEC_FLOAT + TEST_CPP_INT + ; + +exe miller_rabin_performance : miller_rabin_performance.cpp /boost/system//boost_system /boost/chrono//boost_chrono + : release + [ check-target-builds ../config//has_gmp : TEST_MPF TEST_MPZ gmp : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR mpfr : ] + #[ check-target-builds ../config//has_tommath : TEST_TOMMATH $(TOMMATH) : ] + TEST_CPP_DEC_FLOAT + TEST_CPP_INT + ; + +exe sf_performance : sf_performance.cpp sf_performance_basic.cpp sf_performance_bessel.cpp + sf_performance_nct.cpp sf_performance_poly.cpp + /boost/system//boost_system /boost/chrono//boost_chrono /boost/thread//boost_thread + : release + [ check-target-builds ../config//has_gmp : TEST_MPF TEST_MPZ gmp : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR mpfr : ] + TEST_CPP_DEC_FLOAT + msvc:-bigobj + ; + +exe delaunay_test : delaunay_test.cpp /boost/system//boost_system /boost/chrono//boost_chrono ; + +obj obj_linpack_benchmark_mpfr : linpack-benchmark.cpp + : release + [ check-target-builds ../config//has_mpfr : : no ] + TEST_MPFR_50 + ; + +obj obj_linpack_benchmark_mpf : linpack-benchmark.cpp + : release + [ check-target-builds ../config//has_gmp : : no ] + TEST_MPF_50 + ; + +obj obj_linpack_benchmark_cpp_float : linpack-benchmark.cpp + : release + TEST_CPP_DEC_FLOAT + ; + +obj obj_linpack_benchmark_double : linpack-benchmark.cpp + : release + ; + +lib f2c ; + +exe linpack_benchmark_mpfr : obj_linpack_benchmark_mpfr mpfr f2c gmp + : release + [ check-target-builds ../config//has_mpfr : : no ] + TEST_MPFR_50 + ; + +exe linpack_benchmark_mpf : obj_linpack_benchmark_mpf gmp f2c + : release + [ check-target-builds ../config//has_gmp : : no ] + TEST_MPF_50 + ; + +exe linpack_benchmark_cpp_float : obj_linpack_benchmark_cpp_float f2c + : release + TEST_CPP_DEC_FLOAT + ; + +exe linpack_benchmark_double : obj_linpack_benchmark_double f2c + : release + ; + +install miller_rabin_install : miller_rabin_performance : . ; +install performance_test_install : performance_test : . ; +install sf_performance_install : sf_performance : . ; +install . : linpack_benchmark_double linpack_benchmark_cpp_float linpack_benchmark_mpf linpack_benchmark_mpfr ; +install delaunay_install : delaunay_test : . ; + + diff --git a/performance/arithmetic_backend.hpp b/performance/arithmetic_backend.hpp new file mode 100644 index 00000000..1f0c360b --- /dev/null +++ b/performance/arithmetic_backend.hpp @@ -0,0 +1,586 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MATH_FLOAT_BACKEND_HPP +#define BOOST_MATH_FLOAT_BACKEND_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4389 4244 4018 4244 4127) +#endif + +template +struct arithmetic_backend +{ + typedef mpl::list signed_types; + typedef mpl::list unsigned_types; + typedef mpl::list float_types; + typedef int exponent_type; + + arithmetic_backend(){} + arithmetic_backend(const arithmetic_backend& o) + { + m_value = o.m_value; + } + template + arithmetic_backend(const A& o, const typename enable_if >::type* = 0) : m_value(o) {} + template + arithmetic_backend(const arithmetic_backend& o) : m_value(o.data()) {} + arithmetic_backend& operator = (const arithmetic_backend& o) + { + m_value = o.m_value; + return *this; + } + template + typename enable_if, arithmetic_backend&>::type operator = (A i) + { + m_value = i; + return *this; + } + template + arithmetic_backend& operator = (const arithmetic_backend& i) + { + m_value = i.data(); + return *this; + } + arithmetic_backend& operator = (const char* s) + { + try + { + m_value = boost::lexical_cast(s); + } + catch(const bad_lexical_cast&) + { + throw std::runtime_error(std::string("Unable to interpret the string provided: \"") + s + std::string("\" as a compatible number type.")); + } + return *this; + } + void swap(arithmetic_backend& o) + { + std::swap(m_value, o.m_value); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + std::stringstream ss; + ss.flags(f); + ss << std::setprecision(digits ? digits : std::numeric_limits::digits10 + 4) << m_value; + return ss.str(); + } + void do_negate(const mpl::true_&) + { + m_value = 1 + ~m_value; + } + void do_negate(const mpl::false_&) + { + m_value = -m_value; + } + void negate() + { + do_negate(is_unsigned()); + } + int compare(const arithmetic_backend& o)const + { + return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); + } + template + typename enable_if, int>::type compare(A i)const + { + return m_value > i ? 1 : (m_value < i ? -1 : 0); + } + Arithmetic& data() { return m_value; } + const Arithmetic& data()const { return m_value; } +private: + Arithmetic m_value; +}; + +template +inline void eval_convert_to(R* result, const arithmetic_backend& backend) +{ + *result = backend.data(); +} + +template +inline bool eval_eq(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() == b.data(); +} +template +inline bool eval_eq(const arithmetic_backend& a, const A2& b) +{ + return a.data() == b; +} +template +inline bool eval_lt(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() < b.data(); +} +template +inline bool eval_lt(const arithmetic_backend& a, const A2& b) +{ + return a.data() < b; +} +template +inline bool eval_gt(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() > b.data(); +} +template +inline bool eval_gt(const arithmetic_backend& a, const A2& b) +{ + return a.data() > b; +} + +template +inline void eval_add(arithmetic_backend& result, const arithmetic_backend& o) +{ + result.data() += o.data(); +} +template +inline void eval_subtract(arithmetic_backend& result, const arithmetic_backend& o) +{ + result.data() -= o.data(); +} +template +inline void eval_multiply(arithmetic_backend& result, const arithmetic_backend& o) +{ + result.data() *= o.data(); +} +template +inline typename enable_if_c::has_infinity>::type eval_divide(arithmetic_backend& result, const arithmetic_backend& o) +{ + result.data() /= o.data(); +} +template +inline typename disable_if_c::has_infinity>::type eval_divide(arithmetic_backend& result, const arithmetic_backend& o) +{ + if(!o.data()) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); + result.data() /= o.data(); +} + +template +inline typename enable_if >::type eval_add(arithmetic_backend& result, const A2& o) +{ + result.data() += o; +} +template +inline typename enable_if >::type eval_subtract(arithmetic_backend& result, const A2& o) +{ + result.data() -= o; +} +template +inline typename enable_if >::type eval_multiply(arithmetic_backend& result, const A2& o) +{ + result.data() *= o; +} +template +inline typename enable_if_c<(is_arithmetic::value && !std::numeric_limits::has_infinity)>::type + eval_divide(arithmetic_backend& result, const A2& o) +{ + if(!o) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); + result.data() /= o; +} +template +inline typename enable_if_c<(is_arithmetic::value && std::numeric_limits::has_infinity)>::type + eval_divide(arithmetic_backend& result, const A2& o) +{ + result.data() /= o; +} + +template +inline void eval_add(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = a.data() + b.data(); +} +template +inline void eval_subtract(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = a.data() - b.data(); +} +template +inline void eval_multiply(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = a.data() * b.data(); +} +template +inline typename enable_if_c::has_infinity>::type eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = a.data() / b.data(); +} +template +inline typename disable_if_c::has_infinity>::type eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + if(!b.data()) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); + result.data() = a.data() / b.data(); +} + +template +inline typename enable_if >::type eval_add(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) +{ + result.data() = a.data() + b; +} +template +inline typename enable_if >::type eval_subtract(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) +{ + result.data() = a.data() - b; +} +template +inline typename enable_if >::type eval_multiply(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) +{ + result.data() = a.data() * b; +} +template +inline typename enable_if_c<(is_arithmetic::value && !std::numeric_limits::has_infinity)>::type + eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) +{ + if(!b) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); + result.data() = a.data() / b; +} +template +inline typename enable_if_c<(is_arithmetic::value && std::numeric_limits::has_infinity)>::type + eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) +{ + result.data() = a.data() / b; +} + +template +inline bool eval_is_zero(const arithmetic_backend& val) +{ + return val.data() == 0; +} + +template +inline int eval_get_sign(const arithmetic_backend& val) +{ + return val.data() == 0 ? 0 : val.data() < 0 ? -1 : 1; +} + +template +inline typename enable_if, T>::type abs(T v) { return v; } + +template +inline void eval_abs(arithmetic_backend& result, const arithmetic_backend& o) +{ + using std::abs; + using boost::multiprecision::backends::abs; + result.data() = abs(o.data()); +} + +template +inline void eval_fabs(arithmetic_backend& result, const arithmetic_backend& o) +{ + result.data() = std::abs(o.data()); +} + +template +inline void eval_floor(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = floor(o.data()); +} + +template +inline void eval_ceil(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = ceil(o.data()); +} + +template +inline void eval_sqrt(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = sqrt(o.data()); +} + +template +inline int eval_fpclassify(const arithmetic_backend& o) +{ + return (boost::math::fpclassify)(o.data()); +} + +template +inline void eval_trunc(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = trunc(o.data()); +} + +template +inline void eval_round(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = round(o.data()); +} + +template +inline void eval_frexp(arithmetic_backend& result, const arithmetic_backend& a, int* v) +{ + BOOST_MATH_STD_USING + result.data() = frexp(a.data(), v); +} + +template +inline void eval_ldexp(arithmetic_backend& result, const arithmetic_backend& a, int v) +{ + BOOST_MATH_STD_USING + result.data() = ldexp(a.data(), v); +} + +template +inline void eval_exp(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = exp(o.data()); +} + +template +inline void eval_log(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = log(o.data()); +} + +template +inline void eval_log10(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = log10(o.data()); +} + +template +inline void eval_sin(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = sin(o.data()); +} + +template +inline void eval_cos(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = cos(o.data()); +} + +template +inline void eval_tan(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = tan(o.data()); +} + +template +inline void eval_acos(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = acos(o.data()); +} + +template +inline void eval_asin(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = asin(o.data()); +} + +template +inline void eval_atan(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = atan(o.data()); +} + +template +inline void eval_sinh(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = sinh(o.data()); +} + +template +inline void eval_cosh(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = cosh(o.data()); +} + +template +inline void eval_tanh(arithmetic_backend& result, const arithmetic_backend& o) +{ + BOOST_MATH_STD_USING + result.data() = tanh(o.data()); +} + +template +inline void eval_fmod(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + BOOST_MATH_STD_USING + result.data() = fmod(a.data(), b.data()); +} + +template +inline void eval_pow(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + BOOST_MATH_STD_USING + result.data() = pow(a.data(), b.data()); +} + +template +inline void eval_atan2(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + BOOST_MATH_STD_USING + result.data() = atan2(a.data(), b.data()); +} + +template +inline void eval_left_shift(arithmetic_backend& result, I val) +{ + result.data() <<= val; +} + +template +inline void eval_right_shift(arithmetic_backend& result, I val) +{ + result.data() >>= val; +} + +template +inline void eval_modulus(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() %= a.data(); +} + +template +inline void eval_bitwise_and(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() &= a.data(); +} + +template +inline void eval_bitwise_or(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() |= a.data(); +} + +template +inline void eval_bitwise_xor(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() ^= a.data(); +} + +template +inline void eval_complement(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() = ~a.data(); +} + +template +inline void eval_gcd(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = boost::math::gcd(a.data(), b.data()); +} + +template +inline void eval_lcm(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = boost::math::lcm(a.data(), b.data()); +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +} // namespace backends + +using boost::multiprecision::backends::arithmetic_backend; + +template +struct number_category > : public mpl::int_::value ? number_kind_integer : number_kind_floating_point>{}; + +namespace detail{ + +template +struct double_precision_type, ET> > +{ + typedef number::type>, ET> type; +}; +template<> +struct double_precision_type > +{ + typedef arithmetic_backend type; +}; + +} + +}} // namespaces + +namespace boost{ namespace math{ namespace tools{ + +template <> +inline double real_cast(concepts::real_concept r) +{ + return static_cast(r.value()); +} + +}}} + + +namespace std{ + +template +class numeric_limits, ExpressionTemplates > > : public std::numeric_limits +{ + typedef std::numeric_limits base_type; + typedef boost::multiprecision::number, ExpressionTemplates> number_type; +public: + BOOST_STATIC_CONSTEXPR number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } + BOOST_STATIC_CONSTEXPR number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } + BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); } + BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } + BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } + BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } + BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } + BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } + BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } +}; + +template<> +class numeric_limits : public std::numeric_limits +{ + typedef std::numeric_limits base_type; + typedef boost::math::concepts::real_concept number_type; +public: + static const number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } + static const number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } + static const number_type lowest() BOOST_NOEXCEPT { return -(max)(); } + static const number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } + static const number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } + static const number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } + static const number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } + static const number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } + static const number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } +}; + +} + +#include + +#endif diff --git a/performance/delaunay_test.cpp b/performance/delaunay_test.cpp new file mode 100644 index 00000000..d6fff135 --- /dev/null +++ b/performance/delaunay_test.cpp @@ -0,0 +1,295 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. +// Copyright 2012 Phil Endecott +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include "arithmetic_backend.hpp" +#include +#include +#include + +#include +#include + +template +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; + +// Custom 128-bit maths used for exact calculation of the Delaunay test. +// Only the few operators actually needed here are implemented. + +struct int128_t { + int64_t high; + uint64_t low; + + int128_t() {} + int128_t(int32_t i): high(i>>31), low(static_cast(i)) {} + int128_t(uint32_t i): high(0), low(i) {} + int128_t(int64_t i): high(i>>63), low(i) {} + int128_t(uint64_t i): high(0), low(i) {} +}; + +inline int128_t operator<<(int128_t val, int amt) +{ + int128_t r; + r.low = val.low << amt; + r.high = val.low >> (64-amt); + r.high |= val.high << amt; + return r; +} + +inline int128_t& operator+=(int128_t& l, int128_t r) +{ + l.low += r.low; + bool carry = l.low < r.low; + l.high += r.high; + if (carry) ++l.high; + return l; +} + +inline int128_t operator-(int128_t val) +{ + val.low = ~val.low; + val.high = ~val.high; + val.low += 1; + if (val.low == 0) val.high += 1; + return val; +} + +inline int128_t operator+(int128_t l, int128_t r) +{ + l += r; + return l; +} + +inline bool operator<(int128_t l, int128_t r) +{ + if (l.high != r.high) return l.high < r.high; + return l.low < r.low; +} + + +inline int128_t mult_64x64_to_128(int64_t a, int64_t b) +{ + // Make life simple by dealing only with positive numbers: + bool neg = false; + if (a<0) { neg = !neg; a = -a; } + if (b<0) { neg = !neg; b = -b; } + + // Divide input into 32-bit halves: + uint32_t ah = a >> 32; + uint32_t al = a & 0xffffffff; + uint32_t bh = b >> 32; + uint32_t bl = b & 0xffffffff; + + // Long multiplication, with 64-bit temporaries: + + // ah al + // * bh bl + // ---------------- + // al*bl (t1) + // + ah*bl (t2) + // + al*bh (t3) + // + ah*bh (t4) + // ---------------- + + uint64_t t1 = static_cast(al)*bl; + uint64_t t2 = static_cast(ah)*bl; + uint64_t t3 = static_cast(al)*bh; + uint64_t t4 = static_cast(ah)*bh; + + int128_t r(t1); + r.high = t4; + r += int128_t(t2) << 32; + r += int128_t(t3) << 32; + + if (neg) r = -r; + + return r; +} + +template +BOOST_FORCEINLINE void mul_2n(R& r, const T& a, const T& b) +{ + r = a; + r *= b; +} + +template +BOOST_FORCEINLINE void mul_2n(boost::multiprecision::number& r, const T& a, const T& b) +{ + multiply(r, a, b); +} + +BOOST_FORCEINLINE void mul_2n(int128_t& r, const boost::int64_t& a, const boost::int64_t& b) +{ + r = mult_64x64_to_128(a, b); +} + +template +inline bool delaunay_test(int32_t ax, int32_t ay, int32_t bx, int32_t by, + int32_t cx, int32_t cy, int32_t dx, int32_t dy) +{ + // Test whether the quadrilateral ABCD's diagonal AC should be flipped to BD. + // This is the Cline & Renka method. + // Flip if the sum of the angles ABC and CDA is greater than 180 degrees. + // Equivalently, flip if sin(ABC + CDA) < 0. + // Trig identity: cos(ABC) * sin(CDA) + sin(ABC) * cos(CDA) < 0 + // We can use scalar and vector products to find sin and cos, and simplify + // to the following code. + // Numerical robustness is important. This code addresses it by performing + // exact calculations with large integer types. + // + // NOTE: This routine is limited to inputs with up to 30 BIT PRECISION, which + // is to say all inputs must be in the range [INT_MIN/2, INT_MAX/2]. + + typedef typename Traits::i64_t i64; + typedef typename Traits::i128_t i128; + + i64 cos_abc, t; + mul_2n(cos_abc, (ax-bx), (cx-bx)); // subtraction yields 31-bit values, multiplied to give 62-bit values + mul_2n(t, (ay-by), (cy-by)); + cos_abc += t; // addition yields 63 bit value, leaving one left for the sign + + i64 cos_cda; + mul_2n(cos_cda, (cx-dx), (ax-dx)); + mul_2n(t, (cy-dy), (ay-dy)); + cos_cda += t; + + if (cos_abc >= 0 && cos_cda >= 0) return false; + if (cos_abc < 0 && cos_cda < 0) return true; + + i64 sin_abc; + mul_2n(sin_abc, (ax-bx), (cy-by)); + mul_2n(t, (cx-bx), (ay-by)); + sin_abc -= t; + + i64 sin_cda; + mul_2n(sin_cda, (cx-dx), (ay-dy)); + mul_2n(t, (ax-dx), (cy-dy)); + sin_cda -= t; + + i128 sin_sum, t128; + mul_2n(sin_sum, sin_abc, cos_cda); // 63-bit inputs multiplied to 126-bit output + mul_2n(t128, cos_abc, sin_cda); + sin_sum += t128; // Addition yields 127 bit result, leaving one bit for the sign + + return sin_sum < 0; +} + + +struct dt_dat { + int32_t ax, ay, bx, by, cx, cy, dx, dy; +}; + +typedef std::vector data_t; +data_t data; + +template +void do_calc(const char* name) +{ + std::cout << "Running calculations for: " << name << std::endl; + + stopwatch w; + + boost::uint64_t flips = 0; + boost::uint64_t calcs = 0; + + for(int j = 0; j < 1000; ++j) + { + for(data_t::const_iterator i = data.begin(); i != data.end(); ++i) + { + const dt_dat& d = *i; + bool flip = delaunay_test(d.ax,d.ay, d.bx,d.by, d.cx,d.cy, d.dx,d.dy); + if (flip) ++flips; + ++calcs; + } + } + double t = boost::chrono::duration_cast >(w.elapsed()).count(); + + std::cout << "Number of calculations = " << calcs << std::endl; + std::cout << "Number of flips = " << flips << std::endl; + std::cout << "Total execution time = " << t << std::endl; + std::cout << "Time per calculation = " << t / calcs << std::endl << std::endl; +} + +template +struct test_traits +{ + typedef I64 i64_t; + typedef I128 i128_t; +}; + + +dt_dat generate_quadrilateral() +{ + static boost::random::mt19937 gen; + static boost::random::uniform_int_distribution<> dist(INT_MIN/2, INT_MAX/2); + + dt_dat result; + + result.ax = dist(gen); + result.ay = dist(gen); + result.bx = boost::random::uniform_int_distribution<>(result.ax, INT_MAX/2)(gen); // bx is to the right of ax. + result.by = dist(gen); + result.cx = dist(gen); + result.cy = boost::random::uniform_int_distribution<>(result.cx > result.bx ? result.by : result.ay, INT_MAX/2)(gen); // cy is below at least one of ay and by. + result.dx = boost::random::uniform_int_distribution<>(result.cx, INT_MAX/2)(gen); // dx is to the right of cx. + result.dy = boost::random::uniform_int_distribution<>(result.cx > result.bx ? result.by : result.ay, INT_MAX/2)(gen); // cy is below at least one of ay and by. + + return result; +} + +static void load_data() +{ + for(unsigned i = 0; i < 100000; ++i) + data.push_back(generate_quadrilateral()); +} + + +int main() +{ + using namespace boost::multiprecision; + std::cout << "loading data...\n"; + load_data(); + + std::cout << "calculating...\n"; + + do_calc >("int64_t, int64_t"); + do_calc, et_off>, number, et_off> > >("arithmetic_backend, arithmetic_backend"); + do_calc, et_off> > >("int64_t, arithmetic_backend"); + do_calc, et_off>, number, et_off> > >("multiprecision::int64_t, multiprecision::int64_t"); + + do_calc >("int64_t, int128_t"); + do_calc >("int64_t, boost::multiprecision::int128_t"); + do_calc, et_on> > >("int64_t, int128_t (ET)"); + do_calc, et_off>, boost::multiprecision::int128_t > >("multiprecision::int64_t, multiprecision::int128_t"); + + do_calc >("int64_t, cpp_int"); + do_calc, et_off> > >("int64_t, cpp_int (no ET's)"); + do_calc > > >("int64_t, cpp_int(128-bit cache)"); + do_calc, et_off> > >("int64_t, cpp_int (128-bit Cache no ET's)"); + + return 0; +} + diff --git a/performance/linpack-benchmark.cpp b/performance/linpack-benchmark.cpp new file mode 100644 index 00000000..ec21f437 --- /dev/null +++ b/performance/linpack-benchmark.cpp @@ -0,0 +1,1249 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* 1000d.f -- translated by f2c (version 20050501). +You must link the resulting object file with libf2c: +on Microsoft Windows system, link with libf2c.lib; +on Linux or Unix systems, link with .../path/to/libf2c.a -lm +or, if you install libf2c.a in a standard place, with -lf2c -lm +-- in that order, at the end of the command line, as in +cc *.o -lf2c -lm +Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., + +http://www.netlib.org/f2c/libf2c.zip +*/ +#include +#include +#include +#include + +#if defined(TEST_GMPXX) +#include +typedef mpf_class real_type; +#elif defined(TEST_MPFRXX) +#include +typedef mpfr_class real_type; +#elif defined(TEST_CPP_DEC_FLOAT) +#include +typedef boost::multiprecision::cpp_dec_float_50 real_type; +#elif defined(TEST_MPFR_50) +#include +typedef boost::multiprecision::mpfr_float_50 real_type; +#elif defined(TEST_MPF_50) +#include +typedef boost::multiprecision::mpf_float_50 real_type; +#else +typedef double real_type; +#endif + +#ifndef CAST_TO_RT +# define CAST_TO_RT(x) x +#endif + +extern "C" { +#include "f2c.h" + integer s_wsfe(cilist *), e_wsfe(void), do_fio(integer *, char *, ftnlen), + s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), + e_wsle(void); + /* Subroutine */ int s_stop(char *, ftnlen); + +#undef abs +#undef dabs +#define dabs abs +#undef min +#undef max +#undef dmin +#undef dmax +#define dmin min +#define dmax max + +} +#include + +using std::min; +using std::max; + +/* Table of constant values */ + +static integer c__0 = 0; +static real_type c_b7 = CAST_TO_RT(1); +static integer c__1 = 1; +static integer c__9 = 9; + +inline double second_(void) +{ + return ((double)(clock())) / CLOCKS_PER_SEC; +} + +int dgefa_(real_type *, integer *, integer *, integer *, integer *), dgesl_(real_type *, integer *, integer *, integer *, real_type *, integer *); +int dmxpy_(integer *, real_type *, integer *, integer *, real_type *, real_type *); +int matgen_(real_type *, integer *, integer *, real_type *, real_type *); +real_type epslon_(real_type *); +real_type ran_(integer *); +int dscal_(integer *, real_type *, real_type *, integer *); +int daxpy_(integer *, real_type *, real_type *, integer *, real_type *, integer *); +integer idamax_(integer *, real_type *, integer *); +real_type ddot_(integer *, real_type *, integer *, real_type *, integer *); +int daxpy_(integer *, real_type *, real_type *, integer *, real_type *, integer *); +int dmxpy_(integer *, real_type *, integer *, integer *, real_type *, real_type *); + + +extern "C" int MAIN__() +{ +#ifdef TEST_MPF_50 + std::cout << "Testing number >" << std::endl; +#elif defined(TEST_MPFR_50) + std::cout << "Testing number >" << std::endl; +#elif defined(TEST_GMPXX) + std::cout << "Testing mpf_class at 50 decimal degits" << std::endl; + mpf_set_default_prec(((50 + 1) * 1000L) / 301L); +#elif defined(TEST_MPFRXX) + std::cout << "Testing mpfr_class at 50 decimal degits" << std::endl; + mpfr_set_default_prec(((50 + 1) * 1000L) / 301L); +#elif defined(TEST_CPP_DEC_FLOAT) + std::cout << "Testing number >" << std::endl; +#else + std::cout << "Testing double" << std::endl; +#endif + + + /* Format strings */ + static char fmt_1[] = "(\002 Please send the results of this run to:\002" + "//\002 Jack J. Dongarra\002/\002 Computer Science Department\002/" + "\002 University of Tennessee\002/\002 Knoxville, Tennessee 37996" + "-1300\002//\002 Fax: 615-974-8296\002//\002 Internet: dongarra@c" + "s.utk.edu\002/)"; + static char fmt_40[] = "(\002 norm. resid resid mac" + "hep\002,\002 x(1) x(n)\002)"; + static char fmt_50[] = "(1p5e16.8)"; + static char fmt_60[] = "(//\002 times are reported for matrices of or" + "der \002,i5)"; + static char fmt_70[] = "(6x,\002factor\002,5x,\002solve\002,6x,\002tota" + "l\002,5x,\002mflops\002,7x,\002unit\002,6x,\002ratio\002)"; + static char fmt_80[] = "(\002 times for array with leading dimension o" + "f\002,i4)"; + static char fmt_110[] = "(6(1pe11.3))"; + + /* System generated locals */ + integer i__1; + real_type d__1, d__2, d__3; + + /* Builtin functions */ + + /* Local variables */ + static real_type a[1001000] /* was [1001][1000] */, b[1000]; + static integer i__, n; + static real_type x[1000]; + static double t1; + static integer lda; + static double ops; + static real_type eps; + static integer info; + static double time[6], cray, total; + static integer ipvt[1000]; + static real_type resid, norma; + static real_type normx; + static real_type residn; + + /* Fortran I/O blocks */ + static cilist io___4 = { 0, 6, 0, fmt_1, 0 }; + static cilist io___20 = { 0, 6, 0, fmt_40, 0 }; + static cilist io___21 = { 0, 6, 0, fmt_50, 0 }; + static cilist io___22 = { 0, 6, 0, fmt_60, 0 }; + static cilist io___23 = { 0, 6, 0, fmt_70, 0 }; + static cilist io___24 = { 0, 6, 0, fmt_80, 0 }; + static cilist io___25 = { 0, 6, 0, fmt_110, 0 }; + static cilist io___26 = { 0, 6, 0, 0, 0 }; + + + lda = 1001; + + /* this program was updated on 10/12/92 to correct a */ + /* problem with the random number generator. The previous */ + /* random number generator had a short period and produced */ + /* singular matrices occasionally. */ + + n = 1000; + cray = .056f; + s_wsfe(&io___4); + e_wsfe(); + /* Computing 3rd power */ + d__1 = (real_type) n; + /* Computing 2nd power */ + d__2 = (real_type) n; + ops = boost::lexical_cast(real_type(d__1 * (d__1 * d__1) * 2. / 3. + d__2 * d__2 * 2.)); + + matgen_(a, &lda, &n, b, &norma); + + /* ****************************************************************** */ + /* ****************************************************************** */ + /* you should replace the call to dgefa and dgesl */ + /* by calls to your linear equation solver. */ + /* ****************************************************************** */ + /* ****************************************************************** */ + + t1 = second_(); + dgefa_(a, &lda, &n, ipvt, &info); + time[0] = second_() - t1; + t1 = second_(); + dgesl_(a, &lda, &n, ipvt, b, &c__0); + time[1] = second_() - t1; + total = time[0] + time[1]; + /* ****************************************************************** */ + /* ****************************************************************** */ + + /* compute a residual to verify results. */ + + i__1 = n; + for (i__ = 1; i__ <= i__1; ++i__) { + x[i__ - 1] = b[i__ - 1]; + /* L10: */ + } + matgen_(a, &lda, &n, b, &norma); + i__1 = n; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__ - 1] = -b[i__ - 1]; + /* L20: */ + } + dmxpy_(&n, b, &n, &lda, x, a); + resid = CAST_TO_RT(0); + normx = CAST_TO_RT(0); + i__1 = n; + for (i__ = 1; i__ <= i__1; ++i__) { + /* Computing MAX */ + d__2 = resid, d__3 = (d__1 = b[i__ - 1], abs(d__1)); + resid = max(d__2,d__3); + /* Computing MAX */ + d__2 = normx, d__3 = (d__1 = x[i__ - 1], abs(d__1)); + normx = max(d__2,d__3); + /* L30: */ + } + eps = epslon_(&c_b7); + residn = resid / (n * norma * normx * eps); + s_wsfe(&io___20); + e_wsfe(); + s_wsfe(&io___21); + /* + do_fio(&c__1, (char *)&residn, (ftnlen)sizeof(real_type)); + do_fio(&c__1, (char *)&resid, (ftnlen)sizeof(real_type)); + do_fio(&c__1, (char *)&eps, (ftnlen)sizeof(real_type)); + do_fio(&c__1, (char *)&x[0], (ftnlen)sizeof(real_type)); + do_fio(&c__1, (char *)&x[n - 1], (ftnlen)sizeof(real_type)); + */ + std::cout << std::setw(12) << std::setprecision(5) << residn << " " << resid << " " << eps << " " << x[0] << " " << x[n-1] << std::endl; + e_wsfe(); + + s_wsfe(&io___22); + do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer)); + e_wsfe(); + s_wsfe(&io___23); + e_wsfe(); + + time[2] = total; + time[3] = ops / (total * 1e6); + time[4] = 2. / time[3]; + time[5] = total / cray; + s_wsfe(&io___24); + do_fio(&c__1, (char *)&lda, (ftnlen)sizeof(integer)); + e_wsfe(); + s_wsfe(&io___25); + for (i__ = 1; i__ <= 6; ++i__) { + // do_fio(&c__1, (char *)&time[i__ - 1], (ftnlen)sizeof(real_type)); + std::cout << std::setw(12) << std::setprecision(5) << time[i__ - 1]; + } + e_wsfe(); + s_wsle(&io___26); + do_lio(&c__9, &c__1, " end of tests -- this version dated 10/12/92", ( + ftnlen)44); + e_wsle(); + + s_stop("", (ftnlen)0); + return 0; +} /* MAIN__ */ + +/* Subroutine */ int matgen_(real_type *a, integer *lda, integer *n, + real_type *b, real_type *norma) +{ + /* System generated locals */ + integer a_dim1, a_offset, i__1, i__2; + real_type d__1, d__2; + + /* Local variables */ + static integer i__, j; + static integer init[4]; + + + /* Parameter adjustments */ + a_dim1 = *lda; + a_offset = 1 + a_dim1; + a -= a_offset; + --b; + + /* Function Body */ + init[0] = 1; + init[1] = 2; + init[2] = 3; + init[3] = 1325; + *norma = CAST_TO_RT(0); + i__1 = *n; + for (j = 1; j <= i__1; ++j) { + i__2 = *n; + for (i__ = 1; i__ <= i__2; ++i__) { + a[i__ + j * a_dim1] = ran_(init) - .5f; + /* Computing MAX */ + d__2 = (d__1 = a[i__ + j * a_dim1], abs(d__1)); + *norma = max(d__2,*norma); + /* L20: */ + } + /* L30: */ + } + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__] = CAST_TO_RT(0); + /* L35: */ + } + i__1 = *n; + for (j = 1; j <= i__1; ++j) { + i__2 = *n; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__] += a[i__ + j * a_dim1]; + /* L40: */ + } + /* L50: */ + } + return 0; +} /* matgen_ */ + +/* Subroutine */ int dgefa_(real_type *a, integer *lda, integer *n, integer * + ipvt, integer *info) +{ + /* System generated locals */ + integer a_dim1, a_offset, i__1, i__2, i__3; + + /* Local variables */ + static integer j, k, l; + static real_type t; + static integer kp1, nm1; + + + /* dgefa factors a double precision matrix by gaussian elimination. */ + + /* dgefa is usually called by dgeco, but it can be called */ + /* directly with a saving in time if rcond is not needed. */ + /* (time for dgeco) = (1 + 9/n)*(time for dgefa) . */ + + /* on entry */ + + /* a double precision(lda, n) */ + /* the matrix to be factored. */ + + /* lda integer */ + /* the leading dimension of the array a . */ + + /* n integer */ + /* the order of the matrix a . */ + + /* on return */ + + /* a an upper triangular matrix and the multipliers */ + /* which were used to obtain it. */ + /* the factorization can be written a = l*u where */ + /* l is a product of permutation and unit lower */ + /* triangular matrices and u is upper triangular. */ + + /* ipvt integer(n) */ + /* an integer vector of pivot indices. */ + + /* info integer */ + /* = 0 normal value. */ + /* = k if u(k,k) .eq. 0.0 . this is not an error */ + /* condition for this subroutine, but it does */ + /* indicate that dgesl or dgedi will divide by zero */ + /* if called. use rcond in dgeco for a reliable */ + /* indication of singularity. */ + + /* linpack. this version dated 08/14/78 . */ + /* cleve moler, university of new mexico, argonne national lab. */ + + /* subroutines and functions */ + + /* blas daxpy,dscal,idamax */ + + /* internal variables */ + + + + /* gaussian elimination with partial pivoting */ + + /* Parameter adjustments */ + a_dim1 = *lda; + a_offset = 1 + a_dim1; + a -= a_offset; + --ipvt; + + /* Function Body */ + *info = 0; + nm1 = *n - 1; + if (nm1 < 1) { + goto L70; + } + i__1 = nm1; + for (k = 1; k <= i__1; ++k) { + kp1 = k + 1; + + /* find l = pivot index */ + + i__2 = *n - k + 1; + l = idamax_(&i__2, &a[k + k * a_dim1], &c__1) + k - 1; + ipvt[k] = l; + + /* zero pivot implies this column already triangularized */ + + if (a[l + k * a_dim1] == 0.) { + goto L40; + } + + /* interchange if necessary */ + + if (l == k) { + goto L10; + } + t = a[l + k * a_dim1]; + a[l + k * a_dim1] = a[k + k * a_dim1]; + a[k + k * a_dim1] = t; +L10: + + /* compute multipliers */ + + t = -1. / a[k + k * a_dim1]; + i__2 = *n - k; + dscal_(&i__2, &t, &a[k + 1 + k * a_dim1], &c__1); + + /* row elimination with column indexing */ + + i__2 = *n; + for (j = kp1; j <= i__2; ++j) { + t = a[l + j * a_dim1]; + if (l == k) { + goto L20; + } + a[l + j * a_dim1] = a[k + j * a_dim1]; + a[k + j * a_dim1] = t; +L20: + i__3 = *n - k; + daxpy_(&i__3, &t, &a[k + 1 + k * a_dim1], &c__1, &a[k + 1 + j * + a_dim1], &c__1); + /* L30: */ + } + goto L50; +L40: + *info = k; +L50: + /* L60: */ + ; + } +L70: + ipvt[*n] = *n; + if (a[*n + *n * a_dim1] == 0.) { + *info = *n; + } + return 0; +} /* dgefa_ */ + +/* Subroutine */ int dgesl_(real_type *a, integer *lda, integer *n, integer * + ipvt, real_type *b, integer *job) +{ + /* System generated locals */ + integer a_dim1, a_offset, i__1, i__2; + + /* Local variables */ + static integer k, l; + static real_type t; + static integer kb, nm1; + + + /* dgesl solves the double precision system */ + /* a * x = b or trans(a) * x = b */ + /* using the factors computed by dgeco or dgefa. */ + + /* on entry */ + + /* a double precision(lda, n) */ + /* the output from dgeco or dgefa. */ + + /* lda integer */ + /* the leading dimension of the array a . */ + + /* n integer */ + /* the order of the matrix a . */ + + /* ipvt integer(n) */ + /* the pivot vector from dgeco or dgefa. */ + + /* b double precision(n) */ + /* the right hand side vector. */ + + /* job integer */ + /* = 0 to solve a*x = b , */ + /* = nonzero to solve trans(a)*x = b where */ + /* trans(a) is the transpose. */ + + /* on return */ + + /* b the solution vector x . */ + + /* error condition */ + + /* a division by zero will occur if the input factor contains a */ + /* zero on the diagonal. technically this indicates singularity */ + /* but it is often caused by improper arguments or improper */ + /* setting of lda . it will not occur if the subroutines are */ + /* called correctly and if dgeco has set rcond .gt. 0.0 */ + /* or dgefa has set info .eq. 0 . */ + + /* to compute inverse(a) * c where c is a matrix */ + /* with p columns */ + /* call dgeco(a,lda,n,ipvt,rcond,z) */ + /* if (rcond is too small) go to ... */ + /* do 10 j = 1, p */ + /* call dgesl(a,lda,n,ipvt,c(1,j),0) */ + /* 10 continue */ + + /* linpack. this version dated 08/14/78 . */ + /* cleve moler, university of new mexico, argonne national lab. */ + + /* subroutines and functions */ + + /* blas daxpy,ddot */ + + /* internal variables */ + + + /* Parameter adjustments */ + a_dim1 = *lda; + a_offset = 1 + a_dim1; + a -= a_offset; + --ipvt; + --b; + + /* Function Body */ + nm1 = *n - 1; + if (*job != 0) { + goto L50; + } + + /* job = 0 , solve a * x = b */ + /* first solve l*y = b */ + + if (nm1 < 1) { + goto L30; + } + i__1 = nm1; + for (k = 1; k <= i__1; ++k) { + l = ipvt[k]; + t = b[l]; + if (l == k) { + goto L10; + } + b[l] = b[k]; + b[k] = t; +L10: + i__2 = *n - k; + daxpy_(&i__2, &t, &a[k + 1 + k * a_dim1], &c__1, &b[k + 1], &c__1); + /* L20: */ + } +L30: + + /* now solve u*x = y */ + + i__1 = *n; + for (kb = 1; kb <= i__1; ++kb) { + k = *n + 1 - kb; + b[k] /= a[k + k * a_dim1]; + t = -b[k]; + i__2 = k - 1; + daxpy_(&i__2, &t, &a[k * a_dim1 + 1], &c__1, &b[1], &c__1); + /* L40: */ + } + goto L100; +L50: + + /* job = nonzero, solve trans(a) * x = b */ + /* first solve trans(u)*y = b */ + + i__1 = *n; + for (k = 1; k <= i__1; ++k) { + i__2 = k - 1; + t = ddot_(&i__2, &a[k * a_dim1 + 1], &c__1, &b[1], &c__1); + b[k] = (b[k] - t) / a[k + k * a_dim1]; + /* L60: */ + } + + /* now solve trans(l)*x = y */ + + if (nm1 < 1) { + goto L90; + } + i__1 = nm1; + for (kb = 1; kb <= i__1; ++kb) { + k = *n - kb; + i__2 = *n - k; + b[k] += ddot_(&i__2, &a[k + 1 + k * a_dim1], &c__1, &b[k + 1], &c__1); + l = ipvt[k]; + if (l == k) { + goto L70; + } + t = b[l]; + b[l] = b[k]; + b[k] = t; +L70: + /* L80: */ + ; + } +L90: +L100: + return 0; +} /* dgesl_ */ + +/* Subroutine */ int daxpy_(integer *n, real_type *da, real_type *dx, + integer *incx, real_type *dy, integer *incy) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + static integer i__, m, ix, iy, mp1; + + + /* constant times a vector plus a vector. */ + /* uses unrolled loops for increments equal to one. */ + /* jack dongarra, linpack, 3/11/78. */ + + + /* Parameter adjustments */ + --dy; + --dx; + + /* Function Body */ + if (*n <= 0) { + return 0; + } + if (*da == 0.) { + return 0; + } + if (*incx == 1 && *incy == 1) { + goto L20; + } + + /* code for unequal increments or equal increments */ + /* not equal to 1 */ + + ix = 1; + iy = 1; + if (*incx < 0) { + ix = (-(*n) + 1) * *incx + 1; + } + if (*incy < 0) { + iy = (-(*n) + 1) * *incy + 1; + } + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + dy[iy] += *da * dx[ix]; + ix += *incx; + iy += *incy; + /* L10: */ + } + return 0; + + /* code for both increments equal to 1 */ + + + /* clean-up loop */ + +L20: + m = *n % 4; + if (m == 0) { + goto L40; + } + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + dy[i__] += *da * dx[i__]; + /* L30: */ + } + if (*n < 4) { + return 0; + } +L40: + mp1 = m + 1; + i__1 = *n; + for (i__ = mp1; i__ <= i__1; i__ += 4) { + dy[i__] += *da * dx[i__]; + dy[i__ + 1] += *da * dx[i__ + 1]; + dy[i__ + 2] += *da * dx[i__ + 2]; + dy[i__ + 3] += *da * dx[i__ + 3]; + /* L50: */ + } + return 0; +} /* daxpy_ */ + +real_type ddot_(integer *n, real_type *dx, integer *incx, real_type *dy, + integer *incy) +{ + /* System generated locals */ + integer i__1; + real_type ret_val; + + /* Local variables */ + static integer i__, m, ix, iy, mp1; + static real_type dtemp; + + + /* forms the dot product of two vectors. */ + /* uses unrolled loops for increments equal to one. */ + /* jack dongarra, linpack, 3/11/78. */ + + + /* Parameter adjustments */ + --dy; + --dx; + + /* Function Body */ + ret_val = CAST_TO_RT(0); + dtemp = CAST_TO_RT(0); + if (*n <= 0) { + return ret_val; + } + if (*incx == 1 && *incy == 1) { + goto L20; + } + + /* code for unequal increments or equal increments */ + /* not equal to 1 */ + + ix = 1; + iy = 1; + if (*incx < 0) { + ix = (-(*n) + 1) * *incx + 1; + } + if (*incy < 0) { + iy = (-(*n) + 1) * *incy + 1; + } + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + dtemp += dx[ix] * dy[iy]; + ix += *incx; + iy += *incy; + /* L10: */ + } + ret_val = dtemp; + return ret_val; + + /* code for both increments equal to 1 */ + + + /* clean-up loop */ + +L20: + m = *n % 5; + if (m == 0) { + goto L40; + } + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + dtemp += dx[i__] * dy[i__]; + /* L30: */ + } + if (*n < 5) { + goto L60; + } +L40: + mp1 = m + 1; + i__1 = *n; + for (i__ = mp1; i__ <= i__1; i__ += 5) { + dtemp = dtemp + dx[i__] * dy[i__] + dx[i__ + 1] * dy[i__ + 1] + dx[ + i__ + 2] * dy[i__ + 2] + dx[i__ + 3] * dy[i__ + 3] + dx[i__ + + 4] * dy[i__ + 4]; + /* L50: */ + } +L60: + ret_val = dtemp; + return ret_val; +} /* ddot_ */ + +/* Subroutine */ int dscal_(integer *n, real_type *da, real_type *dx, + integer *incx) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Local variables */ + static integer i__, m, mp1, nincx; + + + /* scales a vector by a constant. */ + /* uses unrolled loops for increment equal to one. */ + /* jack dongarra, linpack, 3/11/78. */ + + + /* Parameter adjustments */ + --dx; + + /* Function Body */ + if (*n <= 0) { + return 0; + } + if (*incx == 1) { + goto L20; + } + + /* code for increment not equal to 1 */ + + nincx = *n * *incx; + i__1 = nincx; + i__2 = *incx; + for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) { + dx[i__] = *da * dx[i__]; + /* L10: */ + } + return 0; + + /* code for increment equal to 1 */ + + + /* clean-up loop */ + +L20: + m = *n % 5; + if (m == 0) { + goto L40; + } + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + dx[i__] = *da * dx[i__]; + /* L30: */ + } + if (*n < 5) { + return 0; + } +L40: + mp1 = m + 1; + i__2 = *n; + for (i__ = mp1; i__ <= i__2; i__ += 5) { + dx[i__] = *da * dx[i__]; + dx[i__ + 1] = *da * dx[i__ + 1]; + dx[i__ + 2] = *da * dx[i__ + 2]; + dx[i__ + 3] = *da * dx[i__ + 3]; + dx[i__ + 4] = *da * dx[i__ + 4]; + /* L50: */ + } + return 0; +} /* dscal_ */ + +integer idamax_(integer *n, real_type *dx, integer *incx) +{ + /* System generated locals */ + integer ret_val, i__1; + real_type d__1; + + /* Local variables */ + static integer i__, ix; + static real_type dmax__; + + + /* finds the index of element having max. dabsolute value. */ + /* jack dongarra, linpack, 3/11/78. */ + + + /* Parameter adjustments */ + --dx; + + /* Function Body */ + ret_val = 0; + if (*n < 1) { + return ret_val; + } + ret_val = 1; + if (*n == 1) { + return ret_val; + } + if (*incx == 1) { + goto L20; + } + + /* code for increment not equal to 1 */ + + ix = 1; + dmax__ = abs(dx[1]); + ix += *incx; + i__1 = *n; + for (i__ = 2; i__ <= i__1; ++i__) { + if ((d__1 = dx[ix], abs(d__1)) <= dmax__) { + goto L5; + } + ret_val = i__; + dmax__ = (d__1 = dx[ix], abs(d__1)); +L5: + ix += *incx; + /* L10: */ + } + return ret_val; + + /* code for increment equal to 1 */ + +L20: + dmax__ = abs(dx[1]); + i__1 = *n; + for (i__ = 2; i__ <= i__1; ++i__) { + if ((d__1 = dx[i__], abs(d__1)) <= dmax__) { + goto L30; + } + ret_val = i__; + dmax__ = (d__1 = dx[i__], abs(d__1)); +L30: + ; + } + return ret_val; +} /* idamax_ */ + +real_type epslon_(real_type *x) +{ +#if defined(TEST_MPF_100) || defined(TEST_MPFR_100) || defined(TEST_GMPXX) || defined(TEST_MPFRXX) + return std::ldexp(1.0, 1 - ((100 + 1) * 1000L) / 301L); +#elif defined(TEST_CPP_DEC_FLOAT_BN) + return std::pow(10.0, 1-std::numeric_limits::digits10); +#else + return CAST_TO_RT(std::numeric_limits::epsilon()); +#endif +} /* epslon_ */ + +/* Subroutine */ int mm_(real_type *a, integer *lda, integer *n1, integer * + n3, real_type *b, integer *ldb, integer *n2, real_type *c__, + integer *ldc) +{ + /* System generated locals */ + integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2; + + /* Local variables */ + static integer i__, j; + + + /* purpose: */ + /* multiply matrix b times matrix c and store the result in matrix a. */ + + /* parameters: */ + + /* a double precision(lda,n3), matrix of n1 rows and n3 columns */ + + /* lda integer, leading dimension of array a */ + + /* n1 integer, number of rows in matrices a and b */ + + /* n3 integer, number of columns in matrices a and c */ + + /* b double precision(ldb,n2), matrix of n1 rows and n2 columns */ + + /* ldb integer, leading dimension of array b */ + + /* n2 integer, number of columns in matrix b, and number of rows in */ + /* matrix c */ + + /* c double precision(ldc,n3), matrix of n2 rows and n3 columns */ + + /* ldc integer, leading dimension of array c */ + + /* ---------------------------------------------------------------------- */ + + /* Parameter adjustments */ + a_dim1 = *lda; + a_offset = 1 + a_dim1; + a -= a_offset; + b_dim1 = *ldb; + b_offset = 1 + b_dim1; + b -= b_offset; + c_dim1 = *ldc; + c_offset = 1 + c_dim1; + c__ -= c_offset; + + /* Function Body */ + i__1 = *n3; + for (j = 1; j <= i__1; ++j) { + i__2 = *n1; + for (i__ = 1; i__ <= i__2; ++i__) { + a[i__ + j * a_dim1] = CAST_TO_RT(0); + /* L10: */ + } + dmxpy_(n2, &a[j * a_dim1 + 1], n1, ldb, &c__[j * c_dim1 + 1], &b[ + b_offset]); + /* L20: */ + } + + return 0; +} /* mm_ */ + +/* Subroutine */ int dmxpy_(integer *n1, real_type *y, integer *n2, integer * + ldm, real_type *x, real_type *m) +{ + /* System generated locals */ + integer m_dim1, m_offset, i__1, i__2; + + /* Local variables */ + static integer i__, j, jmin; + + + /* purpose: */ + /* multiply matrix m times vector x and add the result to vector y. */ + + /* parameters: */ + + /* n1 integer, number of elements in vector y, and number of rows in */ + /* matrix m */ + + /* y double precision(n1), vector of length n1 to which is added */ + /* the product m*x */ + + /* n2 integer, number of elements in vector x, and number of columns */ + /* in matrix m */ + + /* ldm integer, leading dimension of array m */ + + /* x double precision(n2), vector of length n2 */ + + /* m double precision(ldm,n2), matrix of n1 rows and n2 columns */ + + /* ---------------------------------------------------------------------- */ + + /* cleanup odd vector */ + + /* Parameter adjustments */ + --y; + m_dim1 = *ldm; + m_offset = 1 + m_dim1; + m -= m_offset; + --x; + + /* Function Body */ + j = *n2 % 2; + if (j >= 1) { + i__1 = *n1; + for (i__ = 1; i__ <= i__1; ++i__) { + y[i__] += x[j] * m[i__ + j * m_dim1]; + /* L10: */ + } + } + + /* cleanup odd group of two vectors */ + + j = *n2 % 4; + if (j >= 2) { + i__1 = *n1; + for (i__ = 1; i__ <= i__1; ++i__) { + y[i__] = y[i__] + x[j - 1] * m[i__ + (j - 1) * m_dim1] + x[j] * m[ + i__ + j * m_dim1]; + /* L20: */ + } + } + + /* cleanup odd group of four vectors */ + + j = *n2 % 8; + if (j >= 4) { + i__1 = *n1; + for (i__ = 1; i__ <= i__1; ++i__) { + y[i__] = y[i__] + x[j - 3] * m[i__ + (j - 3) * m_dim1] + x[j - 2] + * m[i__ + (j - 2) * m_dim1] + x[j - 1] * m[i__ + (j - 1) * + m_dim1] + x[j] * m[i__ + j * m_dim1]; + /* L30: */ + } + } + + /* cleanup odd group of eight vectors */ + + j = *n2 % 16; + if (j >= 8) { + i__1 = *n1; + for (i__ = 1; i__ <= i__1; ++i__) { + y[i__] = y[i__] + x[j - 7] * m[i__ + (j - 7) * m_dim1] + x[j - 6] + * m[i__ + (j - 6) * m_dim1] + x[j - 5] * m[i__ + (j - 5) * + m_dim1] + x[j - 4] * m[i__ + (j - 4) * m_dim1] + x[j - 3] + * m[i__ + (j - 3) * m_dim1] + x[j - 2] * m[i__ + (j - 2) + * m_dim1] + x[j - 1] * m[i__ + (j - 1) * m_dim1] + x[j] * + m[i__ + j * m_dim1]; + /* L40: */ + } + } + + /* main loop - groups of sixteen vectors */ + + jmin = j + 16; + i__1 = *n2; + for (j = jmin; j <= i__1; j += 16) { + i__2 = *n1; + for (i__ = 1; i__ <= i__2; ++i__) { + y[i__] = y[i__] + x[j - 15] * m[i__ + (j - 15) * m_dim1] + x[j - + 14] * m[i__ + (j - 14) * m_dim1] + x[j - 13] * m[i__ + (j + - 13) * m_dim1] + x[j - 12] * m[i__ + (j - 12) * m_dim1] + + x[j - 11] * m[i__ + (j - 11) * m_dim1] + x[j - 10] * m[ + i__ + (j - 10) * m_dim1] + x[j - 9] * m[i__ + (j - 9) * + m_dim1] + x[j - 8] * m[i__ + (j - 8) * m_dim1] + x[j - 7] + * m[i__ + (j - 7) * m_dim1] + x[j - 6] * m[i__ + (j - 6) * + m_dim1] + x[j - 5] * m[i__ + (j - 5) * m_dim1] + x[j - 4] + * m[i__ + (j - 4) * m_dim1] + x[j - 3] * m[i__ + (j - 3) + * m_dim1] + x[j - 2] * m[i__ + (j - 2) * m_dim1] + x[j - + 1] * m[i__ + (j - 1) * m_dim1] + x[j] * m[i__ + j * + m_dim1]; + /* L50: */ + } + /* L60: */ + } + return 0; +} /* dmxpy_ */ + +real_type ran_(integer *iseed) +{ + /* System generated locals */ + real_type ret_val; + + /* Local variables */ + static integer it1, it2, it3, it4; + + + /* modified from the LAPACK auxiliary routine 10/12/92 JD */ + /* -- LAPACK auxiliary routine (version 1.0) -- */ + /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ + /* Courant Institute, Argonne National Lab, and Rice University */ + /* February 29, 1992 */ + + /* .. Array Arguments .. */ + /* .. */ + + /* Purpose */ + /* ======= */ + + /* DLARAN returns a random double number from a uniform (0,1) */ + /* distribution. */ + + /* Arguments */ + /* ========= */ + + /* ISEED (input/output) INTEGER array, dimension (4) */ + /* On entry, the seed of the random number generator; the array */ + /* elements must be between 0 and 4095, and ISEED(4) must be */ + /* odd. */ + /* On exit, the seed is updated. */ + + /* Further Details */ + /* =============== */ + + /* This routine uses a multiplicative congruential method with modulus */ + /* 2**48 and multiplier 33952834046453 (see G.S.Fishman, */ + /* 'Multiplicative congruential random number generators with modulus */ + /* 2**b: an exhaustive analysis for b = 32 and a partial analysis for */ + /* b = 48', Math. Comp. 189, pp 331-344, 1990). */ + + /* 48-bit integers are stored in 4 integer array elements with 12 bits */ + /* per element. Hence the routine is portable across machines with */ + /* integers of 32 bits or more. */ + + /* .. Parameters .. */ + /* .. */ + /* .. Local Scalars .. */ + /* .. */ + /* .. Intrinsic Functions .. */ + /* .. */ + /* .. Executable Statements .. */ + + /* multiply the seed by the multiplier modulo 2**48 */ + + /* Parameter adjustments */ + --iseed; + + /* Function Body */ + it4 = iseed[4] * 2549; + it3 = it4 / 4096; + it4 -= it3 << 12; + it3 = it3 + iseed[3] * 2549 + iseed[4] * 2508; + it2 = it3 / 4096; + it3 -= it2 << 12; + it2 = it2 + iseed[2] * 2549 + iseed[3] * 2508 + iseed[4] * 322; + it1 = it2 / 4096; + it2 -= it1 << 12; + it1 = it1 + iseed[1] * 2549 + iseed[2] * 2508 + iseed[3] * 322 + iseed[4] + * 494; + it1 %= 4096; + + /* return updated seed */ + + iseed[1] = it1; + iseed[2] = it2; + iseed[3] = it3; + iseed[4] = it4; + + /* convert 48-bit integer to a double number in the interval (0,1) */ + + ret_val = ((real_type) it1 + ((real_type) it2 + ((real_type) it3 + ( + real_type) it4 * 2.44140625e-4) * 2.44140625e-4) * 2.44140625e-4) + * 2.44140625e-4; + return ret_val; + + /* End of RAN */ + +} /* ran_ */ + +/* + +Double results: +~~~~~~~~~~~~~~ + +norm. resid resid machep x(1) x(n) +6.4915 7.207e-013 2.2204e-016 1 1 + + + +times are reported for matrices of order 1000 +factor solve total mflops unit ratio +times for array with leading dimension of1001 +1.443 0.003 1.446 462.43 0.004325 25.821 + + +mpf_class results: +~~~~~~~~~~~~~~~~~~ + +norm. resid resid machep x(1) x(n) +3.6575e-05 5.2257e-103 2.8575e-101 1 1 + + + +times are reported for matrices of order 1000 +factor solve total mflops unit ratio +times for array with leading dimension of1001 +266.45 0.798 267.24 2.5021 0.79933 4772.2 + + +number >: +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + norm. resid resid machep x(1) x(n) + 0.36575e-4 0.52257e-102 0.28575e-100 0.1e1 0.1e1 + + + + times are reported for matrices of order 1000 + factor solve total mflops unit ratio + times for array with leading dimension of1001 + 279.96 0.84 280.8 2.3813 0.83988 5014.3 + +boost::multiprecision::ef::cpp_dec_float_50: +~~~~~~~~~~~~~~~~~~~~~~~~~ + + norm. resid resid machep x(1) x(n) + 2.551330735e-16 1.275665107e-112 1e-99 1 1 + + + + times are reported for matrices of order 1000 + factor solve total mflops unit ratio + times for array with leading dimension of1001 + 363.89 1.074 364.97 1.8321 1.0916 6517.3 +*/ diff --git a/performance/miller_rabin_performance.cpp b/performance/miller_rabin_performance.cpp new file mode 100644 index 00000000..e4ca6a50 --- /dev/null +++ b/performance/miller_rabin_performance.cpp @@ -0,0 +1,167 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#define BOOST_CHRONO_HEADER_ONLY + +#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +# define TEST_MPZ +# define TEST_TOMMATH +# define TEST_CPP_INT +#endif + +#ifdef TEST_MPZ +#include +#endif +#ifdef TEST_TOMMATH +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif +#include +#include +#include + +template +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; + +unsigned allocation_count = 0; + +void *(*alloc_func_ptr) (size_t); +void *(*realloc_func_ptr) (void *, size_t, size_t); +void (*free_func_ptr) (void *, size_t); + +void *alloc_func(size_t n) +{ + ++allocation_count; + return (*alloc_func_ptr)(n); +} + +void free_func(void * p, size_t n) +{ + (*free_func_ptr)(p, n); +} + +void * realloc_func(void * p, size_t old, size_t n) +{ + ++allocation_count; + return (*realloc_func_ptr)(p, old, n); +} + +#ifdef TEST_MPZ +boost::chrono::duration test_miller_rabin_gmp() +{ + using namespace boost::random; + using namespace boost::multiprecision; + + stopwatch c; + + independent_bits_engine gen; + + for(unsigned i = 0; i < 1000; ++i) + { + mpz_int n = gen(); + mpz_probab_prime_p(n.backend().data(), 25); + } + return c.elapsed(); +} +#endif + +std::map results; +double min_time = (std::numeric_limits::max)(); + +template +boost::chrono::duration test_miller_rabin(const char* name) +{ + using namespace boost::random; + + stopwatch c; + + independent_bits_engine gen; + // + // We must use a different generator for the tests and number generation, otherwise + // we get false positives. + // + mt19937 gen2; + unsigned result_count = 0; + + for(unsigned i = 0; i < 1000; ++i) + { + IntType n = gen(); + if(boost::multiprecision::miller_rabin_test(n, 25, gen2)) + ++result_count; + } + boost::chrono::duration t = c.elapsed(); + double d = t.count(); + if(d < min_time) + min_time = d; + results[name] = d; + std::cout << "Time for " << std::setw(30) << std::left << name << " = " << d << std::endl; + std::cout << "Number of primes found = " << result_count << std::endl; + return t; +} + +void generate_quickbook() +{ + std::cout << "[table\n[[Integer Type][Relative Performance (Actual time in parenthesis)]]\n"; + + std::map::const_iterator i(results.begin()), j(results.end()); + + while(i != j) + { + double rel = i->second / min_time; + std::cout << "[[" << i->first << "][" << rel << "(" << i->second << "s)]]\n"; + ++i; + } + + std::cout << "]\n"; +} + +int main() +{ + using namespace boost::multiprecision; +#ifdef TEST_CPP_INT + test_miller_rabin, et_off> >("cpp_int (no Expression templates)"); + test_miller_rabin("cpp_int"); + test_miller_rabin > >("cpp_int (128-bit cache)"); + test_miller_rabin > >("cpp_int (256-bit cache)"); + test_miller_rabin > >("cpp_int (512-bit cache)"); + test_miller_rabin > >("cpp_int (1024-bit cache)"); + test_miller_rabin("int1024_t"); + test_miller_rabin("checked_int1024_t"); +#endif +#ifdef TEST_MPZ + test_miller_rabin >("mpz_int (no Expression templates)"); + test_miller_rabin("mpz_int"); + std::cout << "Time for mpz_int (native Miller Rabin Test) = " << test_miller_rabin_gmp() << std::endl; +#endif +#ifdef TEST_TOMMATH + test_miller_rabin >("tom_int (no Expression templates)"); + test_miller_rabin("tom_int"); +#endif + + generate_quickbook(); + + return 0; +} + diff --git a/performance/performance_test-gcc-linux.log b/performance/performance_test-gcc-linux.log new file mode 100644 index 00000000..83b15004 --- /dev/null +++ b/performance/performance_test-gcc-linux.log @@ -0,0 +1,718 @@ +gmp_float 50 + 0.0180885 +gmp_float 50 - 0.0227712 +gmp_float 50 * 0.0567584 +gmp_float 50 / 0.289062 +gmp_float 50 str 0.00354863 +gmp_float 50 +(int)0.0129337 +gmp_float 50 -(int)0.0256267 +gmp_float 50 *(int)0.0197258 +gmp_float 50 /(int)0.087785 +gmp_float 100 + 0.0196977 +gmp_float 100 - 0.024745 +gmp_float 100 * 0.0972 +gmp_float 100 / 0.393792 +gmp_float 100 str 0.00528245 +gmp_float 100 +(int)0.0154802 +gmp_float 100 -(int)0.0242376 +gmp_float 100 *(int)0.0251239 +gmp_float 100 /(int)0.100588 +gmp_float 500 + 0.034133 +gmp_float 500 - 0.0411447 +gmp_float 500 * 0.938779 +gmp_float 500 / 1.5973 +gmp_float 500 str 0.0406575 +gmp_float 500 +(int)0.0220839 +gmp_float 500 -(int)0.0310849 +gmp_float 500 *(int)0.046899 +gmp_float 500 /(int)0.240511 +gmp_int 128 + 0.0236625 +gmp_int 128 - 0.0255431 +gmp_int 128 * 0.0164612 +gmp_int 128 / 0.20205 +gmp_int 128 str 0.000397397 +gmp_int 128 +(int)0.00907029 +gmp_int 128 -(int)0.0120936 +gmp_int 128 *(int)0.0139764 +gmp_int 128 /(int)0.061181 +gmp_int 128 % 0.167724 +gmp_int 128 | 0.0126627 +gmp_int 128 & 0.0129377 +gmp_int 128 ^ 0.0136018 +gmp_int 128 << 0.0109566 +gmp_int 128 >> 0.0107283 +gmp_int 128 %(int)0.0408971 +gmp_int 128 |(int)0.0463637 +gmp_int 128 &(int)0.0502028 +gmp_int 128 ^(int)0.047593 +gmp_int 128 gcd 0.452707 +gmp_int 256 + 0.0257277 +gmp_int 256 - 0.0314085 +gmp_int 256 * 0.0495293 +gmp_int 256 / 0.242695 +gmp_int 256 str 0.000617745 +gmp_int 256 +(int)0.0129046 +gmp_int 256 -(int)0.0163165 +gmp_int 256 *(int)0.0153128 +gmp_int 256 /(int)0.0730963 +gmp_int 256 % 0.203102 +gmp_int 256 | 0.0149383 +gmp_int 256 & 0.0170717 +gmp_int 256 ^ 0.0160796 +gmp_int 256 << 0.0146023 +gmp_int 256 >> 0.010293 +gmp_int 256 %(int)0.0525884 +gmp_int 256 |(int)0.0501017 +gmp_int 256 &(int)0.0508389 +gmp_int 256 ^(int)0.0498771 +gmp_int 256 gcd 2.17179 +gmp_int 512 + 0.0283556 +gmp_int 512 - 0.0398509 +gmp_int 512 * 0.104633 +gmp_int 512 / 0.294206 +gmp_int 512 str 0.00125749 +gmp_int 512 +(int)0.0156938 +gmp_int 512 -(int)0.0204795 +gmp_int 512 *(int)0.0190714 +gmp_int 512 /(int)0.09638 +gmp_int 512 % 0.23687 +gmp_int 512 | 0.0244134 +gmp_int 512 & 0.0209509 +gmp_int 512 ^ 0.0266707 +gmp_int 512 << 0.0178981 +gmp_int 512 >> 0.0122496 +gmp_int 512 %(int)0.0655264 +gmp_int 512 |(int)0.0536497 +gmp_int 512 &(int)0.0532932 +gmp_int 512 ^(int)0.0540655 +gmp_int 512 gcd 4.86569 +gmp_int 1024 + 0.0417292 +gmp_int 1024 - 0.0504965 +gmp_int 1024 * 0.330741 +gmp_int 1024 / 0.376529 +gmp_int 1024 str 0.00295526 +gmp_int 1024 +(int)0.0258726 +gmp_int 1024 -(int)0.0235972 +gmp_int 1024 *(int)0.0326542 +gmp_int 1024 /(int)0.148103 +gmp_int 1024 % 0.301177 +gmp_int 1024 | 0.0262977 +gmp_int 1024 & 0.0235786 +gmp_int 1024 ^ 0.0254182 +gmp_int 1024 << 0.0206225 +gmp_int 1024 >> 0.012848 +gmp_int 1024 %(int)0.0765616 +gmp_int 1024 |(int)0.0495613 +gmp_int 1024 &(int)0.0512979 +gmp_int 1024 ^(int)0.0491785 +gmp_int 1024 gcd 10.2899 +cpp_int 128 + 0.0226262 +cpp_int 128 - 0.0256171 +cpp_int 128 * 0.0363846 +cpp_int 128 / 0.227187 +cpp_int 128 str 0.000703371 +cpp_int 128 +(int)0.0156956 +cpp_int 128 -(int)0.0122229 +cpp_int 128 *(int)0.0257193 +cpp_int 128 /(int)0.129609 +cpp_int 128 % 0.226534 +cpp_int 128 | 0.0242976 +cpp_int 128 & 0.0244482 +cpp_int 128 ^ 0.0243197 +cpp_int 128 << 0.0182175 +cpp_int 128 >> 0.0215535 +cpp_int 128 %(int)0.181554 +cpp_int 128 |(int)0.0454215 +cpp_int 128 &(int)0.0426893 +cpp_int 128 ^(int)0.0404509 +cpp_int 128 gcd 4.16823 +cpp_int 256 + 0.0275581 +cpp_int 256 - 0.0305114 +cpp_int 256 * 0.100083 +cpp_int 256 / 0.467116 +cpp_int 256 str 0.00181769 +cpp_int 256 +(int)0.017033 +cpp_int 256 -(int)0.0143035 +cpp_int 256 *(int)0.0294836 +cpp_int 256 /(int)0.303922 +cpp_int 256 % 0.435207 +cpp_int 256 | 0.0281237 +cpp_int 256 & 0.028049 +cpp_int 256 ^ 0.0280192 +cpp_int 256 << 0.0210768 +cpp_int 256 >> 0.0175781 +cpp_int 256 %(int)0.279274 +cpp_int 256 |(int)0.0323883 +cpp_int 256 &(int)0.0338674 +cpp_int 256 ^(int)0.0299941 +cpp_int 256 gcd 8.51244 +cpp_int 512 + 0.033691 +cpp_int 512 - 0.0422701 +cpp_int 512 * 0.343683 +cpp_int 512 / 0.755608 +cpp_int 512 str 0.00434022 +cpp_int 512 +(int)0.0196755 +cpp_int 512 -(int)0.0171212 +cpp_int 512 *(int)0.039305 +cpp_int 512 /(int)0.535727 +cpp_int 512 % 0.719958 +cpp_int 512 | 0.0339623 +cpp_int 512 & 0.0342017 +cpp_int 512 ^ 0.033929 +cpp_int 512 << 0.0269161 +cpp_int 512 >> 0.0216914 +cpp_int 512 %(int)0.53345 +cpp_int 512 |(int)0.0324562 +cpp_int 512 &(int)0.0424884 +cpp_int 512 ^(int)0.0323887 +cpp_int 512 gcd 19.489 +cpp_int 1024 + 0.0456764 +cpp_int 1024 - 0.0574919 +cpp_int 1024 * 1.28548 +cpp_int 1024 / 1.30086 +cpp_int 1024 str 0.0122363 +cpp_int 1024 +(int)0.0241476 +cpp_int 1024 -(int)0.0212992 +cpp_int 1024 *(int)0.0540818 +cpp_int 1024 /(int)1.00179 +cpp_int 1024 % 1.27181 +cpp_int 1024 | 0.0457886 +cpp_int 1024 & 0.0456006 +cpp_int 1024 ^ 0.0456494 +cpp_int 1024 << 0.0394128 +cpp_int 1024 >> 0.0294462 +cpp_int 1024 %(int)0.962651 +cpp_int 1024 |(int)0.0372077 +cpp_int 1024 &(int)0.0577198 +cpp_int 1024 ^(int)0.0372218 +cpp_int 1024 gcd 47.7651 +cpp_int(fixed) 128 + 0.0183948 +cpp_int(fixed) 128 - 0.0182905 +cpp_int(fixed) 128 * 0.0201727 +cpp_int(fixed) 128 / 0.206852 +cpp_int(fixed) 128 str 0.000630107 +cpp_int(fixed) 128 +(int)0.00967714 +cpp_int(fixed) 128 -(int)0.00810627 +cpp_int(fixed) 128 *(int)0.0183201 +cpp_int(fixed) 128 /(int)0.111309 +cpp_int(fixed) 128 % 0.204164 +cpp_int(fixed) 128 | 0.0136789 +cpp_int(fixed) 128 & 0.0143848 +cpp_int(fixed) 128 ^ 0.0137773 +cpp_int(fixed) 128 << 0.0131154 +cpp_int(fixed) 128 >> 0.00912176 +cpp_int(fixed) 128 %(int)0.115583 +cpp_int(fixed) 128 |(int)0.0164462 +cpp_int(fixed) 128 &(int)0.0169816 +cpp_int(fixed) 128 ^(int)0.014607 +cpp_int(fixed) 128 gcd 2.87326 +cpp_int(fixed) 256 + 0.0217614 +cpp_int(fixed) 256 - 0.0208437 +cpp_int(fixed) 256 * 0.0385279 +cpp_int(fixed) 256 / 0.321272 +cpp_int(fixed) 256 str 0.00149991 +cpp_int(fixed) 256 +(int)0.0102395 +cpp_int(fixed) 256 -(int)0.00923316 +cpp_int(fixed) 256 *(int)0.021549 +cpp_int(fixed) 256 /(int)0.219146 +cpp_int(fixed) 256 % 0.321039 +cpp_int(fixed) 256 | 0.0154596 +cpp_int(fixed) 256 & 0.0156443 +cpp_int(fixed) 256 ^ 0.015493 +cpp_int(fixed) 256 << 0.0169546 +cpp_int(fixed) 256 >> 0.0114138 +cpp_int(fixed) 256 %(int)0.238857 +cpp_int(fixed) 256 |(int)0.015725 +cpp_int(fixed) 256 &(int)0.021641 +cpp_int(fixed) 256 ^(int)0.0163443 +cpp_int(fixed) 256 gcd 6.68597 +cpp_int(fixed) 512 + 0.0284799 +cpp_int(fixed) 512 - 0.028304 +cpp_int(fixed) 512 * 0.119904 +cpp_int(fixed) 512 / 0.616699 +cpp_int(fixed) 512 str 0.00415653 +cpp_int(fixed) 512 +(int)0.0122821 +cpp_int(fixed) 512 -(int)0.0110103 +cpp_int(fixed) 512 *(int)0.0283635 +cpp_int(fixed) 512 /(int)0.451373 +cpp_int(fixed) 512 % 0.620217 +cpp_int(fixed) 512 | 0.0189862 +cpp_int(fixed) 512 & 0.0192657 +cpp_int(fixed) 512 ^ 0.018973 +cpp_int(fixed) 512 << 0.0188263 +cpp_int(fixed) 512 >> 0.0152103 +cpp_int(fixed) 512 %(int)0.491398 +cpp_int(fixed) 512 |(int)0.0182191 +cpp_int(fixed) 512 &(int)0.0277722 +cpp_int(fixed) 512 ^(int)0.0182565 +cpp_int(fixed) 512 gcd 16.1788 +cpp_int(fixed) 1024 + 0.0396571 +cpp_int(fixed) 1024 - 0.0413187 +cpp_int(fixed) 1024 * 0.371065 +cpp_int(fixed) 1024 / 1.09072 +cpp_int(fixed) 1024 str 0.011546 +cpp_int(fixed) 1024 +(int)0.0254102 +cpp_int(fixed) 1024 -(int)0.020939 +cpp_int(fixed) 1024 *(int)0.0494233 +cpp_int(fixed) 1024 /(int)0.870306 +cpp_int(fixed) 1024 % 1.09888 +cpp_int(fixed) 1024 | 0.0393824 +cpp_int(fixed) 1024 & 0.0397966 +cpp_int(fixed) 1024 ^ 0.0394082 +cpp_int(fixed) 1024 << 0.0392477 +cpp_int(fixed) 1024 >> 0.0214742 +cpp_int(fixed) 1024 %(int)0.941513 +cpp_int(fixed) 1024 |(int)0.0304613 +cpp_int(fixed) 1024 &(int)0.0497983 +cpp_int(fixed) 1024 ^(int)0.0333848 +cpp_int(fixed) 1024 gcd 41.9178 +cpp_rational 128 + 8.33358 +cpp_rational 128 - 8.3543 +cpp_rational 128 * 15.3196 +cpp_rational 128 / 31.794 +cpp_rational 128 str 0.00980984 +cpp_rational 128 +(int)1.14042 +cpp_rational 128 -(int)1.13947 +cpp_rational 128 *(int)1.3425 +cpp_rational 128 /(int)1.35276 +cpp_rational 256 + 24.5753 +cpp_rational 256 - 24.3831 +cpp_rational 256 * 45.9283 +cpp_rational 256 / 80.7871 +cpp_rational 256 str 0.0288878 +cpp_rational 256 +(int)1.54697 +cpp_rational 256 -(int)1.55711 +cpp_rational 256 *(int)2.05921 +cpp_rational 256 /(int)2.12933 +cpp_rational 512 + 58.1983 +cpp_rational 512 - 58.3044 +cpp_rational 512 * 111.528 +cpp_rational 512 / 184.73 +cpp_rational 512 str 0.067039 +cpp_rational 512 +(int)1.83113 +cpp_rational 512 -(int)1.82889 +cpp_rational 512 *(int)2.75206 +cpp_rational 512 /(int)2.75885 +cpp_rational 1024 + 139.884 +cpp_rational 1024 - 139.665 +cpp_rational 1024 * 270.253 +cpp_rational 1024 / 436.471 +cpp_rational 1024 str 0.165057 +cpp_rational 1024 +(int)2.65768 +cpp_rational 1024 -(int)2.68279 +cpp_rational 1024 *(int)4.26866 +cpp_rational 1024 /(int)4.27228 +mpq_rational 128 + 0.518878 +mpq_rational 128 - 0.520249 +mpq_rational 128 * 0.940549 +mpq_rational 128 / 2.63335 +mpq_rational 128 str 0.000732008 +mpq_rational 128 +(int)0.145745 +mpq_rational 128 -(int)0.142505 +mpq_rational 128 *(int)0.173305 +mpq_rational 128 /(int)0.178914 +mpq_rational 256 + 2.2747 +mpq_rational 256 - 2.27886 +mpq_rational 256 * 4.27402 +mpq_rational 256 / 8.07149 +mpq_rational 256 str 0.00123256 +mpq_rational 256 +(int)0.164417 +mpq_rational 256 -(int)0.161741 +mpq_rational 256 *(int)0.193095 +mpq_rational 256 /(int)0.202255 +mpq_rational 512 + 5.09463 +mpq_rational 512 - 5.09757 +mpq_rational 512 * 9.6481 +mpq_rational 512 / 16.9064 +mpq_rational 512 str 0.00244388 +mpq_rational 512 +(int)0.202901 +mpq_rational 512 -(int)0.200644 +mpq_rational 512 *(int)0.248942 +mpq_rational 512 /(int)0.251928 +mpq_rational 1024 + 11.2492 +mpq_rational 1024 - 11.2528 +mpq_rational 1024 * 21.0227 +mpq_rational 1024 / 35.7647 +mpq_rational 1024 str 0.00559869 +mpq_rational 1024 +(int)0.287349 +mpq_rational 1024 -(int)0.28136 +mpq_rational 1024 *(int)0.337805 +mpq_rational 1024 /(int)0.351164 +tommath_int 128 + 0.0169999 +tommath_int 128 - 0.025088 +tommath_int 128 * 0.0608098 +tommath_int 128 / 1.14807 +tommath_int 128 str 0.00864677 +tommath_int 128 +(int)0.170239 +tommath_int 128 -(int)0.169805 +tommath_int 128 *(int)0.18998 +tommath_int 128 /(int)0.936106 +tommath_int 128 % 1.10993 +tommath_int 128 | 0.0742258 +tommath_int 128 & 0.0747022 +tommath_int 128 ^ 0.0734074 +tommath_int 128 << 0.0316344 +tommath_int 128 >> 0.139155 +tommath_int 128 %(int)0.871093 +tommath_int 128 |(int)0.249135 +tommath_int 128 &(int)0.224394 +tommath_int 128 ^(int)0.248407 +tommath_int 128 gcd 7.6073 +tommath_int 256 + 0.0191462 +tommath_int 256 - 0.0267191 +tommath_int 256 * 0.0843842 +tommath_int 256 / 1.34052 +tommath_int 256 str 0.0212684 +tommath_int 256 +(int)0.173633 +tommath_int 256 -(int)0.173084 +tommath_int 256 *(int)0.20074 +tommath_int 256 /(int)1.17192 +tommath_int 256 % 1.33781 +tommath_int 256 | 0.0740269 +tommath_int 256 & 0.0747001 +tommath_int 256 ^ 0.0741847 +tommath_int 256 << 0.0379471 +tommath_int 256 >> 0.14164 +tommath_int 256 %(int)1.52193 +tommath_int 256 |(int)0.251418 +tommath_int 256 &(int)0.230435 +tommath_int 256 ^(int)0.249516 +tommath_int 256 gcd 15.8851 +tommath_int 512 + 0.0241933 +tommath_int 512 - 0.032154 +tommath_int 512 * 0.195855 +tommath_int 512 / 2.061 +tommath_int 512 str 0.0827649 +tommath_int 512 +(int)0.25223 +tommath_int 512 -(int)0.25482 +tommath_int 512 *(int)0.305608 +tommath_int 512 /(int)1.76155 +tommath_int 512 % 1.97453 +tommath_int 512 | 0.0795209 +tommath_int 512 & 0.0815029 +tommath_int 512 ^ 0.0793004 +tommath_int 512 << 0.0449753 +tommath_int 512 >> 0.149597 +tommath_int 512 %(int)1.74258 +tommath_int 512 |(int)0.253519 +tommath_int 512 &(int)0.235246 +tommath_int 512 ^(int)0.261762 +tommath_int 512 gcd 33.8904 +tommath_int 1024 + 0.0356467 +tommath_int 1024 - 0.0426379 +tommath_int 1024 * 0.563154 +tommath_int 1024 / 3.3106 +tommath_int 1024 str 0.200351 +tommath_int 1024 +(int)0.183982 +tommath_int 1024 -(int)0.182348 +tommath_int 1024 *(int)0.265242 +tommath_int 1024 /(int)2.99248 +tommath_int 1024 % 3.36442 +tommath_int 1024 | 0.0935681 +tommath_int 1024 & 0.0990244 +tommath_int 1024 ^ 0.0948247 +tommath_int 1024 << 0.0671463 +tommath_int 1024 >> 0.167341 +tommath_int 1024 %(int)2.8911 +tommath_int 1024 |(int)0.26358 +tommath_int 1024 &(int)0.244976 +tommath_int 1024 ^(int)0.261357 +tommath_int 1024 gcd 67.1657 +cpp_dec_float 50 + 0.0139248 +cpp_dec_float 50 - 0.0142418 +cpp_dec_float 50 * 0.118247 +cpp_dec_float 50 / 1.82747 +cpp_dec_float 50 str 0.00932849 +cpp_dec_float 50 +(int)0.0253923 +cpp_dec_float 50 -(int)0.0248418 +cpp_dec_float 50 *(int)0.0371704 +cpp_dec_float 50 /(int)0.199883 +cpp_dec_float 100 + 0.0171021 +cpp_dec_float 100 - 0.0176287 +cpp_dec_float 100 * 0.237033 +cpp_dec_float 100 / 3.63766 +cpp_dec_float 100 str 0.0201057 +cpp_dec_float 100 +(int)0.0330663 +cpp_dec_float 100 -(int)0.0332922 +cpp_dec_float 100 *(int)0.0606472 +cpp_dec_float 100 /(int)0.343778 +cpp_dec_float 500 + 0.043194 +cpp_dec_float 500 - 0.0443422 +cpp_dec_float 500 * 2.12299 +cpp_dec_float 500 / 25.7245 +cpp_dec_float 500 str 0.0655127 +cpp_dec_float 500 +(int)0.0706977 +cpp_dec_float 500 -(int)0.0727089 +cpp_dec_float 500 *(int)0.239796 +cpp_dec_float 500 /(int)1.39609 +mpfr_float 50 + 0.019179 +mpfr_float 50 - 0.0225632 +mpfr_float 50 * 0.0588765 +mpfr_float 50 / 0.317276 +mpfr_float 50 str 0.00725414 +mpfr_float 50 +(int)0.0286079 +mpfr_float 50 -(int)0.0465151 +mpfr_float 50 *(int)0.0362579 +mpfr_float 50 /(int)0.0888645 +mpfr_float 100 + 0.0210236 +mpfr_float 100 - 0.0250703 +mpfr_float 100 * 0.0946262 +mpfr_float 100 / 0.456375 +mpfr_float 100 str 0.00900848 +mpfr_float 100 +(int)0.0320443 +mpfr_float 100 -(int)0.0487733 +mpfr_float 100 *(int)0.0437034 +mpfr_float 100 /(int)0.154203 +mpfr_float 500 + 0.033691 +mpfr_float 500 - 0.0371954 +mpfr_float 500 * 0.851721 +mpfr_float 500 / 2.7946 +mpfr_float 500 str 0.0342011 +mpfr_float 500 +(int)0.0414774 +mpfr_float 500 -(int)0.0616173 +mpfr_float 500 *(int)0.0826485 +mpfr_float 500 /(int)0.254227 +[section:float_performance Float Type Perfomance] +[table Operator * +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.08334 (0.118247s)][2.50494 (0.237033s)][2.49259 (2.12299s)]] +[[gmp_float][[*1] (0.0567584s)][1.0272 (0.0972s)][1.10221 (0.938779s)]] +[[mpfr_float][1.03732 (0.0588765s)][[*1] (0.0946262s)][[*1] (0.851721s)]] +] +[table Operator *(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.88436 (0.0371704s)][2.41392 (0.0606472s)][5.11303 (0.239796s)]] +[[gmp_float][[*1] (0.0197258s)][[*1] (0.0251239s)][[*1] (0.046899s)]] +[[mpfr_float][1.8381 (0.0362579s)][1.73951 (0.0437034s)][1.76227 (0.0826485s)]] +] +[table Operator + +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0139248s)][[*1] (0.0171021s)][1.28206 (0.043194s)]] +[[gmp_float][1.29901 (0.0180885s)][1.15177 (0.0196977s)][1.01312 (0.034133s)]] +[[mpfr_float][1.37732 (0.019179s)][1.2293 (0.0210236s)][[*1] (0.033691s)]] +] +[table Operator +(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.96327 (0.0253923s)][2.13604 (0.0330663s)][3.20133 (0.0706977s)]] +[[gmp_float][[*1] (0.0129337s)][[*1] (0.0154802s)][[*1] (0.0220839s)]] +[[mpfr_float][2.21189 (0.0286079s)][2.07002 (0.0320443s)][1.87818 (0.0414774s)]] +] +[table Operator - +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0142418s)][[*1] (0.0176287s)][1.19214 (0.0443422s)]] +[[gmp_float][1.5989 (0.0227712s)][1.40368 (0.024745s)][1.10618 (0.0411447s)]] +[[mpfr_float][1.5843 (0.0225632s)][1.42213 (0.0250703s)][[*1] (0.0371954s)]] +] +[table Operator -(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0248418s)][1.37357 (0.0332922s)][2.33904 (0.0727089s)]] +[[gmp_float][1.03159 (0.0256267s)][[*1] (0.0242376s)][[*1] (0.0310849s)]] +[[mpfr_float][1.87245 (0.0465151s)][2.0123 (0.0487733s)][1.98223 (0.0616173s)]] +] +[table Operator / +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][6.32206 (1.82747s)][9.23752 (3.63766s)][16.1049 (25.7245s)]] +[[gmp_float][[*1] (0.289062s)][[*1] (0.393792s)][[*1] (1.5973s)]] +[[mpfr_float][1.09761 (0.317276s)][1.15892 (0.456375s)][1.74957 (2.7946s)]] +] +[table Operator /(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.27696 (0.199883s)][3.41769 (0.343778s)][5.8047 (1.39609s)]] +[[gmp_float][[*1] (0.087785s)][[*1] (0.100588s)][[*1] (0.240511s)]] +[[mpfr_float][1.0123 (0.0888645s)][1.53302 (0.154203s)][1.05703 (0.254227s)]] +] +[table Operator str +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.62876 (0.00932849s)][3.80613 (0.0201057s)][1.91552 (0.0655127s)]] +[[gmp_float][[*1] (0.00354863s)][[*1] (0.00528245s)][1.18878 (0.0406575s)]] +[[mpfr_float][2.04421 (0.00725414s)][1.70536 (0.00900848s)][[*1] (0.0342011s)]] +] +[endsect] +[section:integer_performance Integer Type Perfomance] +[table Operator % +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.35064 (0.226534s)][2.1428 (0.435207s)][3.03946 (0.719958s)][4.22281 (1.27181s)]] +[[cpp_int(fixed)][1.21726 (0.204164s)][1.58068 (0.321039s)][2.61838 (0.620217s)][3.6486 (1.09888s)]] +[[gmp_int][[*1] (0.167724s)][[*1] (0.203102s)][[*1] (0.23687s)][[*1] (0.301177s)]] +[[tommath_int][6.61759 (1.10993s)][6.58689 (1.33781s)][8.33593 (1.97453s)][11.1709 (3.36442s)]] +] +[table Operator %(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][4.43928 (0.181554s)][5.31056 (0.279274s)][8.141 (0.53345s)][12.5735 (0.962651s)]] +[[cpp_int(fixed)][2.82619 (0.115583s)][4.54202 (0.238857s)][7.49924 (0.491398s)][12.2974 (0.941513s)]] +[[gmp_int][[*1] (0.0408971s)][[*1] (0.0525884s)][[*1] (0.0655264s)][[*1] (0.0765616s)]] +[[tommath_int][21.2996 (0.871093s)][28.9405 (1.52193s)][26.5936 (1.74258s)][37.7618 (2.8911s)]] +] +[table Operator & +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.88968 (0.0244482s)][1.79292 (0.028049s)][1.77526 (0.0342017s)][1.93398 (0.0456006s)]] +[[cpp_int(fixed)][1.11185 (0.0143848s)][[*1] (0.0156443s)][[*1] (0.0192657s)][1.68783 (0.0397966s)]] +[[gmp_int][[*1] (0.0129377s)][1.09124 (0.0170717s)][1.08747 (0.0209509s)][[*1] (0.0235786s)]] +[[tommath_int][5.77397 (0.0747022s)][4.7749 (0.0747001s)][4.23046 (0.0815029s)][4.19976 (0.0990244s)]] +] +[table Operator &(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.51385 (0.0426893s)][1.56497 (0.0338674s)][1.52989 (0.0424884s)][1.15907 (0.0577198s)]] +[[cpp_int(fixed)][[*1] (0.0169816s)][[*1] (0.021641s)][[*1] (0.0277722s)][[*1] (0.0497983s)]] +[[gmp_int][2.9563 (0.0502028s)][2.3492 (0.0508389s)][1.91894 (0.0532932s)][1.03011 (0.0512979s)]] +[[tommath_int][13.2139 (0.224394s)][10.6481 (0.230435s)][8.47057 (0.235246s)][4.91936 (0.244976s)]] +] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.21032 (0.0363846s)][2.59769 (0.100083s)][3.28466 (0.343683s)][3.88666 (1.28548s)]] +[[cpp_int(fixed)][1.22547 (0.0201727s)][[*1] (0.0385279s)][1.14595 (0.119904s)][1.12192 (0.371065s)]] +[[gmp_int][[*1] (0.0164612s)][1.28554 (0.0495293s)][[*1] (0.104633s)][[*1] (0.330741s)]] +[[tommath_int][3.69412 (0.0608098s)][2.19021 (0.0843842s)][1.87184 (0.195855s)][1.70271 (0.563154s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.8402 (0.0257193s)][1.92542 (0.0294836s)][2.06094 (0.039305s)][1.6562 (0.0540818s)]] +[[cpp_int(fixed)][1.3108 (0.0183201s)][1.40725 (0.021549s)][1.48723 (0.0283635s)][1.51354 (0.0494233s)]] +[[gmp_int][[*1] (0.0139764s)][[*1] (0.0153128s)][[*1] (0.0190714s)][[*1] (0.0326542s)]] +[[tommath_int][13.593 (0.18998s)][13.1093 (0.20074s)][16.0244 (0.305608s)][8.12274 (0.265242s)]] +] +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.33096 (0.0226262s)][1.43935 (0.0275581s)][1.39258 (0.033691s)][1.28136 (0.0456764s)]] +[[cpp_int(fixed)][1.08205 (0.0183948s)][1.13659 (0.0217614s)][1.17718 (0.0284799s)][1.1125 (0.0396571s)]] +[[gmp_int][1.39192 (0.0236625s)][1.34375 (0.0257277s)][1.17204 (0.0283556s)][1.17063 (0.0417292s)]] +[[tommath_int][[*1] (0.0169999s)][[*1] (0.0191462s)][[*1] (0.0241933s)][[*1] (0.0356467s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.73044 (0.0156956s)][1.66346 (0.017033s)][1.60196 (0.0196755s)][[*1] (0.0241476s)]] +[[cpp_int(fixed)][1.06691 (0.00967714s)][[*1] (0.0102395s)][[*1] (0.0122821s)][1.05229 (0.0254102s)]] +[[gmp_int][[*1] (0.00907029s)][1.26028 (0.0129046s)][1.27777 (0.0156938s)][1.07144 (0.0258726s)]] +[[tommath_int][18.7688 (0.170239s)][16.9572 (0.173633s)][20.5363 (0.25223s)][7.61905 (0.183982s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.40057 (0.0256171s)][1.46382 (0.0305114s)][1.49343 (0.0422701s)][1.39142 (0.0574919s)]] +[[cpp_int(fixed)][[*1] (0.0182905s)][[*1] (0.0208437s)][[*1] (0.028304s)][[*1] (0.0413187s)]] +[[gmp_int][1.39653 (0.0255431s)][1.50686 (0.0314085s)][1.40796 (0.0398509s)][1.22212 (0.0504965s)]] +[[tommath_int][1.37164 (0.025088s)][1.28188 (0.0267191s)][1.13602 (0.032154s)][1.03193 (0.0426379s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.50784 (0.0122229s)][1.54914 (0.0143035s)][1.55501 (0.0171212s)][1.0172 (0.0212992s)]] +[[cpp_int(fixed)][[*1] (0.00810627s)][[*1] (0.00923316s)][[*1] (0.0110103s)][[*1] (0.020939s)]] +[[gmp_int][1.49189 (0.0120936s)][1.76716 (0.0163165s)][1.86002 (0.0204795s)][1.12695 (0.0235972s)]] +[[tommath_int][20.9474 (0.169805s)][18.7459 (0.173084s)][23.1437 (0.25482s)][8.70855 (0.182348s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.12441 (0.227187s)][1.92471 (0.467116s)][2.5683 (0.755608s)][3.45487 (1.30086s)]] +[[cpp_int(fixed)][1.02377 (0.206852s)][1.32377 (0.321272s)][2.09615 (0.616699s)][2.89679 (1.09072s)]] +[[gmp_int][[*1] (0.20205s)][[*1] (0.242695s)][[*1] (0.294206s)][[*1] (0.376529s)]] +[[tommath_int][5.68214 (1.14807s)][5.52349 (1.34052s)][7.00529 (2.061s)][8.79242 (3.3106s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.11845 (0.129609s)][4.15783 (0.303922s)][5.55849 (0.535727s)][6.76415 (1.00179s)]] +[[cpp_int(fixed)][1.81934 (0.111309s)][2.99804 (0.219146s)][4.68327 (0.451373s)][5.87635 (0.870306s)]] +[[gmp_int][[*1] (0.061181s)][[*1] (0.0730963s)][[*1] (0.09638s)][[*1] (0.148103s)]] +[[tommath_int][15.3006 (0.936106s)][16.0325 (1.17192s)][18.2771 (1.76155s)][20.2054 (2.99248s)]] +] +[table Operator << +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.66271 (0.0182175s)][1.44338 (0.0210768s)][1.50386 (0.0269161s)][1.91115 (0.0394128s)]] +[[cpp_int(fixed)][1.19703 (0.0131154s)][1.16109 (0.0169546s)][1.05186 (0.0188263s)][1.90315 (0.0392477s)]] +[[gmp_int][[*1] (0.0109566s)][[*1] (0.0146023s)][[*1] (0.0178981s)][[*1] (0.0206225s)]] +[[tommath_int][2.88726 (0.0316344s)][2.5987 (0.0379471s)][2.51285 (0.0449753s)][3.25597 (0.0671463s)]] +] +[table Operator >> +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.36287 (0.0215535s)][1.70778 (0.0175781s)][1.77078 (0.0216914s)][2.29189 (0.0294462s)]] +[[cpp_int(fixed)][[*1] (0.00912176s)][1.10889 (0.0114138s)][1.2417 (0.0152103s)][1.6714 (0.0214742s)]] +[[gmp_int][1.17612 (0.0107283s)][[*1] (0.010293s)][[*1] (0.0122496s)][[*1] (0.012848s)]] +[[tommath_int][15.2553 (0.139155s)][13.7608 (0.14164s)][12.2124 (0.149597s)][13.0247 (0.167341s)]] +] +[table Operator ^ +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.78798 (0.0243197s)][1.8085 (0.0280192s)][1.78828 (0.033929s)][1.79594 (0.0456494s)]] +[[cpp_int(fixed)][1.0129 (0.0137773s)][[*1] (0.015493s)][[*1] (0.018973s)][1.5504 (0.0394082s)]] +[[gmp_int][[*1] (0.0136018s)][1.03786 (0.0160796s)][1.40572 (0.0266707s)][[*1] (0.0254182s)]] +[[tommath_int][5.39689 (0.0734074s)][4.78827 (0.0741847s)][4.17964 (0.0793004s)][3.73059 (0.0948247s)]] +] +[table Operator ^(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.76928 (0.0404509s)][1.83515 (0.0299941s)][1.77409 (0.0323887s)][1.11493 (0.0372218s)]] +[[cpp_int(fixed)][[*1] (0.014607s)][[*1] (0.0163443s)][[*1] (0.0182565s)][[*1] (0.0333848s)]] +[[gmp_int][3.25823 (0.047593s)][3.05166 (0.0498771s)][2.96144 (0.0540655s)][1.47308 (0.0491785s)]] +[[tommath_int][17.006 (0.248407s)][15.2663 (0.249516s)][14.338 (0.261762s)][7.82864 (0.261357s)]] +] +[table Operator gcd +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.20736 (4.16823s)][3.91955 (8.51244s)][4.00539 (19.489s)][4.64192 (47.7651s)]] +[[cpp_int(fixed)][6.34685 (2.87326s)][3.07855 (6.68597s)][3.32507 (16.1788s)][4.07366 (41.9178s)]] +[[gmp_int][[*1] (0.452707s)][[*1] (2.17179s)][[*1] (4.86569s)][[*1] (10.2899s)]] +[[tommath_int][16.804 (7.6073s)][7.31428 (15.8851s)][6.96518 (33.8904s)][6.52732 (67.1657s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.76995 (0.000703371s)][2.94246 (0.00181769s)][3.45149 (0.00434022s)][4.14052 (0.0122363s)]] +[[cpp_int(fixed)][1.58559 (0.000630107s)][2.42804 (0.00149991s)][3.30542 (0.00415653s)][3.90693 (0.011546s)]] +[[gmp_int][[*1] (0.000397397s)][[*1] (0.000617745s)][[*1] (0.00125749s)][[*1] (0.00295526s)]] +[[tommath_int][21.7585 (0.00864677s)][34.4291 (0.0212684s)][65.8175 (0.0827649s)][67.7946 (0.200351s)]] +] +[table Operator | +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.91883 (0.0242976s)][1.88265 (0.0281237s)][1.78879 (0.0339623s)][1.74117 (0.0457886s)]] +[[cpp_int(fixed)][1.08025 (0.0136789s)][1.03489 (0.0154596s)][[*1] (0.0189862s)][1.49756 (0.0393824s)]] +[[gmp_int][[*1] (0.0126627s)][[*1] (0.0149383s)][1.28585 (0.0244134s)][[*1] (0.0262977s)]] +[[tommath_int][5.86177 (0.0742258s)][4.9555 (0.0740269s)][4.18835 (0.0795209s)][3.55804 (0.0935681s)]] +] +[table Operator |(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.76183 (0.0454215s)][2.05967 (0.0323883s)][1.78143 (0.0324562s)][1.22147 (0.0372077s)]] +[[cpp_int(fixed)][[*1] (0.0164462s)][[*1] (0.015725s)][[*1] (0.0182191s)][[*1] (0.0304613s)]] +[[gmp_int][2.81912 (0.0463637s)][3.18611 (0.0501017s)][2.94469 (0.0536497s)][1.62702 (0.0495613s)]] +[[tommath_int][15.1485 (0.249135s)][15.9884 (0.251418s)][13.915 (0.253519s)][8.65293 (0.26358s)]] +] +[endsect] +[section:rational_performance Rational Type Perfomance] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][16.2879 (15.3196s)][10.7459 (45.9283s)][11.5596 (111.528s)][12.8553 (270.253s)]] +[[mpq_rational][[*1] (0.940549s)][[*1] (4.27402s)][[*1] (9.6481s)][[*1] (21.0227s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][7.7465 (1.3425s)][10.6643 (2.05921s)][11.055 (2.75206s)][12.6365 (4.26866s)]] +[[mpq_rational][[*1] (0.173305s)][[*1] (0.193095s)][[*1] (0.248942s)][[*1] (0.337805s)]] +] +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][16.0608 (8.33358s)][10.8037 (24.5753s)][11.4235 (58.1983s)][12.435 (139.884s)]] +[[mpq_rational][[*1] (0.518878s)][[*1] (2.2747s)][[*1] (5.09463s)][[*1] (11.2492s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][7.82472 (1.14042s)][9.40883 (1.54697s)][9.02478 (1.83113s)][9.24894 (2.65768s)]] +[[mpq_rational][[*1] (0.145745s)][[*1] (0.164417s)][[*1] (0.202901s)][[*1] (0.287349s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][16.0583 (8.3543s)][10.6997 (24.3831s)][11.4377 (58.3044s)][12.4116 (139.665s)]] +[[mpq_rational][[*1] (0.520249s)][[*1] (2.27886s)][[*1] (5.09757s)][[*1] (11.2528s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][7.99602 (1.13947s)][9.62717 (1.55711s)][9.1151 (1.82889s)][9.53508 (2.68279s)]] +[[mpq_rational][[*1] (0.142505s)][[*1] (0.161741s)][[*1] (0.200644s)][[*1] (0.28136s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][12.0736 (31.794s)][10.0089 (80.7871s)][10.9267 (184.73s)][12.204 (436.471s)]] +[[mpq_rational][[*1] (2.63335s)][[*1] (8.07149s)][[*1] (16.9064s)][[*1] (35.7647s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][7.56092 (1.35276s)][10.5279 (2.12933s)][10.9509 (2.75885s)][12.166 (4.27228s)]] +[[mpq_rational][[*1] (0.178914s)][[*1] (0.202255s)][[*1] (0.251928s)][[*1] (0.351164s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][13.4013 (0.00980984s)][23.4372 (0.0288878s)][27.4314 (0.067039s)][29.4814 (0.165057s)]] +[[mpq_rational][[*1] (0.000732008s)][[*1] (0.00123256s)][[*1] (0.00244388s)][[*1] (0.00559869s)]] +] +[endsect] diff --git a/performance/performance_test-intel-linux.log b/performance/performance_test-intel-linux.log new file mode 100644 index 00000000..e721729e --- /dev/null +++ b/performance/performance_test-intel-linux.log @@ -0,0 +1,422 @@ +gmp_int 64 + 0.016582 +gmp_int 64 - 0.0174517 +gmp_int 64 * 0.0112253 +gmp_int 64 / 0.170951 +gmp_int 64 str 0.000343689 +gmp_int 64 +(int)0.00688382 +gmp_int 64 -(int)0.00734613 +gmp_int 64 *(int)0.00881438 +gmp_int 64 /(int)0.0465651 +gmp_int 64 % 0.164576 +gmp_int 64 | 0.0101555 +gmp_int 64 & 0.00955666 +gmp_int 64 ^ 0.00987346 +gmp_int 64 << 0.0106043 +gmp_int 64 >> 0.0093887 +gmp_int 64 %(int)0.0297463 +gmp_int 64 |(int)0.0403338 +gmp_int 64 &(int)0.0417288 +gmp_int 64 ^(int)0.0405779 +gmp_int 64 gcd 0.173816 +gmp_int 128 + 0.0183088 +gmp_int 128 - 0.0189266 +gmp_int 128 * 0.0161084 +gmp_int 128 / 0.191775 +gmp_int 128 str 0.000374699 +gmp_int 128 +(int)0.00866339 +gmp_int 128 -(int)0.0089443 +gmp_int 128 *(int)0.0114143 +gmp_int 128 /(int)0.0534638 +gmp_int 128 % 0.161212 +gmp_int 128 | 0.0107201 +gmp_int 128 & 0.0113559 +gmp_int 128 ^ 0.0112116 +gmp_int 128 << 0.0103295 +gmp_int 128 >> 0.00813413 +gmp_int 128 %(int)0.03692 +gmp_int 128 |(int)0.0412168 +gmp_int 128 &(int)0.0428359 +gmp_int 128 ^(int)0.0418522 +gmp_int 128 gcd 0.43131 +gmp_int 256 + 0.0224834 +gmp_int 256 - 0.025062 +gmp_int 256 * 0.0417471 +gmp_int 256 / 0.233656 +gmp_int 256 str 0.00059903 +gmp_int 256 +(int)0.0112071 +gmp_int 256 -(int)0.0116302 +gmp_int 256 *(int)0.0137181 +gmp_int 256 /(int)0.0667669 +gmp_int 256 % 0.191884 +gmp_int 256 | 0.0129489 +gmp_int 256 & 0.012778 +gmp_int 256 ^ 0.0134548 +gmp_int 256 << 0.0121471 +gmp_int 256 >> 0.00832878 +gmp_int 256 %(int)0.0474363 +gmp_int 256 |(int)0.0425591 +gmp_int 256 &(int)0.0436742 +gmp_int 256 ^(int)0.0425636 +gmp_int 256 gcd 2.06855 +gmp_int 512 + 0.0277439 +gmp_int 512 - 0.0318874 +gmp_int 512 * 0.0991032 +gmp_int 512 / 0.274993 +gmp_int 512 str 0.00129458 +gmp_int 512 +(int)0.014283 +gmp_int 512 -(int)0.0149874 +gmp_int 512 *(int)0.0180512 +gmp_int 512 /(int)0.0906691 +gmp_int 512 % 0.222477 +gmp_int 512 | 0.0217103 +gmp_int 512 & 0.0165285 +gmp_int 512 ^ 0.0208848 +gmp_int 512 << 0.014839 +gmp_int 512 >> 0.00988994 +gmp_int 512 %(int)0.0605682 +gmp_int 512 |(int)0.0462909 +gmp_int 512 &(int)0.046599 +gmp_int 512 ^(int)0.0456608 +gmp_int 512 gcd 4.68499 +gmp_int 1024 + 0.0397479 +gmp_int 1024 - 0.042232 +gmp_int 1024 * 0.31703 +gmp_int 1024 / 0.345984 +gmp_int 1024 str 0.00271592 +gmp_int 1024 +(int)0.0189969 +gmp_int 1024 -(int)0.0195046 +gmp_int 1024 *(int)0.0260306 +gmp_int 1024 /(int)0.140151 +gmp_int 1024 % 0.286399 +gmp_int 1024 | 0.0261953 +gmp_int 1024 & 0.023083 +gmp_int 1024 ^ 0.0248084 +gmp_int 1024 << 0.0202635 +gmp_int 1024 >> 0.0127909 +gmp_int 1024 %(int)0.0761102 +gmp_int 1024 |(int)0.049175 +gmp_int 1024 &(int)0.0499195 +gmp_int 1024 ^(int)0.0487102 +gmp_int 1024 gcd 10.1127 +cpp_int 64 + 0.0152915 +cpp_int 64 - 0.0191821 +cpp_int 64 * 0.0326218 +cpp_int 64 / 0.0951094 +cpp_int 64 str 0.000428547 +cpp_int 64 +(int)0.0132027 +cpp_int 64 -(int)0.0126144 +cpp_int 64 *(int)0.0151037 +cpp_int 64 /(int)0.0491116 +cpp_int 64 % 0.0951581 +cpp_int 64 | 0.0199629 +cpp_int 64 & 0.0196969 +cpp_int 64 ^ 0.0208608 +cpp_int 64 << 0.0179372 +cpp_int 64 >> 0.0146206 +cpp_int 64 %(int)0.0229261 +cpp_int 64 |(int)0.0185797 +cpp_int 64 &(int)0.0225055 +cpp_int 64 ^(int)0.0191337 +cpp_int 64 gcd 1.50205 +cpp_int 128 + 0.0170788 +cpp_int 128 - 0.0228373 +cpp_int 128 * 0.0375831 +cpp_int 128 / 0.163958 +cpp_int 128 str 0.000744647 +cpp_int 128 +(int)0.0144833 +cpp_int 128 -(int)0.013922 +cpp_int 128 *(int)0.0176402 +cpp_int 128 /(int)0.0972057 +cpp_int 128 % 0.169015 +cpp_int 128 | 0.0229631 +cpp_int 128 & 0.023126 +cpp_int 128 ^ 0.0229278 +cpp_int 128 << 0.0215749 +cpp_int 128 >> 0.0149198 +cpp_int 128 %(int)0.0476063 +cpp_int 128 |(int)0.0194697 +cpp_int 128 &(int)0.0270183 +cpp_int 128 ^(int)0.0194481 +cpp_int 128 gcd 3.36986 +cpp_int 256 + 0.0231877 +cpp_int 256 - 0.0293424 +cpp_int 256 * 0.113247 +cpp_int 256 / 0.336287 +cpp_int 256 str 0.00190436 +cpp_int 256 +(int)0.0161733 +cpp_int 256 -(int)0.0173225 +cpp_int 256 *(int)0.0199426 +cpp_int 256 /(int)0.229286 +cpp_int 256 % 0.306542 +cpp_int 256 | 0.0257191 +cpp_int 256 & 0.0254172 +cpp_int 256 ^ 0.0259082 +cpp_int 256 << 0.0253994 +cpp_int 256 >> 0.0172635 +cpp_int 256 %(int)0.116093 +cpp_int 256 |(int)0.0233559 +cpp_int 256 &(int)0.0367792 +cpp_int 256 ^(int)0.0232914 +cpp_int 256 gcd 7.88882 +cpp_int 512 + 0.0291058 +cpp_int 512 - 0.0380025 +cpp_int 512 * 0.337161 +cpp_int 512 / 0.487075 +cpp_int 512 str 0.00494162 +cpp_int 512 +(int)0.0201989 +cpp_int 512 -(int)0.0200688 +cpp_int 512 *(int)0.0311497 +cpp_int 512 /(int)0.375279 +cpp_int 512 % 0.459737 +cpp_int 512 | 0.0297101 +cpp_int 512 & 0.0297235 +cpp_int 512 ^ 0.0296913 +cpp_int 512 << 0.0328422 +cpp_int 512 >> 0.0234706 +cpp_int 512 %(int)0.194709 +cpp_int 512 |(int)0.0258992 +cpp_int 512 &(int)0.0529542 +cpp_int 512 ^(int)0.0258749 +cpp_int 512 gcd 19.7141 +cpp_int 1024 + 0.0410101 +cpp_int 1024 - 0.0576733 +cpp_int 1024 * 1.19319 +cpp_int 1024 / 0.850798 +cpp_int 1024 str 0.0149378 +cpp_int 1024 +(int)0.0222435 +cpp_int 1024 -(int)0.0219408 +cpp_int 1024 *(int)0.0435058 +cpp_int 1024 /(int)0.6795 +cpp_int 1024 % 0.800961 +cpp_int 1024 | 0.0369613 +cpp_int 1024 & 0.0368423 +cpp_int 1024 ^ 0.0371252 +cpp_int 1024 << 0.0474759 +cpp_int 1024 >> 0.0297527 +cpp_int 1024 %(int)0.360619 +cpp_int 1024 |(int)0.0326194 +cpp_int 1024 &(int)0.0801744 +cpp_int 1024 ^(int)0.0319848 +cpp_int 1024 gcd 53.3224 +fixed_int 64 + 0.00207275 +fixed_int 64 - 0.00214524 +fixed_int 64 * 0.00391097 +fixed_int 64 / 0.0608466 +fixed_int 64 str 0.000292286 +fixed_int 64 +(int)0.00357336 +fixed_int 64 -(int)0.00352796 +fixed_int 64 *(int)0.00292725 +fixed_int 64 /(int)0.0243018 +fixed_int 64 % 0.0603067 +fixed_int 64 | 0.00258063 +fixed_int 64 & 0.00257379 +fixed_int 64 ^ 0.00258525 +fixed_int 64 << 0.00134947 +fixed_int 64 >> 0.00560378 +fixed_int 64 %(int)0.0241499 +fixed_int 64 |(int)0.00201939 +fixed_int 64 &(int)0.00206716 +fixed_int 64 ^(int)0.00201848 +fixed_int 64 gcd 0.82127 +fixed_int 128 + 0.00325349 +fixed_int 128 - 0.00366953 +fixed_int 128 * 0.010445 +fixed_int 128 / 0.113697 +fixed_int 128 str 0.000564877 +fixed_int 128 +(int)0.00377625 +fixed_int 128 -(int)0.00360179 +fixed_int 128 *(int)0.00418426 +fixed_int 128 /(int)0.091141 +fixed_int 128 % 0.113804 +fixed_int 128 | 0.00360961 +fixed_int 128 & 0.00359913 +fixed_int 128 ^ 0.00361317 +fixed_int 128 << 0.0065905 +fixed_int 128 >> 0.00654308 +fixed_int 128 %(int)0.0809135 +fixed_int 128 |(int)0.00237125 +fixed_int 128 &(int)0.00231056 +fixed_int 128 ^(int)0.00190464 +fixed_int 128 gcd 2.05126 +fixed_int 256 + 0.00785776 +fixed_int 256 - 0.00635884 +fixed_int 256 * 0.0323875 +fixed_int 256 / 0.203194 +fixed_int 256 str 0.0013816 +fixed_int 256 +(int)0.00413397 +fixed_int 256 -(int)0.00379699 +fixed_int 256 *(int)0.00852456 +fixed_int 256 /(int)0.183053 +fixed_int 256 % 0.200368 +fixed_int 256 | 0.0105747 +fixed_int 256 & 0.0105856 +fixed_int 256 ^ 0.0105755 +fixed_int 256 << 0.00874545 +fixed_int 256 >> 0.00906624 +fixed_int 256 %(int)0.152826 +fixed_int 256 |(int)0.00261619 +fixed_int 256 &(int)0.00424202 +fixed_int 256 ^(int)0.00263274 +fixed_int 256 gcd 5.42715 +fixed_int 512 + 0.0131311 +fixed_int 512 - 0.0122513 +fixed_int 512 * 0.205979 +fixed_int 512 / 0.383601 +fixed_int 512 str 0.0043558 +fixed_int 512 +(int)0.00639746 +fixed_int 512 -(int)0.00641876 +fixed_int 512 *(int)0.0152369 +fixed_int 512 /(int)0.363289 +fixed_int 512 % 0.38201 +fixed_int 512 | 0.0131075 +fixed_int 512 & 0.0131292 +fixed_int 512 ^ 0.01314 +fixed_int 512 << 0.0130248 +fixed_int 512 >> 0.0131451 +fixed_int 512 %(int)0.304714 +fixed_int 512 |(int)0.00574368 +fixed_int 512 &(int)0.00810836 +fixed_int 512 ^(int)0.00576694 +fixed_int 512 gcd 16.6269 +fixed_int 1024 + 0.0322386 +fixed_int 1024 - 0.0312142 +fixed_int 1024 * 0.716002 +fixed_int 1024 / 0.728338 +fixed_int 1024 str 0.0135445 +fixed_int 1024 +(int)0.011986 +fixed_int 1024 -(int)0.0119838 +fixed_int 1024 *(int)0.0349878 +fixed_int 1024 /(int)0.708856 +fixed_int 1024 % 0.723622 +fixed_int 1024 | 0.0181468 +fixed_int 1024 & 0.0182648 +fixed_int 1024 ^ 0.018185 +fixed_int 1024 << 0.0252997 +fixed_int 1024 >> 0.0257832 +fixed_int 1024 %(int)0.597535 +fixed_int 1024 |(int)0.0116417 +fixed_int 1024 &(int)0.0172111 +fixed_int 1024 ^(int)0.011526 +fixed_int 1024 gcd 70.6396 +[section:integer_performance Integer Type Perfomance] +[table Operator % +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.5779 (0.0951581s)][1.48514 (0.169015s)][1.59753 (0.306542s)][2.06645 (0.459737s)][2.79666 (0.800961s)]] +[[fixed_int][[*1] (0.0603067s)][[*1] (0.113804s)][1.04421 (0.200368s)][1.71708 (0.38201s)][2.52662 (0.723622s)]] +[[gmp_int][2.72898 (0.164576s)][1.41658 (0.161212s)][[*1] (0.191884s)][[*1] (0.222477s)][[*1] (0.286399s)]] +] +[table Operator %(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][[*1] (0.0229261s)][1.28944 (0.0476063s)][2.44735 (0.116093s)][3.21471 (0.194709s)][4.73812 (0.360619s)]] +[[fixed_int][1.05338 (0.0241499s)][2.19159 (0.0809135s)][3.22171 (0.152826s)][5.03092 (0.304714s)][7.85093 (0.597535s)]] +[[gmp_int][1.29749 (0.0297463s)][[*1] (0.03692s)][[*1] (0.0474363s)][[*1] (0.0605682s)][[*1] (0.0761102s)]] +] +[table Operator & +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][7.65289 (0.0196969s)][6.42545 (0.023126s)][2.4011 (0.0254172s)][2.26393 (0.0297235s)][2.01712 (0.0368423s)]] +[[fixed_int][[*1] (0.00257379s)][[*1] (0.00359913s)][[*1] (0.0105856s)][[*1] (0.0131292s)][[*1] (0.0182648s)]] +[[gmp_int][3.71307 (0.00955666s)][3.15518 (0.0113559s)][1.2071 (0.012778s)][1.25891 (0.0165285s)][1.2638 (0.023083s)]] +] +[table Operator &(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][10.8871 (0.0225055s)][11.6934 (0.0270183s)][8.67021 (0.0367792s)][6.53082 (0.0529542s)][4.65829 (0.0801744s)]] +[[fixed_int][[*1] (0.00206716s)][[*1] (0.00231056s)][[*1] (0.00424202s)][[*1] (0.00810836s)][[*1] (0.0172111s)]] +[[gmp_int][20.1865 (0.0417288s)][18.5392 (0.0428359s)][10.2956 (0.0436742s)][5.74703 (0.046599s)][2.90042 (0.0499195s)]] +] +[table Operator * +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][8.34111 (0.0326218s)][3.59818 (0.0375831s)][3.49662 (0.113247s)][3.40211 (0.337161s)][3.76364 (1.19319s)]] +[[fixed_int][[*1] (0.00391097s)][[*1] (0.010445s)][[*1] (0.0323875s)][2.07843 (0.205979s)][2.25847 (0.716002s)]] +[[gmp_int][2.87022 (0.0112253s)][1.54221 (0.0161084s)][1.28899 (0.0417471s)][[*1] (0.0991032s)][[*1] (0.31703s)]] +] +[table Operator *(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][5.15967 (0.0151037s)][4.21584 (0.0176402s)][2.33943 (0.0199426s)][2.04436 (0.0311497s)][1.67133 (0.0435058s)]] +[[fixed_int][[*1] (0.00292725s)][[*1] (0.00418426s)][[*1] (0.00852456s)][[*1] (0.0152369s)][1.3441 (0.0349878s)]] +[[gmp_int][3.01114 (0.00881438s)][2.72791 (0.0114143s)][1.60924 (0.0137181s)][1.1847 (0.0180512s)][[*1] (0.0260306s)]] +] +[table Operator + +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][7.37741 (0.0152915s)][5.2494 (0.0170788s)][2.95092 (0.0231877s)][2.21655 (0.0291058s)][1.27208 (0.0410101s)]] +[[fixed_int][[*1] (0.00207275s)][[*1] (0.00325349s)][[*1] (0.00785776s)][[*1] (0.0131311s)][[*1] (0.0322386s)]] +[[gmp_int][7.99998 (0.016582s)][5.62745 (0.0183088s)][2.86129 (0.0224834s)][2.11283 (0.0277439s)][1.23293 (0.0397479s)]] +] +[table Operator +(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][3.69474 (0.0132027s)][3.83536 (0.0144833s)][3.91229 (0.0161733s)][3.15733 (0.0201989s)][1.85579 (0.0222435s)]] +[[fixed_int][[*1] (0.00357336s)][[*1] (0.00377625s)][[*1] (0.00413397s)][[*1] (0.00639746s)][[*1] (0.011986s)]] +[[gmp_int][1.92643 (0.00688382s)][2.29418 (0.00866339s)][2.71097 (0.0112071s)][2.23261 (0.014283s)][1.58492 (0.0189969s)]] +] +[table Operator - +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][8.94166 (0.0191821s)][6.22351 (0.0228373s)][4.61443 (0.0293424s)][3.10192 (0.0380025s)][1.84766 (0.0576733s)]] +[[fixed_int][[*1] (0.00214524s)][[*1] (0.00366953s)][[*1] (0.00635884s)][[*1] (0.0122513s)][[*1] (0.0312142s)]] +[[gmp_int][8.13505 (0.0174517s)][5.15777 (0.0189266s)][3.94128 (0.025062s)][2.60278 (0.0318874s)][1.35297 (0.042232s)]] +] +[table Operator -(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][3.57555 (0.0126144s)][3.86529 (0.013922s)][4.56215 (0.0173225s)][3.12658 (0.0200688s)][1.83087 (0.0219408s)]] +[[fixed_int][[*1] (0.00352796s)][[*1] (0.00360179s)][[*1] (0.00379699s)][[*1] (0.00641876s)][[*1] (0.0119838s)]] +[[gmp_int][2.08226 (0.00734613s)][2.4833 (0.0089443s)][3.063 (0.0116302s)][2.33493 (0.0149874s)][1.62759 (0.0195046s)]] +] +[table Operator / +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.5631 (0.0951094s)][1.44205 (0.163958s)][1.655 (0.336287s)][1.77123 (0.487075s)][2.45907 (0.850798s)]] +[[fixed_int][[*1] (0.0608466s)][[*1] (0.113697s)][[*1] (0.203194s)][1.39495 (0.383601s)][2.10512 (0.728338s)]] +[[gmp_int][2.80954 (0.170951s)][1.68671 (0.191775s)][1.14992 (0.233656s)][[*1] (0.274993s)][[*1] (0.345984s)]] +] +[table Operator /(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.0209 (0.0491116s)][1.81816 (0.0972057s)][3.43412 (0.229286s)][4.13899 (0.375279s)][4.84836 (0.6795s)]] +[[fixed_int][[*1] (0.0243018s)][1.70472 (0.091141s)][2.74167 (0.183053s)][4.00675 (0.363289s)][5.05782 (0.708856s)]] +[[gmp_int][1.91611 (0.0465651s)][[*1] (0.0534638s)][[*1] (0.0667669s)][[*1] (0.0906691s)][[*1] (0.140151s)]] +] +[table Operator << +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][13.292 (0.0179372s)][3.27363 (0.0215749s)][2.9043 (0.0253994s)][2.52151 (0.0328422s)][2.34293 (0.0474759s)]] +[[fixed_int][[*1] (0.00134947s)][[*1] (0.0065905s)][[*1] (0.00874545s)][[*1] (0.0130248s)][1.24854 (0.0252997s)]] +[[gmp_int][7.85814 (0.0106043s)][1.56732 (0.0103295s)][1.38897 (0.0121471s)][1.13928 (0.014839s)][[*1] (0.0202635s)]] +] +[table Operator >> +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.60907 (0.0146206s)][2.28025 (0.0149198s)][2.07275 (0.0172635s)][2.37318 (0.0234706s)][2.32609 (0.0297527s)]] +[[fixed_int][[*1] (0.00560378s)][[*1] (0.00654308s)][1.08854 (0.00906624s)][1.32914 (0.0131451s)][2.01575 (0.0257832s)]] +[[gmp_int][1.67542 (0.0093887s)][1.24317 (0.00813413s)][[*1] (0.00832878s)][[*1] (0.00988994s)][[*1] (0.0127909s)]] +] +[table Operator ^ +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][8.06918 (0.0208608s)][6.34562 (0.0229278s)][2.44983 (0.0259082s)][2.25961 (0.0296913s)][2.04153 (0.0371252s)]] +[[fixed_int][[*1] (0.00258525s)][[*1] (0.00361317s)][[*1] (0.0105755s)][[*1] (0.01314s)][[*1] (0.018185s)]] +[[gmp_int][3.81916 (0.00987346s)][3.10299 (0.0112116s)][1.27226 (0.0134548s)][1.5894 (0.0208848s)][1.36422 (0.0248084s)]] +] +[table Operator ^(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.47925 (0.0191337s)][10.2109 (0.0194481s)][8.84686 (0.0232914s)][4.48677 (0.0258749s)][2.775 (0.0319848s)]] +[[fixed_int][[*1] (0.00201848s)][[*1] (0.00190464s)][[*1] (0.00263274s)][[*1] (0.00576694s)][[*1] (0.011526s)]] +[[gmp_int][20.1032 (0.0405779s)][21.9738 (0.0418522s)][16.1671 (0.0425636s)][7.91768 (0.0456608s)][4.2261 (0.0487102s)]] +] +[table Operator gcd +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][8.64165 (1.50205s)][7.81307 (3.36986s)][3.81369 (7.88882s)][4.20792 (19.7141s)][5.27284 (53.3224s)]] +[[fixed_int][4.72495 (0.82127s)][4.75589 (2.05126s)][2.62364 (5.42715s)][3.54898 (16.6269s)][6.98527 (70.6396s)]] +[[gmp_int][[*1] (0.173816s)][[*1] (0.43131s)][[*1] (2.06855s)][[*1] (4.68499s)][[*1] (10.1127s)]] +] +[table Operator str +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.46619 (0.000428547s)][1.98732 (0.000744647s)][3.17907 (0.00190436s)][3.81717 (0.00494162s)][5.50009 (0.0149378s)]] +[[fixed_int][[*1] (0.000292286s)][1.50755 (0.000564877s)][2.30639 (0.0013816s)][3.36465 (0.0043558s)][4.98706 (0.0135445s)]] +[[gmp_int][1.17587 (0.000343689s)][[*1] (0.000374699s)][[*1] (0.00059903s)][[*1] (0.00129458s)][[*1] (0.00271592s)]] +] +[table Operator | +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][7.73565 (0.0199629s)][6.36166 (0.0229631s)][2.43214 (0.0257191s)][2.26665 (0.0297101s)][2.0368 (0.0369613s)]] +[[fixed_int][[*1] (0.00258063s)][[*1] (0.00360961s)][[*1] (0.0105747s)][[*1] (0.0131075s)][[*1] (0.0181468s)]] +[[gmp_int][3.9353 (0.0101555s)][2.96987 (0.0107201s)][1.22452 (0.0129489s)][1.65632 (0.0217103s)][1.44352 (0.0261953s)]] +] +[table Operator |(int) +[[Backend][64 Bits][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.20066 (0.0185797s)][8.21071 (0.0194697s)][8.92746 (0.0233559s)][4.50916 (0.0258992s)][2.80194 (0.0326194s)]] +[[fixed_int][[*1] (0.00201939s)][[*1] (0.00237125s)][[*1] (0.00261619s)][[*1] (0.00574368s)][[*1] (0.0116417s)]] +[[gmp_int][19.9733 (0.0403338s)][17.3819 (0.0412168s)][16.2676 (0.0425591s)][8.05945 (0.0462909s)][4.22404 (0.049175s)]] +] +[endsect] diff --git a/performance/performance_test-msvc-10.log b/performance/performance_test-msvc-10.log new file mode 100644 index 00000000..3e271ff9 --- /dev/null +++ b/performance/performance_test-msvc-10.log @@ -0,0 +1,1220 @@ +gmp_float 50 + 0.110988 +gmp_float 50 - 0.119898 +gmp_float 50 * 0.275044 +gmp_float 50 / 1.27708 +gmp_float 50 str 0.013276 +gmp_float 50 +(int)0.0330888 +gmp_float 50 -(int)0.134451 +gmp_float 50 *(int)0.0422135 +gmp_float 50 /(int)0.180393 +gmp_float 50 construct0.19737 +gmp_float 50 construct(unsigned)0.208078 +gmp_float 50 construct(unsigned long long)0.520025 +gmp_float 50 + 0.498089 +gmp_float 50 - 0.502235 +gmp_float 50 * 0.564768 +gmp_float 50 / 0.90324 +gmp_float 50 + 0.477999 +gmp_float 50 - 0.499682 +gmp_float 50 * 0.551747 +gmp_float 50 / 0.893752 +gmp_float 100 + 0.111217 +gmp_float 100 - 0.120498 +gmp_float 100 * 0.416175 +gmp_float 100 / 1.69515 +gmp_float 100 str 0.0202949 +gmp_float 100 +(int)0.0386882 +gmp_float 100 -(int)0.1351 +gmp_float 100 *(int)0.0493716 +gmp_float 100 /(int)0.23378 +gmp_float 100 construct0.196599 +gmp_float 100 construct(unsigned)0.207062 +gmp_float 100 construct(unsigned long long)0.51936 +gmp_float 100 + 0.517172 +gmp_float 100 - 0.509588 +gmp_float 100 * 0.575954 +gmp_float 100 / 1.04262 +gmp_float 100 + 0.476701 +gmp_float 100 - 0.503546 +gmp_float 100 * 0.564962 +gmp_float 100 / 1.03328 +gmp_float 500 + 0.15445 +gmp_float 500 - 0.164099 +gmp_float 500 * 3.32799 +gmp_float 500 / 8.12655 +gmp_float 500 str 0.141162 +gmp_float 500 +(int)0.0646201 +gmp_float 500 -(int)0.176876 +gmp_float 500 *(int)0.0857876 +gmp_float 500 /(int)0.710204 +gmp_float 500 construct0.206063 +gmp_float 500 construct(unsigned)0.217019 +gmp_float 500 construct(unsigned long long)0.538021 +gmp_float 500 + 0.552532 +gmp_float 500 - 0.555754 +gmp_float 500 * 0.717186 +gmp_float 500 / 2.24686 +gmp_float 500 + 0.490614 +gmp_float 500 - 0.547751 +gmp_float 500 * 0.700957 +gmp_float 500 / 2.24146 +gmp_int 128 + 0.0421662 +gmp_int 128 - 0.0411848 +gmp_int 128 * 0.0708996 +gmp_int 128 / 0.868916 +gmp_int 128 str 0.00185638 +gmp_int 128 +(int)0.0311237 +gmp_int 128 -(int)0.030585 +gmp_int 128 *(int)0.022756 +gmp_int 128 /(int)0.0560401 +gmp_int 128 construct0.196182 +gmp_int 128 construct(unsigned)0.206113 +gmp_int 128 construct(unsigned long long)0.719741 +gmp_int 128 % 0.64148 +gmp_int 128 | 0.0474678 +gmp_int 128 & 0.0538128 +gmp_int 128 ^ 0.0497194 +gmp_int 128 << 0.0273994 +gmp_int 128 >> 0.0288237 +gmp_int 128 %(int)0.0572117 +gmp_int 128 |(int)0.141119 +gmp_int 128 &(int)0.141306 +gmp_int 128 ^(int)0.143934 +gmp_int 128 gcd 2.45095 +gmp_int 128 + 0.71217 +gmp_int 128 - 0.687129 +gmp_int 128 * 0.716479 +gmp_int 128 / 1.04926 +gmp_int 128 + 0.68136 +gmp_int 128 - 0.681187 +gmp_int 128 * 3.1627 +gmp_int 128 / 0.685487 +gmp_int 256 + 0.0449584 +gmp_int 256 - 0.0461316 +gmp_int 256 * 0.134302 +gmp_int 256 / 0.951505 +gmp_int 256 str 0.00344576 +gmp_int 256 +(int)0.0428011 +gmp_int 256 -(int)0.0400434 +gmp_int 256 *(int)0.0282672 +gmp_int 256 /(int)0.0982823 +gmp_int 256 construct0.201199 +gmp_int 256 construct(unsigned)0.211295 +gmp_int 256 construct(unsigned long long)0.729487 +gmp_int 256 % 0.703592 +gmp_int 256 | 0.0618281 +gmp_int 256 & 0.0652169 +gmp_int 256 ^ 0.0630174 +gmp_int 256 << 0.031973 +gmp_int 256 >> 0.0310184 +gmp_int 256 %(int)0.10258 +gmp_int 256 |(int)0.142987 +gmp_int 256 &(int)0.139398 +gmp_int 256 ^(int)0.144825 +gmp_int 256 gcd 5.89505 +gmp_int 256 + 0.728978 +gmp_int 256 - 0.707806 +gmp_int 256 * 0.731454 +gmp_int 256 / 1.17203 +gmp_int 256 + 0.68929 +gmp_int 256 - 0.683532 +gmp_int 256 * 3.15114 +gmp_int 256 / 0.689516 +gmp_int 512 + 0.0522202 +gmp_int 512 - 0.0567637 +gmp_int 512 * 0.532277 +gmp_int 512 / 1.06442 +gmp_int 512 str 0.00618403 +gmp_int 512 +(int)0.0665539 +gmp_int 512 -(int)0.0578194 +gmp_int 512 *(int)0.0361075 +gmp_int 512 /(int)0.183564 +gmp_int 512 construct0.19783 +gmp_int 512 construct(unsigned)0.206944 +gmp_int 512 construct(unsigned long long)0.724649 +gmp_int 512 % 0.819828 +gmp_int 512 | 0.0856626 +gmp_int 512 & 0.092104 +gmp_int 512 ^ 0.0869819 +gmp_int 512 << 0.0471709 +gmp_int 512 >> 0.0337511 +gmp_int 512 %(int)0.188529 +gmp_int 512 |(int)0.155656 +gmp_int 512 &(int)0.142498 +gmp_int 512 ^(int)0.152773 +gmp_int 512 gcd 13.6993 +gmp_int 512 + 0.759532 +gmp_int 512 - 0.732529 +gmp_int 512 * 0.779921 +gmp_int 512 / 1.39149 +gmp_int 512 + 0.694235 +gmp_int 512 - 0.69246 +gmp_int 512 * 3.17094 +gmp_int 512 / 0.688995 +gmp_int 1024 + 0.0699873 +gmp_int 1024 - 0.0731244 +gmp_int 1024 * 1.57852 +gmp_int 1024 / 1.30215 +gmp_int 1024 str 0.0144523 +gmp_int 1024 +(int)0.108272 +gmp_int 1024 -(int)0.100541 +gmp_int 1024 *(int)0.0518882 +gmp_int 1024 /(int)0.352238 +gmp_int 1024 construct0.19744 +gmp_int 1024 construct(unsigned)0.216229 +gmp_int 1024 construct(unsigned long long)0.722262 +gmp_int 1024 % 1.01959 +gmp_int 1024 | 0.136082 +gmp_int 1024 & 0.144412 +gmp_int 1024 ^ 0.139109 +gmp_int 1024 << 0.0721984 +gmp_int 1024 >> 0.0388038 +gmp_int 1024 %(int)0.355222 +gmp_int 1024 |(int)0.163236 +gmp_int 1024 &(int)0.141249 +gmp_int 1024 ^(int)0.161662 +gmp_int 1024 gcd 33.2232 +gmp_int 1024 + 0.83035 +gmp_int 1024 - 0.78115 +gmp_int 1024 * 0.815503 +gmp_int 1024 / 1.84054 +gmp_int 1024 + 0.690013 +gmp_int 1024 - 0.690838 +gmp_int 1024 * 3.20893 +gmp_int 1024 / 0.707578 +cpp_int(unsigned, fixed)64 + 0.00232166 +cpp_int(unsigned, fixed)64 - 0.00234506 +cpp_int(unsigned, fixed)64 * 0.00470304 +cpp_int(unsigned, fixed)64 / 0.0714786 +cpp_int(unsigned, fixed)64 str 0.00256457 +cpp_int(unsigned, fixed)64 +(int)0.00162053 +cpp_int(unsigned, fixed)64 -(int)0.00163617 +cpp_int(unsigned, fixed)64 *(int)0.00236511 +cpp_int(unsigned, fixed)64 /(int)0.0299559 +cpp_int(unsigned, fixed)64 construct0.00111299 +cpp_int(unsigned, fixed)64 construct(unsigned)0.00110489 +cpp_int(unsigned, fixed)64 construct(unsigned long long)0.00240876 +cpp_int(unsigned, fixed)64 % 0.0702826 +cpp_int(unsigned, fixed)64 | 0.00265921 +cpp_int(unsigned, fixed)64 & 0.00261653 +cpp_int(unsigned, fixed)64 ^ 0.0040003 +cpp_int(unsigned, fixed)64 << 0.00161592 +cpp_int(unsigned, fixed)64 >> 0.00161599 +cpp_int(unsigned, fixed)64 %(int)0.0298064 +cpp_int(unsigned, fixed)64 |(int)0.00165538 +cpp_int(unsigned, fixed)64 &(int)0.00161431 +cpp_int(unsigned, fixed)64 ^(int)0.00184507 +cpp_int(unsigned, fixed)64 gcd 0.602722 +cpp_int(unsigned, fixed)64 + 0.00253726 +cpp_int(unsigned, fixed)64 - 0.00301519 +cpp_int(unsigned, fixed)64 * 0.00474872 +cpp_int(unsigned, fixed)64 / 0.0450108 +cpp_int(unsigned, fixed)64 + 0.0020173 +cpp_int(unsigned, fixed)64 - 0.00191079 +cpp_int(unsigned, fixed)64 * 0.00445077 +cpp_int(unsigned, fixed)64 / 0.0294528 +cpp_int(fixed) 64 + 0.00573474 +cpp_int(fixed) 64 - 0.0096272 +cpp_int(fixed) 64 * 0.00897607 +cpp_int(fixed) 64 / 0.0783882 +cpp_int(fixed) 64 str 0.00251659 +cpp_int(fixed) 64 +(int)0.00636247 +cpp_int(fixed) 64 -(int)0.00668367 +cpp_int(fixed) 64 *(int)0.00548722 +cpp_int(fixed) 64 /(int)0.0362985 +cpp_int(fixed) 64 construct0.00161745 +cpp_int(fixed) 64 construct(unsigned)0.00209147 +cpp_int(fixed) 64 construct(unsigned long long)0.00204998 +cpp_int(fixed) 64 % 0.0777437 +cpp_int(fixed) 64 | 0.0108982 +cpp_int(fixed) 64 & 0.0124165 +cpp_int(fixed) 64 ^ 0.0110313 +cpp_int(fixed) 64 << 0.00516511 +cpp_int(fixed) 64 >> 0.00399499 +cpp_int(fixed) 64 %(int)0.0341425 +cpp_int(fixed) 64 |(int)0.0111002 +cpp_int(fixed) 64 &(int)0.0104782 +cpp_int(fixed) 64 ^(int)0.0107199 +cpp_int(fixed) 64 gcd 0.604291 +cpp_int(fixed) 64 + 0.00605482 +cpp_int(fixed) 64 - 0.00714372 +cpp_int(fixed) 64 * 0.00873093 +cpp_int(fixed) 64 / 0.0510195 +cpp_int(fixed) 64 + 0.00430062 +cpp_int(fixed) 64 - 0.00387577 +cpp_int(fixed) 64 * 0.00567824 +cpp_int(fixed) 64 / 0.0320162 +cpp_int(fixed) 128 + 0.0358493 +cpp_int(fixed) 128 - 0.0397574 +cpp_int(fixed) 128 * 0.0672363 +cpp_int(fixed) 128 / 0.222933 +cpp_int(fixed) 128 str 0.0015613 +cpp_int(fixed) 128 +(int)0.0268311 +cpp_int(fixed) 128 -(int)0.0241848 +cpp_int(fixed) 128 *(int)0.0328109 +cpp_int(fixed) 128 /(int)0.137619 +cpp_int(fixed) 128 construct0.00164665 +cpp_int(fixed) 128 construct(unsigned)0.0015986 +cpp_int(fixed) 128 construct(unsigned long long)0.00312994 +cpp_int(fixed) 128 % 0.1971 +cpp_int(fixed) 128 | 0.0380136 +cpp_int(fixed) 128 & 0.0341411 +cpp_int(fixed) 128 ^ 0.0351059 +cpp_int(fixed) 128 << 0.0320915 +cpp_int(fixed) 128 >> 0.0293055 +cpp_int(fixed) 128 %(int)0.103684 +cpp_int(fixed) 128 |(int)0.0317854 +cpp_int(fixed) 128 &(int)0.0417383 +cpp_int(fixed) 128 ^(int)0.0312355 +cpp_int(fixed) 128 gcd 4.18006 +cpp_int(fixed) 128 + 0.0341301 +cpp_int(fixed) 128 - 0.0346952 +cpp_int(fixed) 128 * 0.0675308 +cpp_int(fixed) 128 / 0.466907 +cpp_int(fixed) 128 + 0.0168342 +cpp_int(fixed) 128 - 0.0169449 +cpp_int(fixed) 128 * 0.0673436 +cpp_int(fixed) 128 / 0.0327432 +cpp_int(fixed) 256 + 0.0552275 +cpp_int(fixed) 256 - 0.0560103 +cpp_int(fixed) 256 * 0.166666 +cpp_int(fixed) 256 / 0.349956 +cpp_int(fixed) 256 str 0.00297279 +cpp_int(fixed) 256 +(int)0.0410749 +cpp_int(fixed) 256 -(int)0.0368306 +cpp_int(fixed) 256 *(int)0.049867 +cpp_int(fixed) 256 /(int)0.253796 +cpp_int(fixed) 256 construct0.00363363 +cpp_int(fixed) 256 construct(unsigned)0.00370466 +cpp_int(fixed) 256 construct(unsigned long long)0.00388115 +cpp_int(fixed) 256 % 0.334027 +cpp_int(fixed) 256 | 0.0529581 +cpp_int(fixed) 256 & 0.0501131 +cpp_int(fixed) 256 ^ 0.0530521 +cpp_int(fixed) 256 << 0.0507053 +cpp_int(fixed) 256 >> 0.039006 +cpp_int(fixed) 256 %(int)0.200647 +cpp_int(fixed) 256 |(int)0.0466958 +cpp_int(fixed) 256 &(int)0.0539427 +cpp_int(fixed) 256 ^(int)0.0476923 +cpp_int(fixed) 256 gcd 10.2671 +cpp_int(fixed) 256 + 0.0452762 +cpp_int(fixed) 256 - 0.0444216 +cpp_int(fixed) 256 * 0.112885 +cpp_int(fixed) 256 / 1.36886 +cpp_int(fixed) 256 + 0.0170491 +cpp_int(fixed) 256 - 0.0176783 +cpp_int(fixed) 256 * 0.107306 +cpp_int(fixed) 256 / 0.0340708 +cpp_int(fixed) 512 + 0.0760722 +cpp_int(fixed) 512 - 0.0756027 +cpp_int(fixed) 512 * 0.500399 +cpp_int(fixed) 512 / 0.560837 +cpp_int(fixed) 512 str 0.00708386 +cpp_int(fixed) 512 +(int)0.0524416 +cpp_int(fixed) 512 -(int)0.0503396 +cpp_int(fixed) 512 *(int)0.0658566 +cpp_int(fixed) 512 /(int)0.446782 +cpp_int(fixed) 512 construct0.00576526 +cpp_int(fixed) 512 construct(unsigned)0.0058189 +cpp_int(fixed) 512 construct(unsigned long long)0.00556537 +cpp_int(fixed) 512 % 0.539708 +cpp_int(fixed) 512 | 0.0676884 +cpp_int(fixed) 512 & 0.0588367 +cpp_int(fixed) 512 ^ 0.0695132 +cpp_int(fixed) 512 << 0.0597514 +cpp_int(fixed) 512 >> 0.0515714 +cpp_int(fixed) 512 %(int)0.377704 +cpp_int(fixed) 512 |(int)0.0536974 +cpp_int(fixed) 512 &(int)0.070425 +cpp_int(fixed) 512 ^(int)0.0540962 +cpp_int(fixed) 512 gcd 26.2762 +cpp_int(fixed) 512 + 0.0571069 +cpp_int(fixed) 512 - 0.0563175 +cpp_int(fixed) 512 * 0.177444 +cpp_int(fixed) 512 / 3.1662 +cpp_int(fixed) 512 + 0.0172628 +cpp_int(fixed) 512 - 0.0180756 +cpp_int(fixed) 512 * 0.171821 +cpp_int(fixed) 512 / 0.0444905 +cpp_int(fixed) 1024 + 0.121124 +cpp_int(fixed) 1024 - 0.114246 +cpp_int(fixed) 1024 * 1.54633 +cpp_int(fixed) 1024 / 0.975643 +cpp_int(fixed) 1024 str 0.0172514 +cpp_int(fixed) 1024 +(int)0.0728817 +cpp_int(fixed) 1024 -(int)0.0621059 +cpp_int(fixed) 1024 *(int)0.0948565 +cpp_int(fixed) 1024 /(int)0.84764 +cpp_int(fixed) 1024 construct0.00535599 +cpp_int(fixed) 1024 construct(unsigned)0.00836042 +cpp_int(fixed) 1024 construct(unsigned long long)0.00577713 +cpp_int(fixed) 1024 % 0.94847 +cpp_int(fixed) 1024 | 0.100936 +cpp_int(fixed) 1024 & 0.0774574 +cpp_int(fixed) 1024 ^ 0.09783 +cpp_int(fixed) 1024 << 0.0677088 +cpp_int(fixed) 1024 >> 0.0626121 +cpp_int(fixed) 1024 %(int)0.743202 +cpp_int(fixed) 1024 |(int)0.0819107 +cpp_int(fixed) 1024 &(int)0.112823 +cpp_int(fixed) 1024 ^(int)0.0806317 +cpp_int(fixed) 1024 gcd 76.2849 +cpp_int(fixed) 1024 + 0.0636724 +cpp_int(fixed) 1024 - 0.06467 +cpp_int(fixed) 1024 * 0.303514 +cpp_int(fixed) 1024 / 8.04418 +cpp_int(fixed) 1024 + 0.0181245 +cpp_int(fixed) 1024 - 0.0190581 +cpp_int(fixed) 1024 * 0.299236 +cpp_int(fixed) 1024 / 0.106788 +cpp_int 128 + 0.0273725 +cpp_int 128 - 0.0303219 +cpp_int 128 * 0.0774619 +cpp_int 128 / 0.589941 +cpp_int 128 str 0.00189808 +cpp_int 128 +(int)0.0159069 +cpp_int 128 -(int)0.0151244 +cpp_int 128 *(int)0.0235876 +cpp_int 128 /(int)0.235955 +cpp_int 128 construct0.00293927 +cpp_int 128 construct(unsigned)0.00270684 +cpp_int 128 construct(unsigned long long)0.00719854 +cpp_int 128 % 0.37333 +cpp_int 128 | 0.030991 +cpp_int 128 & 0.031605 +cpp_int 128 ^ 0.0318172 +cpp_int 128 << 0.0256107 +cpp_int 128 >> 0.0237523 +cpp_int 128 %(int)0.104856 +cpp_int 128 |(int)0.0280516 +cpp_int 128 &(int)0.0377678 +cpp_int 128 ^(int)0.0283305 +cpp_int 128 gcd 4.98644 +cpp_int 128 + 0.0283071 +cpp_int 128 - 0.027289 +cpp_int 128 * 0.0584001 +cpp_int 128 / 0.733741 +cpp_int 128 + 0.0196594 +cpp_int 128 - 0.0210968 +cpp_int 128 * 7.6372 +cpp_int 128 / 0.0578293 +cpp_int 256 + 0.0384835 +cpp_int 256 - 0.0402028 +cpp_int 256 * 0.211395 +cpp_int 256 / 0.708882 +cpp_int 256 str 0.00391656 +cpp_int 256 +(int)0.0218386 +cpp_int 256 -(int)0.017199 +cpp_int 256 *(int)0.0318939 +cpp_int 256 /(int)0.35212 +cpp_int 256 construct0.00277479 +cpp_int 256 construct(unsigned)0.0030529 +cpp_int 256 construct(unsigned long long)0.00725455 +cpp_int 256 % 0.673748 +cpp_int 256 | 0.0429658 +cpp_int 256 & 0.0455929 +cpp_int 256 ^ 0.0425243 +cpp_int 256 << 0.0401135 +cpp_int 256 >> 0.0302534 +cpp_int 256 %(int)0.203012 +cpp_int 256 |(int)0.0363929 +cpp_int 256 &(int)0.0471524 +cpp_int 256 ^(int)0.0353555 +cpp_int 256 gcd 11.1816 +cpp_int 256 + 0.030223 +cpp_int 256 - 0.0319489 +cpp_int 256 * 0.0885733 +cpp_int 256 / 1.62706 +cpp_int 256 + 0.0215291 +cpp_int 256 - 0.0213343 +cpp_int 256 * 7.7121 +cpp_int 256 / 0.0615507 +cpp_int 512 + 0.0561351 +cpp_int 512 - 0.0543342 +cpp_int 512 * 0.703234 +cpp_int 512 / 0.924042 +cpp_int 512 str 0.00832019 +cpp_int 512 +(int)0.0316584 +cpp_int 512 -(int)0.0248084 +cpp_int 512 *(int)0.0427792 +cpp_int 512 /(int)0.568032 +cpp_int 512 construct0.0028102 +cpp_int 512 construct(unsigned)0.00288857 +cpp_int 512 construct(unsigned long long)0.00723891 +cpp_int 512 % 0.701584 +cpp_int 512 | 0.0537846 +cpp_int 512 & 0.0546439 +cpp_int 512 ^ 0.0542436 +cpp_int 512 << 0.0436188 +cpp_int 512 >> 0.0355247 +cpp_int 512 %(int)0.391566 +cpp_int 512 |(int)0.0418143 +cpp_int 512 &(int)0.0647085 +cpp_int 512 ^(int)0.041758 +cpp_int 512 gcd 27.2257 +cpp_int 512 + 0.0382495 +cpp_int 512 - 0.0386744 +cpp_int 512 * 0.14417 +cpp_int 512 / 3.61202 +cpp_int 512 + 0.0228565 +cpp_int 512 - 0.0222868 +cpp_int 512 * 7.72815 +cpp_int 512 / 0.0732298 +cpp_int 1024 + 0.0928746 +cpp_int 1024 - 0.0853837 +cpp_int 1024 * 2.6591 +cpp_int 1024 / 1.38142 +cpp_int 1024 str 0.0221599 +cpp_int 1024 +(int)0.0430289 +cpp_int 1024 -(int)0.0331224 +cpp_int 1024 *(int)0.0668616 +cpp_int 1024 /(int)0.989885 +cpp_int 1024 construct0.00277298 +cpp_int 1024 construct(unsigned)0.00265201 +cpp_int 1024 construct(unsigned long long)0.00732796 +cpp_int 1024 % 1.14369 +cpp_int 1024 | 0.0827684 +cpp_int 1024 & 0.0843863 +cpp_int 1024 ^ 0.08333 +cpp_int 1024 << 0.0628544 +cpp_int 1024 >> 0.044717 +cpp_int 1024 %(int)0.768511 +cpp_int 1024 |(int)0.0527075 +cpp_int 1024 &(int)0.10089 +cpp_int 1024 ^(int)0.0538323 +cpp_int 1024 gcd 73.3735 +cpp_int 1024 + 0.0463315 +cpp_int 1024 - 0.0468398 +cpp_int 1024 * 0.255279 +cpp_int 1024 / 8.42528 +cpp_int 1024 + 0.0227402 +cpp_int 1024 - 0.0234526 +cpp_int 1024 * 7.86395 +cpp_int 1024 / 0.123568 +cpp_rational 128 + 18.0021 +cpp_rational 128 - 18.0006 +cpp_rational 128 * 31.5924 +cpp_rational 128 / 65.714 +cpp_rational 128 str 0.020339 +cpp_rational 128 +(int)2.47739 +cpp_rational 128 -(int)2.47959 +cpp_rational 128 *(int)2.4377 +cpp_rational 128 /(int)2.50843 +cpp_rational 128 construct0.0102665 +cpp_rational 128 construct(unsigned)0.0624887 +cpp_rational 128 construct(unsigned long long)0.0658436 +cpp_rational 128 + 2.58812 +cpp_rational 128 - 2.60864 +cpp_rational 128 * 5.53837 +cpp_rational 128 / 5.63033 +cpp_rational 128 + 2.68363 +cpp_rational 128 - 2.72926 +cpp_rational 128 * 57.9393 +cpp_rational 128 / 58.0332 +cpp_rational 256 + 46.3981 +cpp_rational 256 - 46.4818 +cpp_rational 256 * 86.0189 +cpp_rational 256 / 172.8 +cpp_rational 256 str 0.0517328 +cpp_rational 256 +(int)2.92179 +cpp_rational 256 -(int)2.90579 +cpp_rational 256 *(int)2.91325 +cpp_rational 256 /(int)3.00689 +cpp_rational 256 construct0.0101737 +cpp_rational 256 construct(unsigned)0.0609531 +cpp_rational 256 construct(unsigned long long)0.0665504 +cpp_rational 256 + 3.0953 +cpp_rational 256 - 3.08277 +cpp_rational 256 * 6.78796 +cpp_rational 256 / 6.90941 +cpp_rational 256 + 3.15142 +cpp_rational 256 - 3.19882 +cpp_rational 256 * 59.3172 +cpp_rational 256 / 59.5431 +cpp_rational 512 + 108.57 +cpp_rational 512 - 108.81 +cpp_rational 512 * 202.007 +cpp_rational 512 / 348.46 +cpp_rational 512 str 0.119248 +cpp_rational 512 +(int)3.80252 +cpp_rational 512 -(int)3.80714 +cpp_rational 512 *(int)3.94768 +cpp_rational 512 /(int)4.00588 +cpp_rational 512 construct0.0101965 +cpp_rational 512 construct(unsigned)0.0613968 +cpp_rational 512 construct(unsigned long long)0.0659082 +cpp_rational 512 + 4.00751 +cpp_rational 512 - 4.0117 +cpp_rational 512 * 9.43852 +cpp_rational 512 / 9.39508 +cpp_rational 512 + 4.05684 +cpp_rational 512 - 4.08474 +cpp_rational 512 * 61.8998 +cpp_rational 512 / 61.9712 +cpp_rational 1024 + 252.723 +cpp_rational 1024 - 253.81 +cpp_rational 1024 * 484.128 +cpp_rational 1024 / 834.057 +cpp_rational 1024 str 0.286067 +cpp_rational 1024 +(int)5.51612 +cpp_rational 1024 -(int)5.51949 +cpp_rational 1024 *(int)5.87507 +cpp_rational 1024 /(int)5.92837 +cpp_rational 1024 construct0.0102909 +cpp_rational 1024 construct(unsigned)0.062674 +cpp_rational 1024 construct(unsigned long long)0.0659089 +cpp_rational 1024 + 5.7444 +cpp_rational 1024 - 5.73296 +cpp_rational 1024 * 15.1475 +cpp_rational 1024 / 14.9497 +cpp_rational 1024 + 5.80438 +cpp_rational 1024 - 5.86 +cpp_rational 1024 * 67.4139 +cpp_rational 1024 / 67.4254 +mpq_rational 128 + 3.16879 +mpq_rational 128 - 3.18835 +mpq_rational 128 * 5.96709 +mpq_rational 128 / 15.0571 +mpq_rational 128 str 0.0037011 +mpq_rational 128 +(int)0.669634 +mpq_rational 128 -(int)0.666993 +mpq_rational 128 *(int)1.18047 +mpq_rational 128 /(int)1.43177 +mpq_rational 128 construct0.383107 +mpq_rational 128 construct(unsigned)0.394551 +mpq_rational 128 construct(unsigned long long)2.13183 +mpq_rational 128 + 2.33701 +mpq_rational 128 - 2.33227 +mpq_rational 128 * 4.15268 +mpq_rational 128 / 4.26818 +mpq_rational 128 + 2.33097 +mpq_rational 128 - 2.31793 +mpq_rational 128 * 9.34086 +mpq_rational 128 / 9.74135 +mpq_rational 256 + 6.93507 +mpq_rational 256 - 6.90939 +mpq_rational 256 * 12.9674 +mpq_rational 256 / 27.1144 +mpq_rational 256 str 0.00573278 +mpq_rational 256 +(int)0.707818 +mpq_rational 256 -(int)0.719174 +mpq_rational 256 *(int)1.22229 +mpq_rational 256 /(int)1.46082 +mpq_rational 256 construct0.381537 +mpq_rational 256 construct(unsigned)0.390987 +mpq_rational 256 construct(unsigned long long)2.12727 +mpq_rational 256 + 2.4159 +mpq_rational 256 - 2.41594 +mpq_rational 256 * 4.3447 +mpq_rational 256 / 4.43342 +mpq_rational 256 + 2.40187 +mpq_rational 256 - 2.39792 +mpq_rational 256 * 9.51195 +mpq_rational 256 / 9.65697 +mpq_rational 512 + 16.0886 +mpq_rational 512 - 16.1169 +mpq_rational 512 * 29.597 +mpq_rational 512 / 54.8579 +mpq_rational 512 str 0.012222 +mpq_rational 512 +(int)0.812783 +mpq_rational 512 -(int)0.810939 +mpq_rational 512 *(int)1.37678 +mpq_rational 512 /(int)1.6328 +mpq_rational 512 construct0.381355 +mpq_rational 512 construct(unsigned)0.392309 +mpq_rational 512 construct(unsigned long long)2.1179 +mpq_rational 512 + 2.55999 +mpq_rational 512 - 2.52842 +mpq_rational 512 * 4.82251 +mpq_rational 512 / 4.88079 +mpq_rational 512 + 2.5091 +mpq_rational 512 - 2.50572 +mpq_rational 512 * 9.90285 +mpq_rational 512 / 10.0077 +mpq_rational 1024 + 38.8883 +mpq_rational 1024 - 38.9096 +mpq_rational 1024 * 71.0635 +mpq_rational 1024 / 123.985 +mpq_rational 1024 str 0.0291802 +mpq_rational 1024 +(int)0.906471 +mpq_rational 1024 -(int)0.908293 +mpq_rational 1024 *(int)1.52386 +mpq_rational 1024 /(int)1.78575 +mpq_rational 1024 construct0.383461 +mpq_rational 1024 construct(unsigned)0.393504 +mpq_rational 1024 construct(unsigned long long)2.12279 +mpq_rational 1024 + 2.67794 +mpq_rational 1024 - 2.65991 +mpq_rational 1024 * 5.4209 +mpq_rational 1024 / 5.47417 +mpq_rational 1024 + 2.66144 +mpq_rational 1024 - 2.64168 +mpq_rational 1024 * 10.4664 +mpq_rational 1024 / 10.6781 +tommath_int 128 + 0.0222815 +tommath_int 128 - 0.027712 +tommath_int 128 * 0.113094 +tommath_int 128 / 3.09636 +tommath_int 128 str 0.0175165 +tommath_int 128 +(int)0.205506 +tommath_int 128 -(int)0.203148 +tommath_int 128 *(int)0.245897 +tommath_int 128 /(int)2.08045 +tommath_int 128 construct0.207455 +tommath_int 128 construct(unsigned)0.477971 +tommath_int 128 construct(unsigned long long)0.709516 +tommath_int 128 % 3.15171 +tommath_int 128 | 0.153434 +tommath_int 128 & 0.153508 +tommath_int 128 ^ 0.153931 +tommath_int 128 << 0.0408165 +tommath_int 128 >> 0.324163 +tommath_int 128 %(int)2.11648 +tommath_int 128 |(int)0.376671 +tommath_int 128 &(int)0.389144 +tommath_int 128 ^(int)0.374303 +tommath_int 128 gcd 12.5322 +tommath_int 128 + 0.514965 +tommath_int 128 - 0.517555 +tommath_int 128 * 0.607102 +tommath_int 128 / 2.36098 +tommath_int 128 + 0.510608 +tommath_int 128 - 0.520979 +tommath_int 128 * 18.5642 +tommath_int 128 / 1.13357 +tommath_int 256 + 0.0322049 +tommath_int 256 - 0.0407704 +tommath_int 256 * 0.346903 +tommath_int 256 / 4.01311 +tommath_int 256 str 0.0409078 +tommath_int 256 +(int)0.211847 +tommath_int 256 -(int)0.206481 +tommath_int 256 *(int)0.26894 +tommath_int 256 /(int)2.7099 +tommath_int 256 construct0.208012 +tommath_int 256 construct(unsigned)0.470752 +tommath_int 256 construct(unsigned long long)0.709045 +tommath_int 256 % 4.08522 +tommath_int 256 | 0.170093 +tommath_int 256 & 0.176384 +tommath_int 256 ^ 0.172198 +tommath_int 256 << 0.0698155 +tommath_int 256 >> 0.383757 +tommath_int 256 %(int)2.74052 +tommath_int 256 |(int)0.375206 +tommath_int 256 &(int)0.389768 +tommath_int 256 ^(int)0.379255 +tommath_int 256 gcd 26.1755 +tommath_int 256 + 0.530504 +tommath_int 256 - 0.527832 +tommath_int 256 * 0.648438 +tommath_int 256 / 3.16803 +tommath_int 256 + 0.526199 +tommath_int 256 - 0.527479 +tommath_int 256 * 18.624 +tommath_int 256 / 1.1208 +tommath_int 512 + 0.0455267 +tommath_int 512 - 0.0515883 +tommath_int 512 * 0.999026 +tommath_int 512 / 5.95775 +tommath_int 512 str 0.111392 +tommath_int 512 +(int)0.227429 +tommath_int 512 -(int)0.219998 +tommath_int 512 *(int)0.31746 +tommath_int 512 /(int)4.1339 +tommath_int 512 construct0.205622 +tommath_int 512 construct(unsigned)0.473807 +tommath_int 512 construct(unsigned long long)0.703879 +tommath_int 512 % 5.70483 +tommath_int 512 | 0.179084 +tommath_int 512 & 0.182373 +tommath_int 512 ^ 0.183434 +tommath_int 512 << 0.0973643 +tommath_int 512 >> 0.398354 +tommath_int 512 %(int)3.96918 +tommath_int 512 |(int)0.381428 +tommath_int 512 &(int)0.40432 +tommath_int 512 ^(int)0.390434 +tommath_int 512 gcd 56.7747 +tommath_int 512 + 0.546222 +tommath_int 512 - 0.53408 +tommath_int 512 * 0.718764 +tommath_int 512 / 5.07545 +tommath_int 512 + 0.543084 +tommath_int 512 - 0.535411 +tommath_int 512 * 18.745 +tommath_int 512 / 1.15084 +tommath_int 1024 + 0.074223 +tommath_int 1024 - 0.0786205 +tommath_int 1024 * 3.20269 +tommath_int 1024 / 12.7383 +tommath_int 1024 str 0.345861 +tommath_int 1024 +(int)0.250477 +tommath_int 1024 -(int)0.2372 +tommath_int 1024 *(int)0.408933 +tommath_int 1024 /(int)9.04346 +tommath_int 1024 construct0.207377 +tommath_int 1024 construct(unsigned)0.475755 +tommath_int 1024 construct(unsigned long long)0.712949 +tommath_int 1024 % 12.6845 +tommath_int 1024 | 0.436588 +tommath_int 1024 & 0.429721 +tommath_int 1024 ^ 0.429478 +tommath_int 1024 << 0.167289 +tommath_int 1024 >> 0.570323 +tommath_int 1024 %(int)9.09202 +tommath_int 1024 |(int)0.622404 +tommath_int 1024 &(int)0.653128 +tommath_int 1024 ^(int)0.62285 +tommath_int 1024 gcd 132.299 +tommath_int 1024 + 0.578521 +tommath_int 1024 - 0.552649 +tommath_int 1024 * 0.871648 +tommath_int 1024 / 12.2672 +tommath_int 1024 + 0.568301 +tommath_int 1024 - 0.54931 +tommath_int 1024 * 19.0954 +tommath_int 1024 / 1.21165 +cpp_dec_float 50 + 0.0250949 +cpp_dec_float 50 - 0.0264782 +cpp_dec_float 50 * 0.163403 +cpp_dec_float 50 / 3.9502 +cpp_dec_float 50 str 0.0207318 +cpp_dec_float 50 +(int)0.0441266 +cpp_dec_float 50 -(int)0.0442578 +cpp_dec_float 50 *(int)0.234992 +cpp_dec_float 50 /(int)1.81469 +cpp_dec_float 50 construct0.00925753 +cpp_dec_float 50 construct(unsigned)0.0588752 +cpp_dec_float 50 construct(unsigned long long)0.0587691 +cpp_dec_float 50 + 0.0770875 +cpp_dec_float 50 - 0.0741921 +cpp_dec_float 50 * 0.329282 +cpp_dec_float 50 / 1.9701 +cpp_dec_float 50 + 0.0640148 +cpp_dec_float 50 - 0.0643402 +cpp_dec_float 50 * 0.321363 +cpp_dec_float 50 / 1.97464 +cpp_dec_float 100 + 0.0291508 +cpp_dec_float 100 - 0.0307447 +cpp_dec_float 100 * 0.284182 +cpp_dec_float 100 / 7.68823 +cpp_dec_float 100 str 0.0328218 +cpp_dec_float 100 +(int)0.0558389 +cpp_dec_float 100 -(int)0.0563278 +cpp_dec_float 100 *(int)0.460635 +cpp_dec_float 100 /(int)3.62471 +cpp_dec_float 100 construct0.0263234 +cpp_dec_float 100 construct(unsigned)0.0747853 +cpp_dec_float 100 construct(unsigned long long)0.076338 +cpp_dec_float 100 + 0.0845054 +cpp_dec_float 100 - 0.0844193 +cpp_dec_float 100 * 0.582119 +cpp_dec_float 100 / 3.8773 +cpp_dec_float 100 + 0.0708668 +cpp_dec_float 100 - 0.0730765 +cpp_dec_float 100 * 0.574512 +cpp_dec_float 100 / 3.83437 +cpp_dec_float 500 + 0.0630915 +cpp_dec_float 500 - 0.0651113 +cpp_dec_float 500 * 2.22501 +cpp_dec_float 500 / 50.6121 +cpp_dec_float 500 str 0.131293 +cpp_dec_float 500 +(int)0.0935946 +cpp_dec_float 500 -(int)0.0950432 +cpp_dec_float 500 *(int)4.36195 +cpp_dec_float 500 /(int)24.4855 +cpp_dec_float 500 construct0.0306104 +cpp_dec_float 500 construct(unsigned)0.114772 +cpp_dec_float 500 construct(unsigned long long)0.117075 +cpp_dec_float 500 + 0.12407 +cpp_dec_float 500 - 0.122646 +cpp_dec_float 500 * 4.75508 +cpp_dec_float 500 / 25.1602 +cpp_dec_float 500 + 0.0865073 +cpp_dec_float 500 - 0.0929075 +cpp_dec_float 500 * 4.74128 +cpp_dec_float 500 / 25.1175 +mpfr_float 50 + 0.0624318 +mpfr_float 50 - 0.0764497 +mpfr_float 50 * 0.342248 +mpfr_float 50 / 1.69721 +mpfr_float 50 str 0.0289013 +mpfr_float 50 +(int)0.121683 +mpfr_float 50 -(int)0.149605 +mpfr_float 50 *(int)0.1548 +mpfr_float 50 /(int)0.213367 +mpfr_float 50 construct0.214552 +mpfr_float 50 construct(unsigned)0.293892 +mpfr_float 50 construct(unsigned long long)0.638307 +mpfr_float 50 + 0.553442 +mpfr_float 50 - 0.565687 +mpfr_float 50 * 0.841214 +mpfr_float 50 / 1.26072 +mpfr_float 50 + 0.537349 +mpfr_float 50 - 0.561924 +mpfr_float 50 * 0.833423 +mpfr_float 50 / 1.25318 +mpfr_float 100 + 0.0669494 +mpfr_float 100 - 0.0820912 +mpfr_float 100 * 0.478422 +mpfr_float 100 / 2.33995 +mpfr_float 100 str 0.0390764 +mpfr_float 100 +(int)0.117387 +mpfr_float 100 -(int)0.150557 +mpfr_float 100 *(int)0.166496 +mpfr_float 100 /(int)0.267439 +mpfr_float 100 construct0.222594 +mpfr_float 100 construct(unsigned)0.297568 +mpfr_float 100 construct(unsigned long long)0.643108 +mpfr_float 100 + 0.573918 +mpfr_float 100 - 0.592139 +mpfr_float 100 * 0.978674 +mpfr_float 100 / 1.5879 +mpfr_float 100 + 0.561143 +mpfr_float 100 - 0.580528 +mpfr_float 100 * 0.97887 +mpfr_float 100 / 1.58378 +mpfr_float 500 + 0.0817812 +mpfr_float 500 - 0.0975533 +mpfr_float 500 * 3.8308 +mpfr_float 500 / 13.8283 +mpfr_float 500 str 0.156188 +mpfr_float 500 +(int)0.129266 +mpfr_float 500 -(int)0.16446 +mpfr_float 500 *(int)0.273431 +mpfr_float 500 /(int)0.731526 +mpfr_float 500 construct0.222587 +mpfr_float 500 construct(unsigned)0.311108 +mpfr_float 500 construct(unsigned long long)0.653074 +mpfr_float 500 + 0.667956 +mpfr_float 500 - 0.684152 +mpfr_float 500 * 1.2661 +mpfr_float 500 / 7.46167 +mpfr_float 500 + 0.642822 +mpfr_float 500 - 0.65164 +mpfr_float 500 * 1.25714 +mpfr_float 500 / 7.46171 +[section:float_performance Float Type Perfomance] +[table Operator * +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.321363s)][1.0169 (0.574512s)][6.76401 (4.74128s)]] +[[gmp_float][1.7169 (0.551747s)][[*1] (0.564962s)][[*1] (0.700957s)]] +[[mpfr_float][2.5934 (0.833423s)][1.73263 (0.97887s)][1.79346 (1.25714s)]] +] +[table Operator *(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][5.56675 (0.234992s)][9.32996 (0.460635s)][50.8459 (4.36195s)]] +[[gmp_float][[*1] (0.0422135s)][[*1] (0.0493716s)][[*1] (0.0857876s)]] +[[mpfr_float][3.66707 (0.1548s)][3.37231 (0.166496s)][3.1873 (0.273431s)]] +] +[table Operator + +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0640148s)][[*1] (0.0708668s)][[*1] (0.0865073s)]] +[[gmp_float][7.467 (0.477999s)][6.72671 (0.476701s)][5.67136 (0.490614s)]] +[[mpfr_float][8.39413 (0.537349s)][7.91828 (0.561143s)][7.43085 (0.642822s)]] +] +[table Operator +(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.33358 (0.0441266s)][1.4433 (0.0558389s)][1.44838 (0.0935946s)]] +[[gmp_float][[*1] (0.0330888s)][[*1] (0.0386882s)][[*1] (0.0646201s)]] +[[mpfr_float][3.67747 (0.121683s)][3.03419 (0.117387s)][2.00041 (0.129266s)]] +] +[table Operator - +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0643402s)][[*1] (0.0730765s)][[*1] (0.0929075s)]] +[[gmp_float][7.76625 (0.499682s)][6.89067 (0.503546s)][5.89566 (0.547751s)]] +[[mpfr_float][8.73364 (0.561924s)][7.94411 (0.580528s)][7.01385 (0.65164s)]] +] +[table Operator -(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0442578s)][[*1] (0.0563278s)][[*1] (0.0950432s)]] +[[gmp_float][3.0379 (0.134451s)][2.39847 (0.1351s)][1.86101 (0.176876s)]] +[[mpfr_float][3.38031 (0.149605s)][2.67288 (0.150557s)][1.73037 (0.16446s)]] +] +[table Operator / +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][2.20938 (1.97464s)][3.71086 (3.83437s)][11.2059 (25.1175s)]] +[[gmp_float][[*1] (0.893752s)][[*1] (1.03328s)][[*1] (2.24146s)]] +[[mpfr_float][1.40216 (1.25318s)][1.53276 (1.58378s)][3.32895 (7.46171s)]] +] +[table Operator /(int) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][10.0596 (1.81469s)][15.5048 (3.62471s)][34.4767 (24.4855s)]] +[[gmp_float][[*1] (0.180393s)][[*1] (0.23378s)][[*1] (0.710204s)]] +[[mpfr_float][1.18279 (0.213367s)][1.14398 (0.267439s)][1.03002 (0.731526s)]] +] +[table Operator construct +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.00925753s)][[*1] (0.0263234s)][[*1] (0.0306104s)]] +[[gmp_float][21.32 (0.19737s)][7.4686 (0.196599s)][6.73181 (0.206063s)]] +[[mpfr_float][23.176 (0.214552s)][8.45613 (0.222594s)][7.27162 (0.222587s)]] +] +[table Operator construct(unsigned long long) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0587691s)][[*1] (0.076338s)][[*1] (0.117075s)]] +[[gmp_float][8.84863 (0.520025s)][6.80343 (0.51936s)][4.59554 (0.538021s)]] +[[mpfr_float][10.8613 (0.638307s)][8.42448 (0.643108s)][5.57826 (0.653074s)]] +] +[table Operator construct(unsigned) +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][[*1] (0.0588752s)][[*1] (0.0747853s)][[*1] (0.114772s)]] +[[gmp_float][3.53421 (0.208078s)][2.76875 (0.207062s)][1.89088 (0.217019s)]] +[[mpfr_float][4.99178 (0.293892s)][3.97896 (0.297568s)][2.71067 (0.311108s)]] +] +[table Operator str +[[Backend][50 Bits][100 Bits][500 Bits]] +[[cpp_dec_float][1.5616 (0.0207318s)][1.61725 (0.0328218s)][[*1] (0.131293s)]] +[[gmp_float][[*1] (0.013276s)][[*1] (0.0202949s)][1.07517 (0.141162s)]] +[[mpfr_float][2.17696 (0.0289013s)][1.92543 (0.0390764s)][1.18962 (0.156188s)]] +] +[endsect] +[section:integer_performance Integer Type Perfomance] +[table Operator % +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][5.31184 (0.37333s)][1.99944e+236 (0.673748s)][2.08204e+236 (0.701584s)][3.39405e+236 (1.14369s)]] +[[cpp_int(fixed)][1.10616 (0.0777437s)][5.8492e+235 (0.1971s)][9.91271e+235 (0.334027s)][1.60165e+236 (0.539708s)][-1.#INF (0.94847s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0702826s)]] +[[gmp_int][9.12715 (0.64148s)][2.088e+236 (0.703592s)][2.43295e+236 (0.819828s)][3.02578e+236 (1.01959s)]] +[[tommath_int][44.8434 (3.15171s)][1.21234e+237 (4.08522s)][1.69298e+237 (5.70483s)][3.7643e+237 (12.6845s)]] +] +[table Operator %(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][3.51789 (0.104856s)][-1.#INF (0.203012s)][-1.#INF (0.391566s)][-1.#INF (0.768511s)]] +[[cpp_int(fixed)][1.14548 (0.0341425s)][-1.#INF (0.103684s)][-1.#INF (0.200647s)][-1.#INF (0.377704s)][-1.#INF (0.743202s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0298064s)]] +[[gmp_int][1.91945 (0.0572117s)][-1.#INF (0.10258s)][-1.#INF (0.188529s)][-1.#INF (0.355222s)]] +[[tommath_int][71.0078 (2.11648s)][-1.#INF (2.74052s)][-1.#INF (3.96918s)][-1.#INF (9.09202s)]] +] +[table Operator & +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][12.079 (0.031605s)][-1.11772e+007 (0.0455929s)][-1.33961e+007 (0.0546439s)][-2.06875e+007 (0.0843863s)]] +[[cpp_int(fixed)][4.74538 (0.0124165s)][-8.36978e+006 (0.0341411s)][-1.22854e+007 (0.0501131s)][-1.4424e+007 (0.0588367s)][-1.#INF (0.0774574s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00261653s)]] +[[gmp_int][20.5664 (0.0538128s)][-1.59881e+007 (0.0652169s)][-2.25796e+007 (0.092104s)][-3.5403e+007 (0.144412s)]] +[[tommath_int][58.6685 (0.153508s)][-4.3241e+007 (0.176384s)][-4.47093e+007 (0.182373s)][-1.05347e+008 (0.429721s)]] +] +[table Operator &(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][23.3956 (0.0377678s)][-7.85844e+307 (0.0471524s)][-1.07843e+308 (0.0647085s)][-1.68143e+308 (0.10089s)]] +[[cpp_int(fixed)][6.49083 (0.0104782s)][-6.95612e+307 (0.0417383s)][-8.99012e+307 (0.0539427s)][-1.17371e+308 (0.070425s)][-1.#INF (0.112823s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00161431s)]] +[[gmp_int][87.5331 (0.141306s)][-1.#INF (0.139398s)][-1.#INF (0.142498s)][-1.#INF (0.141249s)]] +[[tommath_int][241.059 (0.389144s)][-1.#INF (0.389768s)][-1.#INF (0.40432s)][-1.#INF (0.653128s)]] +] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1715.93 (7.6372s)][-4.15607e+276 (7.7121s)][-4.16472e+276 (7.72815s)][-4.23791e+276 (7.86395s)]] +[[cpp_int(fixed)][1.27579 (0.00567824s)][-3.62916e+274 (0.0673436s)][-5.78275e+274 (0.107306s)][-9.2595e+274 (0.171821s)][-1.#INF (0.299236s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00445077s)]] +[[gmp_int][710.595 (3.1627s)][-1.69816e+276 (3.15114s)][-1.70883e+276 (3.17094s)][-1.7293e+276 (3.20893s)]] +[[tommath_int][4171.01 (18.5642s)][-1.00365e+277 (18.624s)][-1.01017e+277 (18.745s)][-1.02906e+277 (19.0954s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.97316 (0.0235876s)][1.#INF (0.0318939s)][1.#INF (0.0427792s)][1.#INF (0.0668616s)]] +[[cpp_int(fixed)][2.32007 (0.00548722s)][1.#INF (0.0328109s)][1.#INF (0.049867s)][1.#INF (0.0658566s)][-1.#INF (0.0948565s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00236511s)]] +[[gmp_int][9.62157 (0.022756s)][1.#INF (0.0282672s)][1.#INF (0.0361075s)][1.#INF (0.0518882s)]] +[[tommath_int][103.969 (0.245897s)][1.#INF (0.26894s)][1.#INF (0.31746s)][1.#INF (0.408933s)]] +] +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.74543 (0.0196594s)][3.98952e+276 (0.0215291s)][4.2355e+276 (0.0228565s)][4.21393e+276 (0.0227402s)]] +[[cpp_int(fixed)][2.13187 (0.00430062s)][3.11951e+276 (0.0168342s)][3.15933e+276 (0.0170491s)][3.19893e+276 (0.0172628s)][-1.#INF (0.0181245s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0020173s)]] +[[gmp_int][337.759 (0.68136s)][1.27731e+278 (0.68929s)][1.28647e+278 (0.694235s)][1.27865e+278 (0.690013s)]] +[[tommath_int][253.115 (0.510608s)][9.75089e+277 (0.526199s)][1.00638e+278 (0.543084s)][1.05311e+278 (0.568301s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.81588 (0.0159069s)][-5.71737e+244 (0.0218386s)][-8.2882e+244 (0.0316584s)][-1.1265e+245 (0.0430289s)]] +[[cpp_int(fixed)][3.92617 (0.00636247s)][-7.02443e+244 (0.0268311s)][-1.07535e+245 (0.0410749s)][-1.37293e+245 (0.0524416s)][-1.#INF (0.0728817s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00162053s)]] +[[gmp_int][19.2059 (0.0311237s)][-1.12054e+245 (0.0428011s)][-1.74239e+245 (0.0665539s)][-2.83458e+245 (0.108272s)]] +[[tommath_int][126.815 (0.205506s)][-5.54618e+245 (0.211847s)][-5.95413e+245 (0.227429s)][-6.55751e+245 (0.250477s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][11.0409 (0.0210968s)][3.86227e+276 (0.0213343s)][4.03471e+276 (0.0222868s)][4.24576e+276 (0.0234526s)]] +[[cpp_int(fixed)][2.02836 (0.00387577s)][3.06763e+276 (0.0169449s)][3.2004e+276 (0.0176783s)][3.27232e+276 (0.0180756s)][-1.#INF (0.0190581s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00191079s)]] +[[gmp_int][356.496 (0.681187s)][1.23744e+278 (0.683532s)][1.2536e+278 (0.69246s)][1.25066e+278 (0.690838s)]] +[[tommath_int][272.651 (0.520979s)][9.54925e+277 (0.527479s)][9.69283e+277 (0.535411s)][9.94446e+277 (0.54931s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][9.24378 (0.0151244s)][-1.01975e-199 (0.017199s)][-1.47092e-199 (0.0248084s)][-1.96387e-199 (0.0331224s)]] +[[cpp_int(fixed)][4.08494 (0.00668367s)][-1.43394e-199 (0.0241848s)][-2.18373e-199 (0.0368306s)][-2.98469e-199 (0.0503396s)][-1.#INF (0.0621059s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00163617s)]] +[[gmp_int][18.693 (0.030585s)][-2.37422e-199 (0.0400434s)][-3.42818e-199 (0.0578194s)][-5.96116e-199 (0.100541s)]] +[[tommath_int][124.161 (0.203148s)][-1.22425e-198 (0.206481s)][-1.30439e-198 (0.219998s)][-1.40639e-198 (0.2372s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.96346 (0.0578293s)][-1.51814e+061 (0.0615507s)][-1.8062e+061 (0.0732298s)][-3.04778e+061 (0.123568s)]] +[[cpp_int(fixed)][1.08704 (0.0320162s)][-8.07606e+060 (0.0327432s)][-8.40351e+060 (0.0340708s)][-1.09735e+061 (0.0444905s)][-1.#INF (0.106788s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0294528s)]] +[[gmp_int][23.2741 (0.685487s)][-1.70068e+062 (0.689516s)][-1.6994e+062 (0.688995s)][-1.74523e+062 (0.707578s)]] +[[tommath_int][38.4876 (1.13357s)][-2.76443e+062 (1.1208s)][-2.83854e+062 (1.15084s)][-2.98853e+062 (1.21165s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][7.87676 (0.235955s)][1.#INF (0.35212s)][1.#INF (0.568032s)][1.#INF (0.989885s)]] +[[cpp_int(fixed)][1.21173 (0.0362985s)][1.#INF (0.137619s)][1.#INF (0.253796s)][1.#INF (0.446782s)][-1.#INF (0.84764s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0299559s)]] +[[gmp_int][1.87075 (0.0560401s)][1.#INF (0.0982823s)][1.#INF (0.183564s)][1.#INF (0.352238s)]] +[[tommath_int][69.4504 (2.08045s)][1.#INF (2.7099s)][1.#INF (4.1339s)][1.#INF (9.04346s)]] +] +[table Operator << +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][15.849 (0.0256107s)][-5.85461e+126 (0.0401135s)][-6.36621e+126 (0.0436188s)][-9.17366e+126 (0.0628544s)]] +[[cpp_int(fixed)][3.19639 (0.00516511s)][-4.68379e+126 (0.0320915s)][-7.40049e+126 (0.0507053s)][-8.72078e+126 (0.0597514s)][-1.#INF (0.0677088s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00161592s)]] +[[gmp_int][16.956 (0.0273994s)][-4.66649e+126 (0.031973s)][-6.88464e+126 (0.0471709s)][-1.05374e+127 (0.0721984s)]] +[[tommath_int][25.259 (0.0408165s)][-1.01897e+127 (0.0698155s)][-1.42104e+127 (0.0973643s)][-2.4416e+127 (0.167289s)]] +] +[table Operator >> +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][14.6983 (0.0237523s)][-2.28921e+307 (0.0302534s)][-2.68808e+307 (0.0355247s)][-3.38364e+307 (0.044717s)]] +[[cpp_int(fixed)][2.47217 (0.00399499s)][-2.21749e+307 (0.0293055s)][-2.9515e+307 (0.039006s)][-3.9023e+307 (0.0515714s)][-1.#INF (0.0626121s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00161599s)]] +[[gmp_int][17.8366 (0.0288237s)][-2.3471e+307 (0.0310184s)][-2.55387e+307 (0.0337511s)][-2.9362e+307 (0.0388038s)]] +[[tommath_int][200.597 (0.324163s)][-1.#INF (0.383757s)][-1.#INF (0.398354s)][-1.#INF (0.570323s)]] +] +[table Operator ^ +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][7.95372 (0.0318172s)][1.21131 (0.0425243s)][1.02246 (0.0542436s)][1.19877 (0.08333s)]] +[[cpp_int(fixed)][2.75762 (0.0110313s)][[*1] (0.0351059s)][[*1] (0.0530521s)][[*1] (0.0695132s)][-1.#INF (0.09783s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.0040003s)]] +[[gmp_int][12.4289 (0.0497194s)][1.79507 (0.0630174s)][1.63955 (0.0869819s)][2.0012 (0.139109s)]] +[[tommath_int][38.4798 (0.153931s)][4.9051 (0.172198s)][3.45761 (0.183434s)][6.17837 (0.429478s)]] +] +[table Operator ^(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][15.3547 (0.0283305s)][-8.92021e+307 (0.0353555s)][-1.05356e+308 (0.041758s)][-1.35819e+308 (0.0538323s)]] +[[cpp_int(fixed)][5.81005 (0.0107199s)][-7.88073e+307 (0.0312355s)][-1.20328e+308 (0.0476923s)][-1.36485e+308 (0.0540962s)][-1.#INF (0.0806317s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00184507s)]] +[[gmp_int][78.0102 (0.143934s)][-1.#INF (0.144825s)][-1.#INF (0.152773s)][-1.#INF (0.161662s)]] +[[tommath_int][202.867 (0.374303s)][-1.#INF (0.379255s)][-1.#INF (0.390434s)][-1.#INF (0.62285s)]] +] +[table Operator construct +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.64088 (0.00293927s)][1.47161e+238 (0.00277479s)][1.49039e+238 (0.0028102s)][1.47064e+238 (0.00277298s)]] +[[cpp_int(fixed)][1.45325 (0.00161745s)][8.73297e+237 (0.00164665s)][1.92709e+238 (0.00363363s)][3.0576e+238 (0.00576526s)][-1.#INF (0.00535599s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00111299s)]] +[[gmp_int][176.266 (0.196182s)][1.06706e+240 (0.201199s)][1.04919e+240 (0.19783s)][1.04712e+240 (0.19744s)]] +[[tommath_int][186.394 (0.207455s)][1.10319e+240 (0.208012s)][1.09052e+240 (0.205622s)][1.09982e+240 (0.207377s)]] +] +[table Operator construct(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][3.51152 (0.00719854s)][-2.80497e-148 (0.00725455s)][-2.79893e-148 (0.00723891s)][-2.83336e-148 (0.00732796s)]] +[[cpp_int(fixed)][[*1] (0.00204998s)][-1.21019e-148 (0.00312994s)][-1.50065e-148 (0.00388115s)][-2.15185e-148 (0.00556537s)][-1.#INF (0.00577713s)]] +[[cpp_int(unsigned, fixed)][1.17501 (0.00240876s)]] +[[gmp_int][351.097 (0.719741s)][-2.82056e-146 (0.729487s)][-2.80186e-146 (0.724649s)][-2.79263e-146 (0.722262s)]] +[[tommath_int][346.109 (0.709516s)][-2.74152e-146 (0.709045s)][-2.72155e-146 (0.703879s)][-2.75662e-146 (0.712949s)]] +] +[table Operator construct(unsigned) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][2.44987 (0.00270684s)][1.90974 (0.0030529s)][[*1] (0.00288857s)][[*1] (0.00265201s)]] +[[cpp_int(fixed)][1.89292 (0.00209147s)][[*1] (0.0015986s)][1.28253 (0.00370466s)][2.19414 (0.0058189s)][-1.#INF (0.00836042s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00110489s)]] +[[gmp_int][186.546 (0.206113s)][132.175 (0.211295s)][71.6424 (0.206944s)][81.5339 (0.216229s)]] +[[tommath_int][432.596 (0.477971s)][294.478 (0.470752s)][164.029 (0.473807s)][179.394 (0.475755s)]] +] +[table Operator gcd +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][8.27321 (4.98644s)][-1.#INF (11.1816s)][-1.#INF (27.2257s)][-1.#INF (73.3735s)]] +[[cpp_int(fixed)][1.0026 (0.604291s)][-1.#INF (4.18006s)][-1.#INF (10.2671s)][-1.#INF (26.2762s)][-1.#INF (76.2849s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.602722s)]] +[[gmp_int][4.06647 (2.45095s)][-1.#INF (5.89505s)][-1.#INF (13.6993s)][-1.#INF (33.2232s)]] +[[tommath_int][20.7927 (12.5322s)][-1.#INF (26.1755s)][-1.#INF (56.7747s)][-1.#INF (132.299s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][1.02246 (0.00189808s)][-3.42215e+178 (0.00391656s)][-7.26989e+178 (0.00832019s)][-1.93625e+179 (0.0221599s)]] +[[cpp_int(fixed)][1.35564 (0.00251659s)][-1.36421e+178 (0.0015613s)][-2.59752e+178 (0.00297279s)][-6.18963e+178 (0.00708386s)][-1.#INF (0.0172514s)]] +[[cpp_int(unsigned, fixed)][1.38149 (0.00256457s)]] +[[gmp_int][[*1] (0.00185638s)][-3.01078e+178 (0.00344576s)][-5.40339e+178 (0.00618403s)][-1.26279e+179 (0.0144523s)]] +[[tommath_int][9.43586 (0.0175165s)][-3.57438e+179 (0.0409078s)][-9.73304e+179 (0.111392s)][-3.02201e+180 (0.345861s)]] +] +[table Operator | +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][11.6542 (0.030991s)][-6.48076e+046 (0.0429658s)][-8.11261e+046 (0.0537846s)][-1.24844e+047 (0.0827684s)]] +[[cpp_int(fixed)][4.09831 (0.0108982s)][-5.73378e+046 (0.0380136s)][-7.98794e+046 (0.0529581s)][-1.02098e+047 (0.0676884s)][-1.#INF (0.100936s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00265921s)]] +[[gmp_int][17.8503 (0.0474678s)][-9.32586e+046 (0.0618281s)][-1.29209e+047 (0.0856626s)][-2.0526e+047 (0.136082s)]] +[[tommath_int][57.6991 (0.153434s)][-2.5656e+047 (0.170093s)][-2.70121e+047 (0.179084s)][-6.58529e+047 (0.436588s)]] +] +[table Operator |(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_int][16.9457 (0.0280516s)][-4.17523e+307 (0.0363929s)][-4.79721e+307 (0.0418143s)][-6.04694e+307 (0.0527075s)]] +[[cpp_int(fixed)][6.70551 (0.0111002s)][-3.64663e+307 (0.0317854s)][-5.35725e+307 (0.0466958s)][-6.16052e+307 (0.0536974s)][-1.#INF (0.0819107s)]] +[[cpp_int(unsigned, fixed)][[*1] (0.00165538s)]] +[[gmp_int][85.2488 (0.141119s)][-1.64044e+308 (0.142987s)][-1.78579e+308 (0.155656s)][-1.#INF (0.163236s)]] +[[tommath_int][227.544 (0.376671s)][-1.#INF (0.375206s)][-1.#INF (0.381428s)][-1.#INF (0.622404s)]] +] +[endsect] +[section:rational_performance Rational Type Perfomance] +[table Operator * +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][6.20279 (57.9393s)][6.23608 (59.3172s)][6.25071 (61.8998s)][6.44097 (67.4139s)]] +[[mpq_rational][[*1] (9.34086s)][[*1] (9.51195s)][[*1] (9.90285s)][[*1] (10.4664s)]] +] +[table Operator *(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][2.06502 (2.4377s)][2.38344 (2.91325s)][2.86734 (3.94768s)][3.8554 (5.87507s)]] +[[mpq_rational][[*1] (1.18047s)][[*1] (1.22229s)][[*1] (1.37678s)][[*1] (1.52386s)]] +] +[table Operator + +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.1513 (2.68363s)][1.31207 (3.15142s)][1.61685 (4.05684s)][2.18092 (5.80438s)]] +[[mpq_rational][[*1] (2.33097s)][[*1] (2.40187s)][[*1] (2.5091s)][[*1] (2.66144s)]] +] +[table Operator +(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][3.69962 (2.47739s)][4.12788 (2.92179s)][4.67839 (3.80252s)][6.08526 (5.51612s)]] +[[mpq_rational][[*1] (0.669634s)][[*1] (0.707818s)][[*1] (0.812783s)][[*1] (0.906471s)]] +] +[table Operator - +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.17746 (2.72926s)][1.334 (3.19882s)][1.63017 (4.08474s)][2.21829 (5.86s)]] +[[mpq_rational][[*1] (2.31793s)][[*1] (2.39792s)][[*1] (2.50572s)][[*1] (2.64168s)]] +] +[table Operator -(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][3.71756 (2.47959s)][4.04045 (2.90579s)][4.69474 (3.80714s)][6.07677 (5.51949s)]] +[[mpq_rational][[*1] (0.666993s)][[*1] (0.719174s)][[*1] (0.810939s)][[*1] (0.908293s)]] +] +[table Operator / +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.95741 (58.0332s)][6.16582 (59.5431s)][6.19235 (61.9712s)][6.31439 (67.4254s)]] +[[mpq_rational][[*1] (9.74135s)][[*1] (9.65697s)][[*1] (10.0077s)][[*1] (10.6781s)]] +] +[table Operator /(int) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][1.75198 (2.50843s)][2.05836 (3.00689s)][2.45339 (4.00588s)][3.31983 (5.92837s)]] +[[mpq_rational][[*1] (1.43177s)][[*1] (1.46082s)][[*1] (1.6328s)][[*1] (1.78575s)]] +] +[table Operator construct +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.0102665s)][[*1] (0.0101737s)][[*1] (0.0101965s)][[*1] (0.0102909s)]] +[[mpq_rational][37.3164 (0.383107s)][37.5023 (0.381537s)][37.4005 (0.381355s)][37.2621 (0.383461s)]] +] +[table Operator construct(unsigned long long) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.0658436s)][[*1] (0.0665504s)][[*1] (0.0659082s)][[*1] (0.0659089s)]] +[[mpq_rational][32.3771 (2.13183s)][31.9648 (2.12727s)][32.1342 (2.1179s)][32.2079 (2.12279s)]] +] +[table Operator construct(unsigned) +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][[*1] (0.0624887s)][[*1] (0.0609531s)][[*1] (0.0613968s)][[*1] (0.062674s)]] +[[mpq_rational][6.31396 (0.394551s)][6.41455 (0.390987s)][6.38973 (0.392309s)][6.27858 (0.393504s)]] +] +[table Operator str +[[Backend][128 Bits][256 Bits][512 Bits][1024 Bits]] +[[cpp_rational][5.4954 (0.020339s)][9.02403 (0.0517328s)][9.75685 (0.119248s)][9.80346 (0.286067s)]] +[[mpq_rational][[*1] (0.0037011s)][[*1] (0.00573278s)][[*1] (0.012222s)][[*1] (0.0291802s)]] +] +[endsect] diff --git a/performance/performance_test.cpp b/performance/performance_test.cpp new file mode 100644 index 00000000..fe21b2b8 --- /dev/null +++ b/performance/performance_test.cpp @@ -0,0 +1,852 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#define BOOST_CHRONO_HEADER_ONLY + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#if !defined(TEST_MPF) && !defined(TEST_MPZ) && \ + !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPQ) \ + && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\ + && !defined(TEST_CPP_INT) && !defined(TEST_CPP_INT_RATIONAL) +# define TEST_MPF +# define TEST_MPZ +# define TEST_MPQ +# define TEST_MPFR +# define TEST_CPP_DEC_FLOAT +# define TEST_MPQ +# define TEST_TOMMATH +# define TEST_CPP_INT +# define TEST_CPP_INT_RATIONAL + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF) || defined(TEST_MPZ) || defined(TEST_MPQ) || defined(TEST_MPZ_BOOST_RATIONAL) +#include +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif +#if defined(TEST_MPFR) +#include +#endif +#if defined(TEST_TOMMATH) || defined(TEST_TOMMATH_BOOST_RATIONAL) +#include +#include +#endif +#if defined(TEST_CPP_INT) || defined(TEST_CPP_INT_RATIONAL) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; + +unsigned bits_wanted; // for integer types + +namespace boost{ namespace multiprecision{ + +template<> +class number_category : public mpl::int_{}; +template<> +class number_category : public mpl::int_{}; + +}} + +template +struct tester +{ + tester() + { + a.assign(500, 0); + for(int i = 0; i < 500; ++i) + { + b.push_back(generate_random()); + c.push_back(generate_random()); + small.push_back(gen()); + } + } + double test_add() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] + c[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_subtract() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] - c[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_add_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] + 1; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_subtract_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] - 1; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_multiply() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned k = 0; k < b.size(); ++k) + a[k] = b[k] * c[k]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_multiply_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] * 3; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_divide() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] / c[i] + b[i] / small[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_divide_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] / 3; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_str(const boost::mpl::false_&) + { + stopwatch w; + for(unsigned i = 0; i < b.size(); ++i) + a[i] = boost::lexical_cast(boost::lexical_cast(b[i])); + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_str(const boost::mpl::true_&) + { + stopwatch w; + for(unsigned i = 0; i < b.size(); ++i) + a[i].assign(b[i].str()); + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_str() + { + return test_str(boost::is_class()); + } + // + // The following tests only work for integer types: + // + double test_mod() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] % c[i] + b[i] % small[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_mod_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] % 254; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_or() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] | c[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_or_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] | 234; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_and() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] & c[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_and_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] & 234; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_xor() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] ^ c[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_xor_int() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] ^ 234; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_complement() + { + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = ~b[i]; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_left_shift() + { + int shift = std::numeric_limits::is_bounded ? std::numeric_limits::digits : bits_wanted; + shift /= 2; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] << shift; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_right_shift() + { + int shift = std::numeric_limits::is_bounded ? std::numeric_limits::digits : bits_wanted; + shift /= 2; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] >> shift; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_gcd() + { + using boost::math::gcd; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = gcd(b[i], c[i]); + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_powm() + { + stopwatch w; + for(unsigned i = 0; i < 25; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = powm(b[i], b[i] / 2, c[i]); + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + double test_construct() + { + std::allocator a; + T* pt = a.allocate(1000); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < 1000; ++i) + new(pt+i) T(); + for(unsigned i = 0; i < 1000; ++i) + a.destroy(pt+i); + } + double result = boost::chrono::duration_cast >(w.elapsed()).count(); + a.deallocate(pt, 1000); + return result; + } + double test_construct_unsigned() + { + std::allocator a; + T* pt = a.allocate(1000); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < 1000; ++i) + new(pt+i) T(i); + for(unsigned i = 0; i < 1000; ++i) + a.destroy(pt+i); + } + double result = boost::chrono::duration_cast >(w.elapsed()).count(); + a.deallocate(pt, 1000); + return result; + } + double test_construct_unsigned_ll() + { + std::allocator a; + T* pt = a.allocate(1000); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned long long j = 0; j < 1000; ++j) + new(pt+j) T(j); + for(unsigned j = 0; j < 1000; ++j) + a.destroy(pt+j); + } + double result = boost::chrono::duration_cast >(w.elapsed()).count(); + a.deallocate(pt, 1000); + return result; + } + + // + // Hetero operations: + // + template + static U get_hetero_test_value(boost::mpl::false_ const&) + { + return U(2) / 3; + } + template + static U get_hetero_test_value(boost::mpl::true_ const&) + { + return (std::numeric_limits::max)() >> 4; + } + template + static U get_hetero_test_value() + { + return get_hetero_test_value(boost::is_integral()); + } + template + double test_multiply_hetero() + { + static const U val = get_hetero_test_value(); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] * val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_inplace_multiply_hetero() + { + static const U val = get_hetero_test_value(); + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i]; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] *= val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_add_hetero() + { + static const U val = get_hetero_test_value(); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] + val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_inplace_add_hetero() + { + static const U val = get_hetero_test_value(); + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i]; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] += val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_subtract_hetero() + { + static const U val = get_hetero_test_value(); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] - val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_inplace_subtract_hetero() + { + static const U val = get_hetero_test_value(); + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i]; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] -= val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_divide_hetero() + { + static const U val = get_hetero_test_value(); + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i] / val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } + template + double test_inplace_divide_hetero() + { + static const U val = get_hetero_test_value(); + for(unsigned i = 0; i < b.size(); ++i) + a[i] = b[i]; + stopwatch w; + for(unsigned i = 0; i < 1000; ++i) + { + for(unsigned i = 0; i < b.size(); ++i) + a[i] /= val; + } + return boost::chrono::duration_cast >(w.elapsed()).count(); + } +private: + T generate_random() + { + return generate_random(boost::mpl::int_()); + } + T generate_random(const boost::mpl::int_&) + { + T val = gen(); + T prev_val = -1; + while(val != prev_val) + { + val *= (gen.max)(); + prev_val = val; + val += gen(); + } + int e; + val = frexp(val, &e); + + typedef typename T::backend_type::exponent_type e_type; + static boost::random::uniform_int_distribution ui(-30, 30); + return ldexp(val, static_cast(ui(gen))); + } + T generate_random(const boost::mpl::int_&) + { + typedef boost::random::mt19937::result_type random_type; + + T max_val; + unsigned digits; + if(std::numeric_limits::is_bounded) + { + max_val = (std::numeric_limits::max)(); + digits = std::numeric_limits::digits; + } + else + { + max_val = T(1) << bits_wanted; + digits = bits_wanted; + } + + unsigned bits_per_r_val = std::numeric_limits::digits - 1; + while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; + + unsigned terms_needed = digits / bits_per_r_val + 1; + + T val = 0; + for(unsigned i = 0; i < terms_needed; ++i) + { + val *= (gen.max)(); + val += gen(); + } + val %= max_val; + return val; + } + T generate_random(const boost::mpl::int_&) + { + typedef boost::random::mt19937::result_type random_type; + typedef typename boost::multiprecision::component_type::type IntType; + + IntType max_val; + unsigned digits; + if(std::numeric_limits::is_bounded) + { + max_val = (std::numeric_limits::max)(); + digits = std::numeric_limits::digits; + } + else + { + max_val = IntType(1) << bits_wanted; + digits = bits_wanted; + } + + unsigned bits_per_r_val = std::numeric_limits::digits - 1; + while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; + + unsigned terms_needed = digits / bits_per_r_val + 1; + + IntType val = 0; + IntType denom = 0; + for(unsigned i = 0; i < terms_needed; ++i) + { + val *= (gen.max)(); + val += gen(); + } + for(unsigned i = 0; i < terms_needed; ++i) + { + denom *= (gen.max)(); + denom += gen(); + } + if(denom == 0) + denom = 1; + val %= max_val; + denom %= max_val; + return T(val, denom); + } + std::vector a, b, c, small; + static boost::random::mt19937 gen; +}; + +template +boost::random::mt19937 tester::gen; + +const char* category_name(const boost::mpl::int_&) +{ + return "integer"; +} +const char* category_name(const boost::mpl::int_&) +{ + return "float"; +} +const char* category_name(const boost::mpl::int_&) +{ + return "rational"; +} + +// +// Keys in order are: +// Category +// Operator +// Type +// Precision +// Time +// +std::map > > > result_table; + +void report_result(const char* cat, const char* type, const char* op, unsigned precision, double time) +{ + std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(35) << op << time << std::endl; + result_table[cat][op][type][precision] = time; +} + +template +void test_int_ops(tester& t, const char* type, unsigned precision, const boost::mpl::int_&) +{ + const char* cat = "integer"; + report_result(cat, type, "%", precision, t.test_mod()); + report_result(cat, type, "|", precision, t.test_or()); + report_result(cat, type, "&", precision, t.test_and()); + report_result(cat, type, "^", precision, t.test_xor()); + //report_result(cat, type, "~", precision, t.test_complement()); + report_result(cat, type, "<<", precision, t.test_left_shift()); + report_result(cat, type, ">>", precision, t.test_right_shift()); + // integer ops: + report_result(cat, type, "%(int)", precision, t.test_mod_int()); + report_result(cat, type, "|(int)", precision, t.test_or_int()); + report_result(cat, type, "&(int)", precision, t.test_and_int()); + report_result(cat, type, "^(int)", precision, t.test_xor_int()); + report_result(cat, type, "gcd", precision, t.test_gcd()); + report_result(cat, type, "powm", precision, t.test_powm()); +} +template +void test_int_ops(tester& t, const char* type, unsigned precision, const U&) +{ +} + +template +void test(const char* type, unsigned precision) +{ + bits_wanted = precision; + tester::value> t; + const char* cat = category_name(typename boost::multiprecision::number_category::type()); + // + // call t.test_multiply() first so that the destination operands are + // forced to perform whatever memory allocation may be needed. That way + // we measure only algorithm performance, and not memory allocation effects. + // + t.test_multiply(); + // + // Now the actual tests: + // + report_result(cat, type, "+", precision, t.test_add()); + report_result(cat, type, "-", precision, t.test_subtract()); + report_result(cat, type, "*", precision, t.test_multiply()); + report_result(cat, type, "/", precision, t.test_divide()); + report_result(cat, type, "str", precision, t.test_str()); + // integer ops: + report_result(cat, type, "+(int)", precision, t.test_add_int()); + report_result(cat, type, "-(int)", precision, t.test_subtract_int()); + report_result(cat, type, "*(int)", precision, t.test_multiply_int()); + report_result(cat, type, "/(int)", precision, t.test_divide_int()); + // construction and destruction: + report_result(cat, type, "construct", precision, t.test_construct()); + report_result(cat, type, "construct(unsigned)", precision, t.test_construct_unsigned()); + report_result(cat, type, "construct(unsigned long long)", precision, t.test_construct_unsigned_ll()); + test_int_ops(t, type, precision, typename boost::multiprecision::number_category::type()); + // Hetero ops: + report_result(cat, type, "+(unsigned long long)", precision, t.template test_add_hetero()); + report_result(cat, type, "-(unsigned long long)", precision, t.template test_subtract_hetero()); + report_result(cat, type, "*(unsigned long long)", precision, t.template test_multiply_hetero()); + report_result(cat, type, "/(unsigned long long)", precision, t.template test_divide_hetero()); + report_result(cat, type, "+=(unsigned long long)", precision, t.template test_inplace_add_hetero()); + report_result(cat, type, "-=(unsigned long long)", precision, t.template test_inplace_subtract_hetero()); + report_result(cat, type, "*=(unsigned long long)", precision, t.template test_inplace_multiply_hetero()); + report_result(cat, type, "/=(unsigned long long)", precision, t.template test_inplace_divide_hetero()); +} + +void quickbook_results() +{ + // + // Keys in order are: + // Category + // Operator + // Type + // Precision + // Time + // + typedef std::map > > >::const_iterator category_iterator; + typedef std::map > >::const_iterator operator_iterator; + typedef std::map >::const_iterator type_iterator; + typedef std::map::const_iterator precision_iterator; + + for(category_iterator i = result_table.begin(); i != result_table.end(); ++i) + { + std::string cat = i->first; + cat[0] = std::toupper(cat[0]); + std::cout << "[section:" << i->first << "_performance " << cat << " Type Perfomance]" << std::endl; + + for(operator_iterator j = i->second.begin(); j != i->second.end(); ++j) + { + std::string op = j->first; + std::cout << "[table Operator " << op << std::endl; + std::cout << "[[Backend]"; + + for(precision_iterator k = j->second.begin()->second.begin(); k != j->second.begin()->second.end(); ++k) + { + std::cout << "[" << k->first << " Bits]"; + } + std::cout << "]\n"; + + std::vector best_times(j->second.begin()->second.size(), (std::numeric_limits::max)()); + for(unsigned m = 0; m < j->second.begin()->second.size(); ++m) + { + for(type_iterator k = j->second.begin(); k != j->second.end(); ++k) + { + precision_iterator l = k->second.begin(); + std::advance(l, m); + if(best_times[m] > l->second) + best_times[m] = l->second ? l->second : best_times[m]; + } + } + + for(type_iterator k = j->second.begin(); k != j->second.end(); ++k) + { + std::cout << "[[" << k->first << "]"; + + unsigned m = 0; + for(precision_iterator l = k->second.begin(); l != k->second.end(); ++l) + { + double rel_time = l->second / best_times[m]; + if(rel_time == 1) + std::cout << "[[*" << rel_time << "]"; + else + std::cout << "[" << rel_time; + std::cout << " (" << l->second << "s)]"; + ++m; + } + + std::cout << "]\n"; + } + + std::cout << "]\n"; + } + + std::cout << "[endsect]" << std::endl; + } +} + + +int main() +{ +#ifdef TEST_INT64 + test("boost::uint64_t", 64); +#endif +#ifdef TEST_MPF + test("gmp_float", 50); + test("gmp_float", 100); + test("gmp_float", 500); +#endif +#ifdef TEST_MPZ + test("gmp_int", 128); + test("gmp_int", 256); + test("gmp_int", 512); + test("gmp_int", 1024); +#endif +#ifdef TEST_CPP_INT + //test, boost::multiprecision::et_off> >("cpp_int(unsigned, fixed)", 64); + //test, boost::multiprecision::et_off> >("cpp_int(fixed)", 64); + test, boost::multiprecision::et_off> >("cpp_int(fixed)", 128); + test, boost::multiprecision::et_off> >("cpp_int(fixed)", 256); + test, boost::multiprecision::et_off> >("cpp_int(fixed)", 512); + test, boost::multiprecision::et_off> >("cpp_int(fixed)", 1024); + + test("cpp_int", 128); + test("cpp_int", 256); + test("cpp_int", 512); + test("cpp_int", 1024); +#endif +#ifdef TEST_CPP_INT_RATIONAL + test("cpp_rational", 128); + test("cpp_rational", 256); + test("cpp_rational", 512); + test("cpp_rational", 1024); +#endif +#ifdef TEST_MPQ + test("mpq_rational", 128); + test("mpq_rational", 256); + test("mpq_rational", 512); + test("mpq_rational", 1024); +#endif +#ifdef TEST_TOMMATH + test("tommath_int", 128); + test("tommath_int", 256); + test("tommath_int", 512); + test("tommath_int", 1024); + /* + // + // These are actually too slow to test!!! + // + test("tom_rational", 128); + test("tom_rational", 256); + test("tom_rational", 512); + test("tom_rational", 1024); + */ +#endif +#ifdef TEST_CPP_DEC_FLOAT + test("cpp_dec_float", 50); + test("cpp_dec_float", 100); + test > >("cpp_dec_float", 500); +#endif +#ifdef TEST_MPFR + test("mpfr_float", 50); + test("mpfr_float", 100); + test("mpfr_float", 500); +#endif + quickbook_results(); + return 0; +} + diff --git a/performance/sf_performance-msvc-10.log b/performance/sf_performance-msvc-10.log new file mode 100644 index 00000000..9dc8de7b --- /dev/null +++ b/performance/sf_performance-msvc-10.log @@ -0,0 +1,69 @@ +0 +11 +24 +3 +13 +27 +Testing Bessel Functions..... +Time for mpfr_float_50 = 6.47208 seconds +Total allocations for mpfr_float_50 = 2684348 +Time for mpf_float_50 = 11.6627 seconds +Total allocations for mpf_float_50 = 2601366 +Time for cpp_float_50 = 20.2855 seconds +Total allocations for cpp_float_50 = 0 +Time for mpfr_class (50 digits) = 6.48063 seconds +Total allocations for mpfr_class (50 digits) = 3946031 +Time for mpreal (50 digits) = 9.98151 seconds +Total allocations for mpreal (50 digits) = 13223017 +Time for mpfr_float_100 = 10.154 seconds +Total allocations for mpfr_float_50 = 3671485 +Time for mpf_float_100 = 8.51179 seconds +Total allocations for mpf_float_100 = 3593669 +Time for cpp_float_100 = 21.0198 seconds +Total allocations for cpp_float_100 = 0 +Time for mpfr_class (100 digits) = 9.80571 seconds +Total allocations for mpfr_class (100 digits) = 5447348 +Time for mpreal (100 digits) = 13.7021 seconds +Total allocations for mpreal (100 digits) = 16671065 +Testing Polynomial Evaluation..... +Time for mpfr_float_50 = 0.00823841 seconds +Total allocations for mpfr_float_50 = 2996 +Time for mpf_float_50 = 0.00401608 seconds +Total allocations for mpf_float_50 = 2996 +Time for cpp_float_50 = 0.00492116 seconds +Total allocations for cpp_float_50 = 0 +Time for mpfr_class (50 digits) = 0.00935629 seconds +Total allocations for mpfr_class (50 digits) = 12976 +Time for mpreal (50 digits) = 0.0148374 seconds +Total allocations for mpreal (50 digits = 27947 +Time for mpfr_float_100 = 0.00948452 seconds +Total allocations for mpfr_float_100 = 2996 +Time for mpf_float_100 = 0.00390071 seconds +Total allocations for mpf_float_100 = 2996 +Time for cpp_float_100 = 0.00893563 seconds +Total allocations for cpp_float_100 = 0 +Time for mpfr_class (100 digits) = 0.0106166 seconds +Total allocations for mpfr_class (100 digits) = 12976 +Time for mpreal (100 digits) = 0.0162364 seconds +Total allocations for mpreal (100 digits) = 27947 +Testing Non-Central T..... +Time for mpfr_float_50 = 258.087 seconds +Total allocations for mpfr_float_50 = 139149049 +Time for mpf_float_50 = 197.303 seconds +Total allocations for mpf_float_50 = 134600354 +Time for cpp_float_50 = 334.503 seconds +Total allocations for cpp_float_50 = 0 +Time for mpfr_class (50 digits) = 266.389 seconds +Total allocations for mpfr_class (50 digits) = 252401115 +Time for mpreal (50 digits) = 346.641 seconds +Total allocations for mpreal (50 digits) = 447009420 +Time for mpfr_float_100 = 516.741 seconds +Total allocations for mpfr_float_100 = 220400854 +Time for mpf_float_100 = 397.302 seconds +Total allocations for mpf_float_100 = 212307349 +Time for cpp_float_100 = 1064.53 seconds +Total allocations for cpp_float_100 = 0 +Time for mpfr_class (100 digits) = 525.74 seconds +Total allocations for mpfr_class (100 digits) = 407154781 +Time for mpreal (100 digits) = 649.941 seconds +Total allocations for mpreal (100 digits) = 724581024 diff --git a/performance/sf_performance.cpp b/performance/sf_performance.cpp new file mode 100644 index 00000000..95c08d18 --- /dev/null +++ b/performance/sf_performance.cpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +unsigned allocation_count = 0; + +void *(*alloc_func_ptr) (size_t); +void *(*realloc_func_ptr) (void *, size_t, size_t); +void (*free_func_ptr) (void *, size_t); + +void *alloc_func(size_t n) +{ + ++allocation_count; + return (*alloc_func_ptr)(n); +} + +void free_func(void * p, size_t n) +{ + (*free_func_ptr)(p, n); +} + +void * realloc_func(void * p, size_t old, size_t n) +{ + ++allocation_count; + return (*realloc_func_ptr)(p, old, n); +} + +int main() +{ + using namespace boost::multiprecision; + +#if defined(TEST_MPFR) || defined(TEST_MPFR_CLASS) || defined(TEST_MPREAL) || defined(TEST_MPF) + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + mp_set_memory_functions(&alloc_func, &realloc_func, &free_func); +#endif + + basic_tests(); + bessel_tests(); + poly_tests(); + nct_tests(); +} + diff --git a/performance/sf_performance.hpp b/performance/sf_performance.hpp new file mode 100644 index 00000000..c525c675 --- /dev/null +++ b/performance/sf_performance.hpp @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 750 +#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false + +#if !defined(TEST_MPFR) && !defined(TEST_MPREAL) && !defined(TEST_MPF) && !defined(TEST_MPREAL) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_CLASS) && !defined(TEST_FLOAT) +# define TEST_MPFR +# define TEST_MPF +# define TEST_CPP_DEC_FLOAT +# define TEST_MPFR_CLASS +# define TEST_MPREAL +# define TEST_FLOAT +#endif + +#ifdef TEST_FLOAT +#include "arithmetic_backend.hpp" +#endif +#ifdef TEST_MPFR_CLASS +#include +#endif +#ifdef TEST_MPFR +#include +#endif +#ifdef TEST_MPREAL +#include +#endif +#ifdef TEST_MPF +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +template +Real test_bessel(); + +template +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; + +template +Real test_bessel() +{ + try{ +# define T double +# define SC_(x) x +# include "libs/math/test/bessel_i_int_data.ipp" +# include "libs/math/test/bessel_i_data.ipp" + + Real r; + + for(unsigned i = 0; i < bessel_i_int_data.size(); ++i) + { + r += boost::math::cyl_bessel_i(Real(bessel_i_int_data[i][0]), Real(bessel_i_int_data[i][1])); + } + for(unsigned i = 0; i < bessel_i_data.size(); ++i) + { + r += boost::math::cyl_bessel_i(Real(bessel_i_data[i][0]), Real(bessel_i_data[i][1])); + } + +#include "libs/math/test/bessel_j_int_data.ipp" + for(unsigned i = 0; i < bessel_j_int_data.size(); ++i) + { + r += boost::math::cyl_bessel_j(Real(bessel_j_int_data[i][0]), Real(bessel_j_int_data[i][1])); + } + +#include "libs/math/test/bessel_j_data.ipp" + for(unsigned i = 0; i < bessel_j_data.size(); ++i) + { + r += boost::math::cyl_bessel_j(Real(bessel_j_data[i][0]), Real(bessel_j_data[i][1])); + } + +#include "libs/math/test/bessel_j_large_data.ipp" + for(unsigned i = 0; i < bessel_j_large_data.size(); ++i) + { + r += boost::math::cyl_bessel_j(Real(bessel_j_large_data[i][0]), Real(bessel_j_large_data[i][1])); + } + +#include "libs/math/test/sph_bessel_data.ipp" + for(unsigned i = 0; i < sph_bessel_data.size(); ++i) + { + r += boost::math::sph_bessel(static_cast(sph_bessel_data[i][0]), Real(sph_bessel_data[i][1])); + } + + return r; + } + catch(const std::exception& e) + { + std::cout << e.what() << std::endl; + } + return 0; +} + +template +Real test_polynomial() +{ + static const unsigned t[] = { + 2, 3, 4, 5, 6, 7, 8 }; + Real result = 0; + for(Real k = 2; k < 1000; ++k) + result += boost::math::tools::evaluate_polynomial(t, k); + + return result; +} + +template +Real test_nct() +{ +#define T double +#include "libs/math/test/nct.ipp" + + Real result = 0; + for(unsigned i = 0; i < nct.size(); ++i) + { + try{ + result += quantile(boost::math::non_central_t_distribution(nct[i][0], nct[i][1]), nct[i][3]); + result += cdf(boost::math::non_central_t_distribution(nct[i][0], nct[i][1]), nct[i][2]); + } + catch(const std::exception&) + {} + } + return result; +} + +extern unsigned allocation_count; + +template +void basic_allocation_test(const char* name, Real x) +{ + static const unsigned a[] = { 2, 3, 4, 5, 6, 7, 8 }; + allocation_count = 0; + Real result = (((((a[6] * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0]; + std::cout << "Allocation count for type " << name << " = " << allocation_count << std::endl; +} + +template +void poly_allocation_test(const char* name, Real x) +{ + static const unsigned a[] = { 2, 3, 4, 5, 6, 7, 8 }; + allocation_count = 0; + Real result = boost::math::tools::evaluate_polynomial(a, x); + std::cout << "Allocation count for type " << name << " = " << allocation_count << std::endl; +} + +template +void time_proc(const char* name, Real (*proc)(), unsigned threads = 1) +{ + try{ + static Real total = 0; + allocation_count = 0; + boost::chrono::duration time; + stopwatch c; + total += proc(); + time = c.elapsed(); + std::cout << "Time for " << name << " = " << time << std::endl; + std::cout << "Total allocations for " << name << " = " << allocation_count << std::endl; + + for(unsigned thread_count = 1; thread_count < threads; ++thread_count) + { + c.reset(); + boost::thread_group g; + for(unsigned i = 0; i <= thread_count; ++i) + g.create_thread(proc); + g.join_all(); + time = c.elapsed(); + std::cout << "Time for " << name << " (" << (thread_count + 1) << " threads) = " << time << std::endl; + std::cout << "Total allocations for " << name << " = " << allocation_count << std::endl; + } + } + catch(const std::exception& e) + { + std::cout << e.what() << std::endl; + } +} + +using namespace boost::multiprecision; + +void basic_tests(); +void bessel_tests(); +void poly_tests(); +void nct_tests(); diff --git a/performance/sf_performance_basic.cpp b/performance/sf_performance_basic.cpp new file mode 100644 index 00000000..a433288f --- /dev/null +++ b/performance/sf_performance_basic.cpp @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void basic_tests() +{ + + std::cout << "Allocation Counts for Horner Evaluation:\n"; +#ifdef TEST_MPFR + basic_allocation_test("mpfr_float_50", mpfr_float_50(2)); + basic_allocation_test("mpfr_float_50 - no expression templates", number, et_off>(2)); +#endif +#ifdef TEST_MPFR_CLASS + basic_allocation_test("mpfr_class", mpfr_class(2)); +#endif +#ifdef TEST_MPREAL + basic_allocation_test("mpfr::mpreal", mpfr::mpreal(2)); +#endif + + std::cout << "Allocation Counts for boost::math::tools::evaluate_polynomial:\n"; +#ifdef TEST_MPFR + poly_allocation_test("mpfr_float_50", mpfr_float_50(2)); + poly_allocation_test("mpfr_float_50 - no expression templates", number, et_off>(2)); +#endif +#ifdef TEST_MPFR_CLASS + poly_allocation_test("mpfr_class", mpfr_class(2)); +#endif +#ifdef TEST_MPREAL + poly_allocation_test("mpfr::mpreal", mpfr::mpreal(2)); +#endif + + // + // Comparison for builtin floats: + // +#ifdef TEST_FLOAT + time_proc("Bessel Functions - double", test_bessel); + time_proc("Bessel Functions - real_concept", test_bessel); + time_proc("Bessel Functions - arithmetic_backend", test_bessel, et_on> >); + time_proc("Bessel Functions - arithmetic_backend - no expression templates", test_bessel, et_off> >); + + time_proc("Non-central T - double", test_nct); + time_proc("Non-central T - real_concept", test_nct); + time_proc("Non-central T - arithmetic_backend", test_nct, et_on> >); + time_proc("Non-central T - arithmetic_backend - no expression templates", test_nct, et_off> >); +#endif +} diff --git a/performance/sf_performance_bessel.cpp b/performance/sf_performance_bessel.cpp new file mode 100644 index 00000000..817f5a56 --- /dev/null +++ b/performance/sf_performance_bessel.cpp @@ -0,0 +1,42 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_1(); +void bessel_tests_2(); +void bessel_tests_3(); +void bessel_tests_4(); +void bessel_tests_5(); +void bessel_tests_6(); + +void bessel_tests() +{ + // + // 50 digits first: + // + std::cout << "Testing Bessel Functions at 50 digits....." << std::endl; +#if defined(TEST_MPFR) || defined(TEST_MPFR_CLASS) + mpfr_set_default_prec(50 * 1000L / 301L); +#endif +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(50 * 1000L / 301L); +#endif + + bessel_tests_1(); + bessel_tests_2(); + bessel_tests_3(); + + // + // Then 100 digits: + // + std::cout << "Testing Bessel Functions at 100 digits....." << std::endl; +#if defined(TEST_MPFR) || defined(TEST_MPFR_CLASS) + mpfr_set_default_prec(100 * 1000L / 301L); +#endif + bessel_tests_4(); + bessel_tests_5(); + bessel_tests_6(); +} diff --git a/performance/sf_performance_bessel1.cpp b/performance/sf_performance_bessel1.cpp new file mode 100644 index 00000000..6c13315f --- /dev/null +++ b/performance/sf_performance_bessel1.cpp @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_1() +{ +#ifdef TEST_MPFR +#if MPFR_VERSION, 1); + time_proc("mpfr_float_50 (no expression templates)", test_bessel, et_off> >, 1); + time_proc("static_mpfr_float_50", test_bessel, et_on> >, 1); + time_proc("static_mpfr_float_50 (no expression templates)", test_bessel, et_off> >, 1); +#else + time_proc("mpfr_float_50", test_bessel, mpfr_buildopt_tls_p() ? 3 : 1); + time_proc("mpfr_float_50 (no expression templates", test_bessel, et_off> >, mpfr_buildopt_tls_p() ? 3 : 1); + time_proc("static_mpfr_float_50", test_bessel, et_on> >, mpfr_buildopt_tls_p() ? 3 : 1); + time_proc("static_mpfr_float_50 (no expression templates)", test_bessel, et_off> >, mpfr_buildopt_tls_p() ? 3 : 1); +#endif +#endif +} diff --git a/performance/sf_performance_bessel2.cpp b/performance/sf_performance_bessel2.cpp new file mode 100644 index 00000000..3eecda8e --- /dev/null +++ b/performance/sf_performance_bessel2.cpp @@ -0,0 +1,17 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_2() +{ +#ifdef TEST_MPF + time_proc("mpf_float_50", test_bessel, 3); + time_proc("mpf_float_50 (no expression templates", test_bessel, et_off> >, 3); +#endif +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_50", test_bessel, 3); +#endif +} diff --git a/performance/sf_performance_bessel3.cpp b/performance/sf_performance_bessel3.cpp new file mode 100644 index 00000000..67ee0fba --- /dev/null +++ b/performance/sf_performance_bessel3.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_3() +{ +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_bessel, mpfr_buildopt_tls_p() ? 3 : 1); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_bessel, mpfr_buildopt_tls_p() ? 3 : 1); +#endif +} diff --git a/performance/sf_performance_bessel4.cpp b/performance/sf_performance_bessel4.cpp new file mode 100644 index 00000000..108d62e1 --- /dev/null +++ b/performance/sf_performance_bessel4.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_4() +{ +#ifdef TEST_MPFR + time_proc("mpfr_float_100", test_bessel); + time_proc("mpfr_float_100 (no expression templates", test_bessel, et_off> >); + time_proc("static_mpfr_float_100", test_bessel); +#endif +} diff --git a/performance/sf_performance_bessel5.cpp b/performance/sf_performance_bessel5.cpp new file mode 100644 index 00000000..f1154b59 --- /dev/null +++ b/performance/sf_performance_bessel5.cpp @@ -0,0 +1,17 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_5() +{ +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(100 * 1000L / 301L); +#endif +#ifdef TEST_MPF + time_proc("mpf_float_100", test_bessel); + time_proc("mpf_float_100 (no expression templates", test_bessel, et_off> >); +#endif +} diff --git a/performance/sf_performance_bessel6.cpp b/performance/sf_performance_bessel6.cpp new file mode 100644 index 00000000..f9c61cd2 --- /dev/null +++ b/performance/sf_performance_bessel6.cpp @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void bessel_tests_6() +{ +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_100", test_bessel); +#endif +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_bessel); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_bessel); +#endif +} diff --git a/performance/sf_performance_nct.cpp b/performance/sf_performance_nct.cpp new file mode 100644 index 00000000..c0a713ba --- /dev/null +++ b/performance/sf_performance_nct.cpp @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_1(); +void nct_tests_2(); +void nct_tests_3(); +void nct_tests_4(); +void nct_tests_5(); +void nct_tests_6(); + +void nct_tests() +{ + // + // 50 digits first: + // + std::cout << "Testing Non-Central T at 50 digits....." << std::endl; +#ifdef TEST_MPFR_CLASS + mpfr_set_default_prec(50 * 1000L / 301L); +#endif + + nct_tests_1(); + nct_tests_2(); + nct_tests_3(); + + // + // Then 100 digits: + // + std::cout << "Testing Non-Central T at 100 digits....." << std::endl; +#ifdef TEST_MPFR_CLASS + mpfr_set_default_prec(100 * 1000L / 301L); +#endif + nct_tests_4(); + nct_tests_5(); + nct_tests_6(); +} diff --git a/performance/sf_performance_nct1.cpp b/performance/sf_performance_nct1.cpp new file mode 100644 index 00000000..cde285c9 --- /dev/null +++ b/performance/sf_performance_nct1.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_1() +{ +#ifdef TEST_MPFR + time_proc("mpfr_float_50", test_nct); + time_proc("mpfr_float_50 (no expression templates", test_nct, et_off> >); + time_proc("static_mpfr_float_50", test_nct); +#endif +} diff --git a/performance/sf_performance_nct2.cpp b/performance/sf_performance_nct2.cpp new file mode 100644 index 00000000..76142bea --- /dev/null +++ b/performance/sf_performance_nct2.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_2() +{ +#ifdef TEST_MPF + time_proc("mpf_float_50", test_nct); + time_proc("mpf_float_50 (no expression templates", test_nct, et_off> >); +#endif +} diff --git a/performance/sf_performance_nct3.cpp b/performance/sf_performance_nct3.cpp new file mode 100644 index 00000000..714831b8 --- /dev/null +++ b/performance/sf_performance_nct3.cpp @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_3() +{ +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(50 * 1000L / 301L); +#endif +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_50", test_nct); +#endif +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_nct); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_nct); +#endif +} diff --git a/performance/sf_performance_nct4.cpp b/performance/sf_performance_nct4.cpp new file mode 100644 index 00000000..1ad30271 --- /dev/null +++ b/performance/sf_performance_nct4.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_4() +{ +#ifdef TEST_MPFR + time_proc("mpfr_float_100", test_nct); + time_proc("mpfr_float_100 (no expression templates", test_nct, et_off> >); + time_proc("static_mpfr_float_100", test_nct); +#endif +} diff --git a/performance/sf_performance_nct5.cpp b/performance/sf_performance_nct5.cpp new file mode 100644 index 00000000..c098ab20 --- /dev/null +++ b/performance/sf_performance_nct5.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_5() +{ +#ifdef TEST_MPF + time_proc("mpf_float_100", test_nct); + time_proc("mpf_float_100 (no expression templates", test_nct, et_off> >); +#endif +} diff --git a/performance/sf_performance_nct6.cpp b/performance/sf_performance_nct6.cpp new file mode 100644 index 00000000..76e0a7e1 --- /dev/null +++ b/performance/sf_performance_nct6.cpp @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void nct_tests_6() +{ +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(100 * 1000L / 301L); +#endif +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_100", test_nct); +#endif +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_nct); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_nct); +#endif +} diff --git a/performance/sf_performance_poly.cpp b/performance/sf_performance_poly.cpp new file mode 100644 index 00000000..138a39bd --- /dev/null +++ b/performance/sf_performance_poly.cpp @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include "sf_performance.hpp" + +void poly_tests() +{ + // + // 50 digits first: + // + std::cout << "Testing Polynomial Evaluation at 50 digits....." << std::endl; +#if defined(TEST_MPFR) || defined(TEST_MPFR_CLASS) + mpfr_set_default_prec(50 * 1000L / 301L); +#endif +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(50 * 1000L / 301L); +#endif +#ifdef TEST_MPFR + time_proc("mpfr_float_50", test_polynomial); + time_proc("mpfr_float_50 (no expression templates", test_polynomial, et_off> >); + time_proc("static_mpfr_float_50", test_polynomial); +#endif +#ifdef TEST_MPF + time_proc("mpf_float_50", test_polynomial); + time_proc("mpf_float_50 (no expression templates", test_polynomial, et_off> >); +#endif +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_50", test_polynomial); +#endif +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_polynomial); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_polynomial); +#endif + // + // Then 100 digits: + // + std::cout << "Testing Polynomial Evaluation at 100 digits....." << std::endl; +#ifdef TEST_MPFR_CLASS + mpfr_set_default_prec(100 * 1000L / 301L); +#endif +#ifdef TEST_MPREAL + mpfr::mpreal::set_default_prec(100 * 1000L / 301L); +#endif +#ifdef TEST_MPFR + time_proc("mpfr_float_100", test_polynomial); + time_proc("mpfr_float_100 (no expression templates", test_polynomial, et_off> >); + time_proc("static_mpfr_float_100", test_polynomial); +#endif +#ifdef TEST_MPF + time_proc("mpf_float_100", test_polynomial); + time_proc("mpf_float_100 (no expression templates", test_polynomial, et_off> >); +#endif +#ifdef TEST_CPP_DEC_FLOAT + time_proc("cpp_dec_float_100", test_polynomial); +#endif +#ifdef TEST_MPFR_CLASS + time_proc("mpfr_class", test_polynomial); +#endif +#ifdef TEST_MPREAL + time_proc("mpfr::mpreal", test_polynomial); +#endif +} diff --git a/performance/voronoi_performance.cpp b/performance/voronoi_performance.cpp new file mode 100644 index 00000000..a9765780 --- /dev/null +++ b/performance/voronoi_performance.cpp @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TEST_GMP +#include +#endif +#ifdef TEST_TOMMATH +#include +#endif + +#include "arithmetic_backend.hpp" + +typedef boost::polygon::detail::point_2d i_point; + +template +struct stopwatch +{ + typedef typename Clock::duration duration; + stopwatch() + { + m_start = Clock::now(); + } + duration elapsed() + { + return Clock::now() - m_start; + } + void reset() + { + m_start = Clock::now(); + } + +private: + typename Clock::time_point m_start; +}; + +std::vector points; +boost::random::mt19937 gen; + +template +struct cpp_int_voronoi_traits +{ + typedef boost::int32_t int_type; + typedef boost::int64_t int_x2_type; + typedef boost::uint64_t uint_x2_type; + typedef Big big_int_type; + typedef double fpt_type; + typedef boost::polygon::detail::extended_exponent_fpt efpt_type; + typedef boost::polygon::detail::ulp_comparison ulp_cmp_type; + struct to_fpt_converter_type + { + template + double operator ()(const boost::multiprecision::number& val) + { + return val.template convert_to(); + } + double operator ()(double val) + { + return val; + } + double operator()(const efpt_type& that) const + { + return that.d(); + } + template + double operator()(const boost::multiprecision::detail::expression& e) + { + typedef typename boost::multiprecision::detail::expression::result_type r_t; + r_t r(e); + return r.template convert_to(); + } + }; + struct to_efpt_converter_type + { + template + efpt_type operator ()(const boost::multiprecision::number& val) + { + return efpt_type(val.template convert_to(), 0); + } + efpt_type operator ()(double val) + { + return efpt_type(val, 0); + } + template + double operator()(const boost::multiprecision::detail::expression& e) + { + typedef typename boost::multiprecision::detail::expression::result_type r_t; + r_t r(e); + return efpt_type(r.template convert_to(), 0); + } + }; +}; + +template +struct native_int_voronoi_traits +{ + typedef boost::int32_t int_type; + typedef boost::int64_t int_x2_type; + typedef boost::uint64_t uint_x2_type; + typedef Big big_int_type; + typedef double fpt_type; + typedef boost::polygon::detail::extended_exponent_fpt efpt_type; + typedef boost::polygon::detail::ulp_comparison ulp_cmp_type; + struct to_fpt_converter_type + { + template + double operator ()(const T& val)const + { + return val; + } + double operator()(const efpt_type& that) const + { + return that.d(); + } + }; + struct to_efpt_converter_type + { + template + efpt_type operator ()(const T& val)const + { + return efpt_type(val, 0); + } + }; +}; + +std::map results; +double min_time = (std::numeric_limits::max)(); + +template +double test(const char* name) +{ + typedef boost::polygon::detail::voronoi_predicates preds; + typedef boost::polygon::detail::circle_event circle_event; + typedef boost::polygon::detail::site_event site_event; + typedef typename preds::template mp_circle_formation_functor circle_pred; + + boost::random::uniform_int_distribution<> dist(0, points.size() - 1); + circle_pred pc; + circle_event event; + + stopwatch w; + + for(unsigned i = 0; i < 10000; ++i) + { + site_event s1(points[dist(gen)]); + site_event s2(points[dist(gen)]); + site_event s3(points[dist(gen)]); + pc.ppp(s1, s2, s3, event); + pc.pps(s1, s2, s3, 0, event); + pc.pss(s1, s2, s3, 0, event); + pc.sss(s1, s2, s3, event); + } + double d = boost::chrono::duration_cast >(w.elapsed()).count(); + if(d < min_time) + min_time = d; + results[name] = d; + std::cout << "Time for " << std::setw(30) << std::left << name << " = " << d << std::endl; + return d; +} + +void generate_quickbook() +{ + std::cout << "[table\n[[Integer Type][Relative Performance (Actual time in parenthesis)]]\n"; + + std::map::const_iterator i(results.begin()), j(results.end()); + + while(i != j) + { + double rel = i->second / min_time; + std::cout << "[[" << i->first << "][" << rel << "(" << i->second << "s)]]\n"; + ++i; + } + + std::cout << "]\n"; +} + + +int main() +{ + boost::random::uniform_int_distribution<> dist((std::numeric_limits::min)() / 2, (std::numeric_limits::max)() / 2); + + for(unsigned i = 0; i < 100; ++i) + { + points.push_back(i_point(dist(gen), dist(gen))); + } + + test >("extended_int"); + + test >("int256_t"); + test >("int512_t"); + test >("int1024_t"); + + test >("checked_int256_t"); + test >("checked_int512_t"); + test >("checked_int1024_t"); + + test, boost::multiprecision::et_off> > >("cpp_int"); + +#ifdef TEST_GMP + test > >("mpz_int"); +#endif +#ifdef TEST_TOMMATH + test > >("tom_int"); +#endif + + generate_quickbook(); + + test >("int64_t"); + test, boost::multiprecision::et_off> > >("number, et_off>"); + //test, boost::multiprecision::et_on> > >("number, et_on>"); + + return 0; +} + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 00000000..43529770 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,974 @@ +# copyright John Maddock 2011 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + +import modules ; +import path ; + +local ntl-path = [ modules.peek : NTL_PATH ] ; +local gmp_path = [ modules.peek : GMP_PATH ] ; +local mpfr_path = [ modules.peek : MPFR_PATH ] ; +local tommath_path = [ modules.peek : TOMMATH_PATH ] ; + +project : requirements + $(gmp_path) + $(gmp_path)/mpfr + $(gmp_path)/gmpfrxx + $(mpfr_path) + $(tommath_path) + ../../.. + $(gmp_path) + $(mpfr_path) + $(mpfr_path)/build.vc10/lib/Win32/Debug + $(tommath_path) + # We set these to make it easier to set up and test GMP and MPFR under Win32: + msvc:static + msvc:static + msvc:all + gcc:-Wall + gcc:-Wextra + ; + +local enable-specfun = [ MATCH (--enable-specfun) : [ modules.peek : ARGV ] ] ; +local disable-concepts = [ MATCH (--disable-concepts) : [ modules.peek : ARGV ] ] ; + + +lib gmp ; +lib mpfr ; + +if $(tommath_path) +{ + TOMMATH = [ GLOB $(tommath_path) : *.c ] ; +} +else +{ + lib tommath ; + TOMMATH = tommath ; +} + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_BACKEND + : test_arithmetic_backend_concept ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_arithmetic_cpp_dec_float ; + +run test_arithmetic.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_arithmetic_mpf50 ; + +run test_arithmetic.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF + [ check-target-builds ../config//has_gmp : : no ] + : test_arithmetic_mpf ; + +run test_arithmetic.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPZ + [ check-target-builds ../config//has_gmp : : no ] + : test_arithmetic_mpz ; + +run test_arithmetic.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPZ_BOOST_RATIONAL + [ check-target-builds ../config//has_gmp : : no ] + : test_arithmetic_mpz_br ; + +run test_arithmetic.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPQ + [ check-target-builds ../config//has_gmp : : no ] + : test_arithmetic_mpq ; + +run test_arithmetic.cpp mpfr gmp + : # command line + : # input files + : # requirements + TEST_MPFR + [ check-target-builds ../config//has_mpfr : : no ] + : test_arithmetic_mpfr ; + +run test_arithmetic.cpp mpfr gmp + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_arithmetic_mpfr_50 ; + +run test_arithmetic.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + [ check-target-builds ../config//has_tommath : : no ] + : test_arithmetic_tommath ; + +run test_arithmetic.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH_BOOST_RATIONAL + [ check-target-builds ../config//has_tommath : : no ] + : test_arithmetic_tommath_br ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_1 + : test_arithmetic_cpp_int_1 ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_2 + : test_arithmetic_cpp_int_2 ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_3 + : test_arithmetic_cpp_int_3 ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_1A + : test_arithmetic_cpp_int_1a ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_2A + : test_arithmetic_cpp_int_2a ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_3A + : test_arithmetic_cpp_int_3a ; + +run test_arithmetic.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT_BR + : test_arithmetic_cpp_int_br ; + +run test_numeric_limits.cpp + : # command line + : # input files + : # requirements + TEST_BACKEND + : test_numeric_limits_backend_concept ; + +run test_numeric_limits.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_numeric_limits_mpf50 ; + +run test_numeric_limits.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF + [ check-target-builds ../config//has_gmp : : no ] + : test_numeric_limits_mpf ; + +run test_numeric_limits.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPZ + [ check-target-builds ../config//has_gmp : : no ] + : test_numeric_limits_mpz ; + +run test_numeric_limits.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPQ + [ check-target-builds ../config//has_gmp : : no ] + : test_numeric_limits_mpq ; + +run test_numeric_limits.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR + [ check-target-builds ../config//has_mpfr : : no ] + : test_numeric_limits_mpfr ; + +run test_numeric_limits.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_numeric_limits_mpfr_50 ; + +run test_numeric_limits.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_numeric_limits_cpp_dec_float ; + +run test_numeric_limits.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + [ check-target-builds ../config//has_tommath : : no ] + : test_numeric_limits_tommath ; + +run test_numeric_limits.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT + : test_numeric_limits_cpp_int ; + +run test_exp.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_exp_mpf50 ; + +run test_log.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_log_mpf50 ; + +run test_pow.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_pow_mpf50 ; + +run test_sinh.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_sinh_mpf50 ; + +run test_cosh.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_cosh_mpf50 ; + +run test_tanh.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_tanh_mpf50 ; + +run test_exp.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_exp_mpfr50 ; + +run test_log.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_log_mpfr50 ; + +run test_pow.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_pow_mpfr50 ; + +run test_sinh.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_sinh_mpfr50 ; + +run test_cosh.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_cosh_mpfr50 ; + +run test_tanh.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_tanh_mpfr50 ; + +run test_exp.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_exp_cpp_dec_float ; + +run test_sqrt.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_sqrt_cpp_dec_float ; + +run test_log.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_log_cpp_dec_float ; + +run test_pow.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_pow_cpp_dec_float ; + +run test_sinh.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_sinh_cpp_dec_float ; + +run test_cosh.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_cosh_cpp_dec_float ; + +run test_tanh.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_tanh_cpp_dec_float ; + +run test_sin.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_sin_cpp_dec_float ; + +run test_sin.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_sin_mpf50 ; + +run test_sin.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_sin_mpfr_50 ; + +run test_cos.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_cos_cpp_dec_float ; + +run test_cos.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_cos_mpf50 ; + +run test_cos.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_cos_mpfr_50 ; + +run test_asin.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_asin_cpp_dec_float ; + +run test_asin.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_asin_mpf50 ; + +run test_asin.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_asin_mpfr_50 ; + +run test_acos.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_acos_cpp_dec_float ; + +run test_acos.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_acos_mpf50 ; + +run test_acos.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_acos_mpfr_50 ; + +run test_atan.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_atan_mpf50 ; + +run test_atan.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_atan_cpp_dec_float ; + +run test_atan.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_atan_mpfr_50 ; + +run test_tan.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_tan_mpf50 ; + +run test_tan.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_tan_cpp_dec_float ; + +run test_tan.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_tan_mpfr_50 ; + +run test_gmp_conversions.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] ; + +run test_mpfr_conversions.cpp gmp mpfr + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_mpfr : : no ] ; + +run test_round.cpp + : # command line + : # input files + : # requirements + TEST_BACKEND + : test_round_backend_concept ; + +run test_round.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_round_mpf50 ; + +run test_round.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_round_mpfr_50 ; + +run test_round.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_round_cpp_dec_float ; + +run test_fpclassify.cpp + : # command line + : # input files + : # requirements + TEST_BACKEND + : test_fpclassify_backend_concept ; + +run test_fpclassify.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_fpclassify_mpf50 ; + +run test_fpclassify.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_fpclassify_mpfr_50 ; + +run test_fpclassify.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_fpclassify_cpp_dec_float ; + +run test_constants.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + : test_constants_mpf50 ; + +run test_constants.cpp mpfr + : # command line + : # input files + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + : test_constants_mpfr_50 ; + +run test_constants.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + : test_constants_cpp_dec_float ; + + +run test_move.cpp mpfr gmp + : # command line + : # input files + : # requirements + TEST_MPFR + [ check-target-builds ../config//has_mpfr : : no ] + : test_move_mpfr ; + +run test_move.cpp gmp + : # command line + : # input files + : # requirements + TEST_GMP + [ check-target-builds ../config//has_gmp : : no ] + : test_move_gmp ; + +run test_move.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + [ check-target-builds ../config//has_tommath : : no ] + : test_move_tommath ; + +run test_move.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT + : test_move_cpp_int ; + +run test_test.cpp ; +compile test_constexpr.cpp ; + +run test_float_io.cpp + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + #release # Otherwise runtime is slow + : test_float_io_cpp_dec_float ; + +run test_float_io.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPF_50 + release # Otherwise runtime is slow + [ check-target-builds ../config//has_gmp : : no ] + : test_float_io_mpf ; + +run test_float_io.cpp mpfr gmp + : # command line + : # input files + : # requirements + TEST_MPFR_50 + release # Otherwise runtime is slow + [ check-target-builds ../config//has_mpfr : : no ] + : test_float_io_mpfr ; + +run test_int_io.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + release # Otherwise runtime is slow + [ check-target-builds ../config//has_tommath : : no ] + : test_int_io_tommath ; + +run test_int_io.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPZ + release # Otherwise runtime is slow + [ check-target-builds ../config//has_gmp : : no ] + : test_int_io_mpz ; + +run test_int_io.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT + release # Otherwise runtime is slow + : test_int_io_cpp_int ; + +run test_cpp_int.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] + release # otherwise runtime is too slow!! + TEST1 + : test_cpp_int_1 + ; + +run test_cpp_int.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] + release # otherwise runtime is too slow!! + TEST2 + : test_cpp_int_2 + ; + +run test_cpp_int.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] + release # otherwise runtime is too slow!! + TEST3 + : test_cpp_int_3 + ; + +run test_checked_cpp_int.cpp ; + +run test_miller_rabin.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] + release # otherwise runtime is too slow!! + ; + +run test_rational_io.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + TEST_TOMMATH + [ check-target-builds ../config//has_tommath : : no ] + release # Otherwise runtime is slow + : test_rational_io_tommath ; + +run test_rational_io.cpp gmp + : # command line + : # input files + : # requirements + TEST_MPQ + [ check-target-builds ../config//has_gmp : : no ] + release # Otherwise runtime is slow + : test_rational_io_mpz ; + +run test_rational_io.cpp + : # command line + : # input files + : # requirements + TEST_CPP_INT + release # Otherwise runtime is slow + : test_rational_io_cpp_int ; + +run test_generic_conv.cpp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : TEST_GMP gmp : ] + [ check-target-builds ../config//has_tommath : TEST_TOMMATH $(TOMMATH) : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR mpfr : ] + release # Otherwise runtime is slow + ; + + +run ../example/gmp_snips.cpp gmp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] ; + +run ../example/mpfr_snips.cpp mpfr + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_mpfr : : no ] ; + +run ../example/cpp_dec_float_snips.cpp ; +run ../example/cpp_int_snips.cpp ; + +run ../example/tommath_snips.cpp $(TOMMATH) + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_tommath : : no ] ; +run ../example/floating_point_examples.cpp : : : gcc:-std=c++0x ; +run test_cpp_int_conv.cpp ; +run test_native_integer.cpp ; + +run test_mixed_cpp_int.cpp ; +run test_mixed_float.cpp + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : TEST_GMP gmp : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR mpfr gmp : ] ; + + +compile include_test/mpfr_include_test.cpp + : # requirements + [ check-target-builds ../config//has_mpfr : : no ] ; +compile include_test/gmp_include_test.cpp + : # requirements + [ check-target-builds ../config//has_gmp : : no ] ; +compile include_test/tommath_include_test.cpp + : # requirements + [ check-target-builds ../config//has_tommath : : no ] ; +compile include_test/cpp_int_include_test.cpp ; +compile include_test/cpp_dec_float_include_test.cpp ; + +run ublas_interop/test1.cpp ublas_interop/test11.cpp ublas_interop/test12.cpp ublas_interop/test13.cpp ; +run ublas_interop/test2.cpp ublas_interop/test21.cpp ublas_interop/test22.cpp ublas_interop/test23.cpp ; +#run ublas_interop/test3.cpp ublas_interop/test31.cpp ublas_interop/test32.cpp ublas_interop/test33.cpp ; +run ublas_interop/test4.cpp ublas_interop/test42.cpp ublas_interop/test43.cpp ; +run ublas_interop/test5.cpp ublas_interop/test52.cpp ublas_interop/test53.cpp ; +run ublas_interop/test6.cpp ublas_interop/test62.cpp ublas_interop/test63.cpp ; +#run ublas_interop/test7.cpp ublas_interop/test71.cpp ublas_interop/test72.cpp ublas_interop/test73.cpp ; + + +if $(enable-specfun) +{ + + for local source in [ glob math/*.cpp ] + { + run $(source) mpfr gmp /boost/test//boost_test_exec_monitor/static /boost/regex//boost_regex/static + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_mpfr : : no ] + TEST_MPFR_50 + speed + BOOST_ALL_NO_LIB + msvc:-bigobj + release + : $(source:B)_mpfr ; + run $(source) gmp /boost/test//boost_test_exec_monitor/static /boost/regex//boost_regex/static + : # command line + : # input files + : # requirements + [ check-target-builds ../config//has_gmp : : no ] + speed + TEST_MPF_50 + BOOST_ALL_NO_LIB + msvc:-bigobj + release + : $(source:B)_mpf ; + run $(source) /boost/test//boost_test_exec_monitor/static /boost/regex//boost_regex/static + : # command line + : # input files + : # requirements + TEST_CPP_DEC_FLOAT + BOOST_ALL_NO_LIB + speed + msvc:-bigobj + release + : $(source:B)_cpp_dec_float ; + } +} + +for local source in [ glob compile_fail/*.cpp ] +{ + compile-fail $(source) + : + [ check-target-builds ../config//has_gmp : TEST_GMP off : ] + [ check-target-builds ../config//has_mpfr : TEST_MPFR off : ] + ; +} + +if ! $(disable-concepts) +{ + + for local source in [ glob concepts/*.cpp ] + { + + compile $(source) mpfr + : # requirements + TEST_MPFR_50 + [ check-target-builds ../config//has_mpfr : : no ] + off + : $(source:B)_mpfr_50 ; + + compile $(source) mpfr + : # requirements + TEST_MPFR_6 + [ check-target-builds ../config//has_mpfr : : no ] + off + : $(source:B)_mpfr_6 ; + + compile $(source) mpfr + : # requirements + TEST_MPFR_15 + [ check-target-builds ../config//has_mpfr : : no ] + off + : $(source:B)_mpfr_15 ; + + compile $(source) mpfr + : # requirements + TEST_MPFR_17 + [ check-target-builds ../config//has_mpfr : : no ] + off + : $(source:B)_mpfr_17 ; + + compile $(source) mpfr + : # requirements + TEST_MPFR_30 + [ check-target-builds ../config//has_mpfr : : no ] + off + : $(source:B)_mpfr_30 ; + + compile $(source) gmp + : # requirements + TEST_MPF_50 + [ check-target-builds ../config//has_gmp : : no ] + off + : $(source:B)_mpf50 ; + + compile $(source) + : # requirements + TEST_CPP_DEC_FLOAT + off + : $(source:B)_cpp_dec_float ; + + compile $(source) + : # requirements + TEST_CPP_DEC_FLOAT_NO_ET + off + : $(source:B)_cpp_dec_float_no_et ; + + compile $(source) + : # requirements + TEST_BACKEND + off + : $(source:B)_backend_concept ; + } +} + diff --git a/test/compile_fail/conv_fail_01.cpp b/test/compile_fail/conv_fail_01.cpp new file mode 100644 index 00000000..c5edc3b0 --- /dev/null +++ b/test/compile_fail/conv_fail_01.cpp @@ -0,0 +1,17 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +void foo(cpp_int i) +{ +} + +int main() +{ + foo(2.3); // conversion from float is explicit +} diff --git a/test/compile_fail/conv_fail_02.cpp b/test/compile_fail/conv_fail_02.cpp new file mode 100644 index 00000000..79ffff2f --- /dev/null +++ b/test/compile_fail/conv_fail_02.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i == 2.3; +} diff --git a/test/compile_fail/conv_fail_03.cpp b/test/compile_fail/conv_fail_03.cpp new file mode 100644 index 00000000..0fe89320 --- /dev/null +++ b/test/compile_fail/conv_fail_03.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i != 2.3; +} diff --git a/test/compile_fail/conv_fail_04.cpp b/test/compile_fail/conv_fail_04.cpp new file mode 100644 index 00000000..6bd72119 --- /dev/null +++ b/test/compile_fail/conv_fail_04.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i <= 2.3; +} diff --git a/test/compile_fail/conv_fail_05.cpp b/test/compile_fail/conv_fail_05.cpp new file mode 100644 index 00000000..23f49022 --- /dev/null +++ b/test/compile_fail/conv_fail_05.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i >= 2.3; +} diff --git a/test/compile_fail/conv_fail_06.cpp b/test/compile_fail/conv_fail_06.cpp new file mode 100644 index 00000000..78fea0f7 --- /dev/null +++ b/test/compile_fail/conv_fail_06.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i > 2.3; +} diff --git a/test/compile_fail/conv_fail_07.cpp b/test/compile_fail/conv_fail_07.cpp new file mode 100644 index 00000000..af4286f4 --- /dev/null +++ b/test/compile_fail/conv_fail_07.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i < 2.3; +} diff --git a/test/compile_fail/conv_fail_08.cpp b/test/compile_fail/conv_fail_08.cpp new file mode 100644 index 00000000..d741c613 --- /dev/null +++ b/test/compile_fail/conv_fail_08.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i = 2.3; +} diff --git a/test/compile_fail/conv_fail_09.cpp b/test/compile_fail/conv_fail_09.cpp new file mode 100644 index 00000000..29ce8b7b --- /dev/null +++ b/test/compile_fail/conv_fail_09.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i += 2.3; +} diff --git a/test/compile_fail/conv_fail_10.cpp b/test/compile_fail/conv_fail_10.cpp new file mode 100644 index 00000000..d4376a2b --- /dev/null +++ b/test/compile_fail/conv_fail_10.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i -= 2.3; +} diff --git a/test/compile_fail/conv_fail_11.cpp b/test/compile_fail/conv_fail_11.cpp new file mode 100644 index 00000000..b07a8b89 --- /dev/null +++ b/test/compile_fail/conv_fail_11.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i *= 2.3; +} diff --git a/test/compile_fail/conv_fail_12.cpp b/test/compile_fail/conv_fail_12.cpp new file mode 100644 index 00000000..fbaf8fae --- /dev/null +++ b/test/compile_fail/conv_fail_12.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i /= 2.3; +} diff --git a/test/compile_fail/conv_fail_13.cpp b/test/compile_fail/conv_fail_13.cpp new file mode 100644 index 00000000..1d705e7f --- /dev/null +++ b/test/compile_fail/conv_fail_13.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i %= 2.3; +} diff --git a/test/compile_fail/conv_fail_14.cpp b/test/compile_fail/conv_fail_14.cpp new file mode 100644 index 00000000..54b86232 --- /dev/null +++ b/test/compile_fail/conv_fail_14.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i |= 2.3; +} diff --git a/test/compile_fail/conv_fail_15.cpp b/test/compile_fail/conv_fail_15.cpp new file mode 100644 index 00000000..e225a870 --- /dev/null +++ b/test/compile_fail/conv_fail_15.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i ^= 2.3; +} diff --git a/test/compile_fail/conv_fail_16.cpp b/test/compile_fail/conv_fail_16.cpp new file mode 100644 index 00000000..0ba8c25b --- /dev/null +++ b/test/compile_fail/conv_fail_16.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 2; + i &= 2.3; +} diff --git a/test/compile_fail/conv_fail_17.cpp b/test/compile_fail/conv_fail_17.cpp new file mode 100644 index 00000000..0649a64d --- /dev/null +++ b/test/compile_fail/conv_fail_17.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(a); +} diff --git a/test/compile_fail/conv_fail_18.cpp b/test/compile_fail/conv_fail_18.cpp new file mode 100644 index 00000000..4335d975 --- /dev/null +++ b/test/compile_fail/conv_fail_18.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(2); + i = a; +} diff --git a/test/compile_fail/conv_fail_19.cpp b/test/compile_fail/conv_fail_19.cpp new file mode 100644 index 00000000..2315252e --- /dev/null +++ b/test/compile_fail/conv_fail_19.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(a + b); +} diff --git a/test/compile_fail/conv_fail_20.cpp b/test/compile_fail/conv_fail_20.cpp new file mode 100644 index 00000000..24a63fa2 --- /dev/null +++ b/test/compile_fail/conv_fail_20.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i = a * b; +} diff --git a/test/compile_fail/conv_fail_21.cpp b/test/compile_fail/conv_fail_21.cpp new file mode 100644 index 00000000..8c845f10 --- /dev/null +++ b/test/compile_fail/conv_fail_21.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i += a * b; +} diff --git a/test/compile_fail/conv_fail_22.cpp b/test/compile_fail/conv_fail_22.cpp new file mode 100644 index 00000000..d35e837e --- /dev/null +++ b/test/compile_fail/conv_fail_22.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i -= a * b; +} diff --git a/test/compile_fail/conv_fail_23.cpp b/test/compile_fail/conv_fail_23.cpp new file mode 100644 index 00000000..3e5a9f53 --- /dev/null +++ b/test/compile_fail/conv_fail_23.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i *= a * b; +} diff --git a/test/compile_fail/conv_fail_24.cpp b/test/compile_fail/conv_fail_24.cpp new file mode 100644 index 00000000..a2581052 --- /dev/null +++ b/test/compile_fail/conv_fail_24.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i /= a * b; +} diff --git a/test/compile_fail/conv_fail_25.cpp b/test/compile_fail/conv_fail_25.cpp new file mode 100644 index 00000000..694ee712 --- /dev/null +++ b/test/compile_fail/conv_fail_25.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i %= a * b; +} diff --git a/test/compile_fail/conv_fail_26.cpp b/test/compile_fail/conv_fail_26.cpp new file mode 100644 index 00000000..0df397f4 --- /dev/null +++ b/test/compile_fail/conv_fail_26.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i &= a * b; +} diff --git a/test/compile_fail/conv_fail_27.cpp b/test/compile_fail/conv_fail_27.cpp new file mode 100644 index 00000000..3995389d --- /dev/null +++ b/test/compile_fail/conv_fail_27.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i |= a * b; +} diff --git a/test/compile_fail/conv_fail_28.cpp b/test/compile_fail/conv_fail_28.cpp new file mode 100644 index 00000000..4133aa14 --- /dev/null +++ b/test/compile_fail/conv_fail_28.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2), b(3); + cpp_int i(3); + i ^= a * b; +} diff --git a/test/compile_fail/conv_fail_29.cpp b/test/compile_fail/conv_fail_29.cpp new file mode 100644 index 00000000..854118fb --- /dev/null +++ b/test/compile_fail/conv_fail_29.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i + 3.3; +} diff --git a/test/compile_fail/conv_fail_30.cpp b/test/compile_fail/conv_fail_30.cpp new file mode 100644 index 00000000..4ba78fe5 --- /dev/null +++ b/test/compile_fail/conv_fail_30.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 + i; +} diff --git a/test/compile_fail/conv_fail_31.cpp b/test/compile_fail/conv_fail_31.cpp new file mode 100644 index 00000000..56a14828 --- /dev/null +++ b/test/compile_fail/conv_fail_31.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 - i; +} diff --git a/test/compile_fail/conv_fail_32.cpp b/test/compile_fail/conv_fail_32.cpp new file mode 100644 index 00000000..1769185f --- /dev/null +++ b/test/compile_fail/conv_fail_32.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i - 3.3; +} diff --git a/test/compile_fail/conv_fail_33.cpp b/test/compile_fail/conv_fail_33.cpp new file mode 100644 index 00000000..36758318 --- /dev/null +++ b/test/compile_fail/conv_fail_33.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i * 3.3; +} diff --git a/test/compile_fail/conv_fail_34.cpp b/test/compile_fail/conv_fail_34.cpp new file mode 100644 index 00000000..7d178c48 --- /dev/null +++ b/test/compile_fail/conv_fail_34.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 * i; +} diff --git a/test/compile_fail/conv_fail_35.cpp b/test/compile_fail/conv_fail_35.cpp new file mode 100644 index 00000000..67f6bdc8 --- /dev/null +++ b/test/compile_fail/conv_fail_35.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 / i; +} diff --git a/test/compile_fail/conv_fail_36.cpp b/test/compile_fail/conv_fail_36.cpp new file mode 100644 index 00000000..3b175be8 --- /dev/null +++ b/test/compile_fail/conv_fail_36.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i / 3.3; +} diff --git a/test/compile_fail/conv_fail_37.cpp b/test/compile_fail/conv_fail_37.cpp new file mode 100644 index 00000000..164db0b9 --- /dev/null +++ b/test/compile_fail/conv_fail_37.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i % 3.3; +} diff --git a/test/compile_fail/conv_fail_38.cpp b/test/compile_fail/conv_fail_38.cpp new file mode 100644 index 00000000..a905e20e --- /dev/null +++ b/test/compile_fail/conv_fail_38.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 % i; +} diff --git a/test/compile_fail/conv_fail_39.cpp b/test/compile_fail/conv_fail_39.cpp new file mode 100644 index 00000000..fa495d70 --- /dev/null +++ b/test/compile_fail/conv_fail_39.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 & i; +} diff --git a/test/compile_fail/conv_fail_40.cpp b/test/compile_fail/conv_fail_40.cpp new file mode 100644 index 00000000..f3ccf05b --- /dev/null +++ b/test/compile_fail/conv_fail_40.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i & 3.3; +} diff --git a/test/compile_fail/conv_fail_41.cpp b/test/compile_fail/conv_fail_41.cpp new file mode 100644 index 00000000..67c30945 --- /dev/null +++ b/test/compile_fail/conv_fail_41.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i | 3.3; +} diff --git a/test/compile_fail/conv_fail_42.cpp b/test/compile_fail/conv_fail_42.cpp new file mode 100644 index 00000000..6ebe5f5b --- /dev/null +++ b/test/compile_fail/conv_fail_42.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 | i; +} diff --git a/test/compile_fail/conv_fail_43.cpp b/test/compile_fail/conv_fail_43.cpp new file mode 100644 index 00000000..cac2c020 --- /dev/null +++ b/test/compile_fail/conv_fail_43.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = 3.3 ^ i; +} diff --git a/test/compile_fail/conv_fail_44.cpp b/test/compile_fail/conv_fail_44.cpp new file mode 100644 index 00000000..32a27593 --- /dev/null +++ b/test/compile_fail/conv_fail_44.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i(3), j; + j = i ^ 3.3; +} diff --git a/test/compile_fail/conv_fail_45.cpp b/test/compile_fail/conv_fail_45.cpp new file mode 100644 index 00000000..5e2f813a --- /dev/null +++ b/test/compile_fail/conv_fail_45.cpp @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_GMP + +#include + +using namespace boost::multiprecision; + +void foo(mpz_int i); + +int main() +{ + mpf_t f + foo(f); +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_46.cpp b/test/compile_fail/conv_fail_46.cpp new file mode 100644 index 00000000..11530eb1 --- /dev/null +++ b/test/compile_fail/conv_fail_46.cpp @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_GMP + +#include + +using namespace boost::multiprecision; + +int main() +{ + mpf_t f; + mpz_int i; + i = f; +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_47.cpp b/test/compile_fail/conv_fail_47.cpp new file mode 100644 index 00000000..b385e988 --- /dev/null +++ b/test/compile_fail/conv_fail_47.cpp @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_GMP + +#include + +using namespace boost::multiprecision; + +void foo(mpf_float_50); + +int main() +{ + mpf_float_100 f(2); + foo(f); +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_48.cpp b/test/compile_fail/conv_fail_48.cpp new file mode 100644 index 00000000..66828ca3 --- /dev/null +++ b/test/compile_fail/conv_fail_48.cpp @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_GMP + +#include + +using namespace boost::multiprecision; + +int main() +{ + mpf_float_100 f(2); + mpf_float_50 f2; + f2 = f; +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_49.cpp b/test/compile_fail/conv_fail_49.cpp new file mode 100644 index 00000000..7f4bd612 --- /dev/null +++ b/test/compile_fail/conv_fail_49.cpp @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_MPFR + +#include + +using namespace boost::multiprecision; + +int main() +{ + mpfr_float_100 f(2); + mpfr_float_50 f2; + f2 = f; +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_50.cpp b/test/compile_fail/conv_fail_50.cpp new file mode 100644 index 00000000..d0a52a58 --- /dev/null +++ b/test/compile_fail/conv_fail_50.cpp @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef TEST_MPFR + +#include + +using namespace boost::multiprecision; + +int main() +{ + mpfr_float_100 f(2); + mpfr_float_50 f2 = f; +} + +#else + +#error "Nothing to test without GMP!" + +#endif diff --git a/test/compile_fail/conv_fail_51.cpp b/test/compile_fail/conv_fail_51.cpp new file mode 100644 index 00000000..77441672 --- /dev/null +++ b/test/compile_fail/conv_fail_51.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_100 f(2); + cpp_dec_float_50 f2 = f; +} + diff --git a/test/compile_fail/conv_fail_52.cpp b/test/compile_fail/conv_fail_52.cpp new file mode 100644 index 00000000..0f9edfb5 --- /dev/null +++ b/test/compile_fail/conv_fail_52.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_100 f(2); + cpp_dec_float_50 f2; + f2 = f; +} + diff --git a/test/compile_fail/conv_fail_53.cpp b/test/compile_fail/conv_fail_53.cpp new file mode 100644 index 00000000..cd48feea --- /dev/null +++ b/test/compile_fail/conv_fail_53.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + int256_t i = 3; + int128_t j = i; +} + diff --git a/test/compile_fail/conv_fail_54.cpp b/test/compile_fail/conv_fail_54.cpp new file mode 100644 index 00000000..f7583363 --- /dev/null +++ b/test/compile_fail/conv_fail_54.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + int256_t i = 3; + int128_t j; + j = i; +} + diff --git a/test/compile_fail/conv_fail_55.cpp b/test/compile_fail/conv_fail_55.cpp new file mode 100644 index 00000000..680306f1 --- /dev/null +++ b/test/compile_fail/conv_fail_55.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + int256_t i = 3; + uint256_t j; + j = i; +} + diff --git a/test/compile_fail/conv_fail_56.cpp b/test/compile_fail/conv_fail_56.cpp new file mode 100644 index 00000000..f33e832d --- /dev/null +++ b/test/compile_fail/conv_fail_56.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + int256_t i = 3; + uint256_t j = i; +} + diff --git a/test/compile_fail/conv_fail_57.cpp b/test/compile_fail/conv_fail_57.cpp new file mode 100644 index 00000000..04dcb4cf --- /dev/null +++ b/test/compile_fail/conv_fail_57.cpp @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 3; + int256_t j = i; +} + diff --git a/test/compile_fail/conv_fail_58.cpp b/test/compile_fail/conv_fail_58.cpp new file mode 100644 index 00000000..00e09060 --- /dev/null +++ b/test/compile_fail/conv_fail_58.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_int i = 3; + int256_t j; + j = i; +} + diff --git a/test/compile_fail/cpp_int_complement.cpp b/test/compile_fail/cpp_int_complement.cpp new file mode 100644 index 00000000..195d94e7 --- /dev/null +++ b/test/compile_fail/cpp_int_complement.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + checked_int256_t i; + i = ~i; +} diff --git a/test/compile_fail/cpp_int_negate_1.cpp b/test/compile_fail/cpp_int_negate_1.cpp new file mode 100644 index 00000000..35fa0abc --- /dev/null +++ b/test/compile_fail/cpp_int_negate_1.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + checked_uint256_t i; + i = -i; +} diff --git a/test/compile_fail/cpp_int_negate_2.cpp b/test/compile_fail/cpp_int_negate_2.cpp new file mode 100644 index 00000000..5b75cf09 --- /dev/null +++ b/test/compile_fail/cpp_int_negate_2.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + number, et_on> i; + i = -i; +} diff --git a/test/compile_fail/operator_fail_01.cpp b/test/compile_fail/operator_fail_01.cpp new file mode 100644 index 00000000..8b13b385 --- /dev/null +++ b/test/compile_fail/operator_fail_01.cpp @@ -0,0 +1,17 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using namespace boost::multiprecision; + +int main() +{ + number, et_on> a(2); + number, et_off> b(2); + + a = a + b; +} + diff --git a/test/compile_fail/operator_fail_02.cpp b/test/compile_fail/operator_fail_02.cpp new file mode 100644 index 00000000..cd422e74 --- /dev/null +++ b/test/compile_fail/operator_fail_02.cpp @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::multiprecision; + +int main() +{ + cpp_dec_float_50 a(2); + cpp_int b(2); + + a = a + b; +} + diff --git a/test/concepts/number_concept_check.cpp b/test/concepts/number_concept_check.cpp new file mode 100644 index 00000000..ce7d5672 --- /dev/null +++ b/test/concepts/number_concept_check.cpp @@ -0,0 +1,223 @@ +// Copyright John Maddock 2011. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T t = 1; + t = abs(t); + t = abs(t*t); + + t = fabs(t); + t = fabs(t*t); + + t = sqrt(t); + t = sqrt(t*t); + + t = floor(t); + t = floor(t*t); + + t = ceil(t); + t = ceil(t*t); + + t = trunc(t); + t = trunc(t*t); + + t = round(t); + t = round(t*t); + + t = exp(t); + t = exp(t*t); + + t = log(t); + t = log(t*t); + + t = log10(t); + t = log10(t*t); + + t = cos(t); + t = cos(t*t); + + t = sin(t); + t = sin(t*t); + + t = tan(t); + t = tan(t*t); + + t = asin(t); + t = asin(t*t); + + t = atan(t); + t = atan(t*t); + + t = acos(t); + t = acos(t*t); + + t = cosh(t); + t = cosh(t*t); + + t = sinh(t); + t = sinh(t*t); + + t = tanh(t); + t = tanh(t*t); + + double dval = 2; + t = pow(t, t); + t = pow(t, t*t); + t = pow(t, dval); + t = pow(t*t, t); + t = pow(t*t, t*t); + t = pow(t*t, dval); + t = pow(dval, t); + t = pow(dval, t*t); + + t = atan2(t, t); + t = atan2(t, t*t); + t = atan2(t, dval); + t = atan2(t*t, t); + t = atan2(t*t, t*t); + t = atan2(t*t, dval); + t = atan2(dval, t); + t = atan2(dval, t*t); + + t = fmod(t, t); + t = fmod(t, t*t); + t = fmod(t, dval); + t = fmod(t*t, t); + t = fmod(t*t, t*t); + t = fmod(t*t, dval); + t = fmod(dval, t); + t = fmod(dval, t*t); + + typedef typename T::backend_type backend_type; + typedef typename backend_type::exponent_type exp_type; + exp_type e = 0; + int i = 0; + + t = ldexp(t, i); + t = ldexp(t*t, i); + t = ldexp(t, e); + t = ldexp(t*t, e); + + t = frexp(t, &i); + t = frexp(t*t, &i); + t = frexp(t, &e); + t = frexp(t*t, &e); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ +#ifdef TEST_BACKEND + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept)); +#endif +#ifdef TEST_MPF_50 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept)); +#endif +#ifdef TEST_MPFR_50 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept)); +#endif +#ifdef TEST_MPFR_6 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept > >)); +#endif +#ifdef TEST_MPFR_15 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept > >)); +#endif +#ifdef TEST_MPFR_17 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept > >)); +#endif +#ifdef TEST_MPFR_30 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept > >)); +#endif +#ifdef TEST_MPFR_50 + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept)); +#endif +#ifdef TEST_CPP_DEC_FLOAT + BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept)); +#endif + +} diff --git a/test/concepts/sf_concept_check_basic.cpp b/test/concepts/sf_concept_check_basic.cpp new file mode 100644 index 00000000..14244129 --- /dev/null +++ b/test/concepts/sf_concept_check_basic.cpp @@ -0,0 +1,149 @@ +// Copyright John Maddock 2012. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements when used with Boost.Math. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T v1, v2, v3; + int i; + (boost::math::fpclassify)(v1); + (boost::math::isfinite)(v1); + (boost::math::isnormal)(v1); + (boost::math::isnan)(v1); + (boost::math::isinf)(v1); + (boost::math::signbit)(v1); + (boost::math::copysign)(v1, v2); + (boost::math::changesign)(v1); + (boost::math::sign)(v1); + boost::math::log1p(v1); + boost::math::expm1(v1); + boost::math::cbrt(v1); + boost::math::sqrt1pm1(v1); + boost::math::powm1(v1, v2); + boost::math::hypot(v1, v2); + boost::math::sinc_pi(v1); + boost::math::sinhc_pi(v1); + boost::math::asinh(v1); + boost::math::acosh(v1); + boost::math::atanh(v1); + boost::math::sin_pi(v1); + boost::math::cos_pi(v1); + boost::math::trunc(v1); + boost::math::itrunc(v1); + boost::math::ltrunc(v1); + boost::math::round(v1); + boost::math::iround(v1); + boost::math::lround(v1); + boost::math::modf(v1, &v1); + boost::math::modf(v1, &i); + long l; + boost::math::modf(v1, &l); +#ifdef BOOST_HAS_LONG_LONG + boost::math::lltrunc(v1); + boost::math::llround(v1); + boost::long_long_type ll; + boost::math::modf(v1, &ll); +#endif + boost::math::pow<2>(v1); + boost::math::nextafter(v1, v1); + boost::math::float_next(v1); + boost::math::float_prior(v1); + boost::math::float_distance(v1, v1); + // Misc functions that don't fit elsewhere: + boost::math::expint(v1); + boost::math::expint(i); + boost::math::expint(i, v2); + boost::math::expint(i, i); + boost::math::zeta(v1); + boost::math::zeta(i); + boost::math::owens_t(v1, v2); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ + foo(); +} diff --git a/test/concepts/sf_concept_check_bessel.cpp b/test/concepts/sf_concept_check_bessel.cpp new file mode 100644 index 00000000..e6670e25 --- /dev/null +++ b/test/concepts/sf_concept_check_bessel.cpp @@ -0,0 +1,114 @@ +// Copyright John Maddock 2012. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements when used with Boost.Math. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T v1, v2, v3; + int i(0); + boost::math::cyl_neumann(v1, v2); + boost::math::cyl_neumann(i, v2); + boost::math::cyl_bessel_j(v1, v2); + boost::math::cyl_bessel_j(i, v2); + boost::math::cyl_bessel_i(v1, v2); + boost::math::cyl_bessel_i(i, v2); + boost::math::cyl_bessel_k(v1, v2); + boost::math::cyl_bessel_k(i, v2); + boost::math::sph_bessel(i, v2); + boost::math::sph_bessel(i, 1); + boost::math::sph_neumann(i, v2); + boost::math::sph_neumann(i, i); + boost::math::airy_ai(v1); + boost::math::airy_bi(v1); + boost::math::airy_ai_prime(v1); + boost::math::airy_bi_prime(v1); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ + foo(); +} diff --git a/test/concepts/sf_concept_check_elliptic.cpp b/test/concepts/sf_concept_check_elliptic.cpp new file mode 100644 index 00000000..7365f89e --- /dev/null +++ b/test/concepts/sf_concept_check_elliptic.cpp @@ -0,0 +1,120 @@ +// Copyright John Maddock 2012. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements when used with Boost.Math. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T v1, v2, v3; + boost::math::ellint_1(v1); + boost::math::ellint_1(v1, v2); + boost::math::ellint_2(v1); + boost::math::ellint_2(v1, v2); + boost::math::ellint_3(v1, v2); + boost::math::ellint_3(v1, v2, v3); + boost::math::ellint_rc(v1, v2); + boost::math::ellint_rd(v1, v2, v3); + boost::math::ellint_rf(v1, v2, v3); + boost::math::ellint_rj(v1, v2, v3, v1); + boost::math::jacobi_elliptic(v1, v2, &v1, &v2); + boost::math::jacobi_cd(v1, v2); + boost::math::jacobi_cn(v1, v2); + boost::math::jacobi_cs(v1, v2); + boost::math::jacobi_dc(v1, v2); + boost::math::jacobi_dn(v1, v2); + boost::math::jacobi_ds(v1, v2); + boost::math::jacobi_nc(v1, v2); + boost::math::jacobi_nd(v1, v2); + boost::math::jacobi_ns(v1, v2); + boost::math::jacobi_sc(v1, v2); + boost::math::jacobi_sd(v1, v2); + boost::math::jacobi_sn(v1, v2); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ + foo(); +} diff --git a/test/concepts/sf_concept_check_gamma.cpp b/test/concepts/sf_concept_check_gamma.cpp new file mode 100644 index 00000000..9ab61912 --- /dev/null +++ b/test/concepts/sf_concept_check_gamma.cpp @@ -0,0 +1,136 @@ +// Copyright John Maddock 2012. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements when used with Boost.Math. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T v1, v2, v3; + int i; + boost::math::tgamma(v1); + boost::math::tgamma1pm1(v1); + boost::math::lgamma(v1); + boost::math::lgamma(v1, &i); + boost::math::digamma(v1); + boost::math::tgamma_ratio(v1, v2); + boost::math::tgamma_delta_ratio(v1, v2); + boost::math::factorial(i); + boost::math::unchecked_factorial(i); + i = boost::math::max_factorial::value; + boost::math::double_factorial(i); + boost::math::rising_factorial(v1, i); + boost::math::falling_factorial(v1, i); + boost::math::tgamma(v1, v2); + boost::math::tgamma_lower(v1, v2); + boost::math::gamma_p(v1, v2); + boost::math::gamma_q(v1, v2); + boost::math::gamma_p_inv(v1, v2); + boost::math::gamma_q_inv(v1, v2); + boost::math::gamma_p_inva(v1, v2); + boost::math::gamma_q_inva(v1, v2); + boost::math::erf(v1); + boost::math::erfc(v1); + boost::math::erf_inv(v1); + boost::math::erfc_inv(v1); + boost::math::beta(v1, v2); + boost::math::beta(v1, v2, v3); + boost::math::betac(v1, v2, v3); + boost::math::ibeta(v1, v2, v3); + boost::math::ibetac(v1, v2, v3); + boost::math::ibeta_inv(v1, v2, v3); + boost::math::ibetac_inv(v1, v2, v3); + boost::math::ibeta_inva(v1, v2, v3); + boost::math::ibetac_inva(v1, v2, v3); + boost::math::ibeta_invb(v1, v2, v3); + boost::math::ibetac_invb(v1, v2, v3); + boost::math::gamma_p_derivative(v2, v3); + boost::math::ibeta_derivative(v1, v2, v3); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ + foo(); +} diff --git a/test/concepts/sf_concept_check_poly.cpp b/test/concepts/sf_concept_check_poly.cpp new file mode 100644 index 00000000..0bc21001 --- /dev/null +++ b/test/concepts/sf_concept_check_poly.cpp @@ -0,0 +1,111 @@ +// Copyright John Maddock 2012. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +// This tests that cpp_dec_float_50 meets our +// conceptual requirements when used with Boost.Math. +// +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +# pragma warning(disable:4800) +# pragma warning(disable:4512) +# pragma warning(disable:4127) +# pragma warning(disable:4512) +# pragma warning(disable:4503) // decorated name length exceeded, name was truncated +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \ + && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\ + && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) +# define TEST_MPF_50 +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR_50 +# define TEST_MPFR_6 +# define TEST_MPFR_15 +# define TEST_MPFR_17 +# define TEST_MPFR_30 +# define TEST_CPP_DEC_FLOAT +# define TEST_CPP_DEC_FLOAT_NO_ET + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPZ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) +#include +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30) +#include +#endif + +#include + +template +void test_extra(T) +{ + T v1, v2, v3; + boost::math::legendre_p(1, v1); + boost::math::legendre_p(1, 0, v1); + boost::math::legendre_q(1, v1); + boost::math::legendre_next(2, v1, v2, v3); + boost::math::legendre_next(2, 2, v1, v2, v3); + boost::math::laguerre(1, v1); + boost::math::laguerre(2, 1, v1); + boost::math::laguerre(2u, 1u, v1); + boost::math::laguerre_next(2, v1, v2, v3); + boost::math::laguerre_next(2, 1, v1, v2, v3); + boost::math::hermite(1, v1); + boost::math::hermite_next(2, v1, v2, v3); + boost::math::spherical_harmonic_r(2, 1, v1, v2); + boost::math::spherical_harmonic_i(2, 1, v1, v2); +} + +void foo() +{ +#ifdef TEST_BACKEND + test_extra(boost::multiprecision::concepts::mp_number_float_architype()); +#endif +#ifdef TEST_MPF_50 + test_extra(boost::multiprecision::mpf_float_50()); +#endif +#ifdef TEST_MPFR_50 + test_extra(boost::multiprecision::mpfr_float_50()); +#endif +#ifdef TEST_MPFR_6 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_15 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_17 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_MPFR_30 + test_extra(boost::multiprecision::number >()); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_extra(boost::multiprecision::cpp_dec_float_50()); +#endif +#ifdef TEST_CPP_DEC_FLOAT_NO_ET + test_extra(boost::multiprecision::number, boost::multiprecision::et_off>()); +#endif +} + +int main() +{ + foo(); +} diff --git a/test/coverage/Makefile b/test/coverage/Makefile new file mode 100644 index 00000000..5941c633 --- /dev/null +++ b/test/coverage/Makefile @@ -0,0 +1,173 @@ +# copyright John Maddock 2012 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + + +SOURCES=\ +../../../../boost/multiprecision/mpfr.hpp\ +../../../../boost/multiprecision/tommath.hpp\ +../../../../boost/multiprecision/number.hpp\ +../../../../boost/multiprecision/cpp_dec_float.hpp\ +../../../../boost/multiprecision/gmp.hpp\ +../../../../boost/multiprecision/random.hpp\ +../../../../boost/multiprecision/cpp_int.hpp\ +../../../../boost/multiprecision/miller_rabin.hpp\ +../../../../boost/multiprecision/rational_adapter.hpp\ +../../../../boost/multiprecision/concepts/mp_number_archetypes.hpp\ +../../../../boost/multiprecision/detail/big_lanczos.hpp\ +../../../../boost/multiprecision/detail/digits.hpp\ +../../../../boost/multiprecision/detail/no_et_ops.hpp\ +../../../../boost/multiprecision/detail/cpp_int_core.hpp\ +../../../../boost/multiprecision/detail/number_base.hpp\ +../../../../boost/multiprecision/detail/cpp_int_trivial_ops.hpp\ +../../../../boost/multiprecision/detail/generic_interconvert.hpp\ +../../../../boost/multiprecision/detail/number_compare.hpp\ +../../../../boost/multiprecision/detail/default_ops.hpp\ +../../../../boost/multiprecision/detail/integer_ops.hpp\ +../../../../boost/multiprecision/detail/functions/constants.hpp\ +../../../../boost/multiprecision/detail/functions/pow.hpp\ +../../../../boost/multiprecision/detail/functions/trig.hpp\ +../../../../boost/multiprecision/traits/explicit_conversion.hpp\ +../../../../boost/multiprecision/traits/is_restricted_conversion.hpp + +coverage : run + gcov test_arithmetic_cpp_int_1 test_arithmetic_cpp_int_2 test_arithmetic_cpp_int_3 test_arithmetic_cpp_dec_float test_arithmetic_concept test_arithmetic_mpz test_arithmetic_mpf test_arithmetic_mpf_50 test_arithmetic_mpq test_arithmetic_mpfr test_arithmetic_mpfr_50 test_cpp_int test_int_io test_float_io test_rational_io test_gmp_conversions test_mpfr_conversions test_cpp_int_conv + +test_arithmetic_cpp_int_1.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_CPP_INT_1 --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_cpp_int_1.o -c ../test_arithmetic.cpp + +test_arithmetic_cpp_int_1 : test_arithmetic_cpp_int_1.o + g++ -std=gnu++0x --coverage -o test_arithmetic_cpp_int_1 test_arithmetic_cpp_int_1.o + +test_arithmetic_cpp_int_2.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_CPP_INT_2 --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_cpp_int_2.o -c ../test_arithmetic.cpp + +test_arithmetic_cpp_int_2 : test_arithmetic_cpp_int_2.o + g++ -std=gnu++0x --coverage -o test_arithmetic_cpp_int_2 test_arithmetic_cpp_int_2.o + +test_arithmetic_cpp_int_3.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_CPP_INT_3 --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_cpp_int_3.o -c ../test_arithmetic.cpp + +test_arithmetic_cpp_int_3 : test_arithmetic_cpp_int_3.o + g++ -std=gnu++0x --coverage -o test_arithmetic_cpp_int_3 test_arithmetic_cpp_int_3.o + +test_arithmetic_cpp_dec_float.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_CPP_DEC_FLOAT --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_cpp_dec_float.o -c ../test_arithmetic.cpp + +test_arithmetic_cpp_dec_float : test_arithmetic_cpp_dec_float.o + g++ -std=gnu++0x --coverage -o test_arithmetic_cpp_dec_float test_arithmetic_cpp_dec_float.o + +test_arithmetic_concept.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_BACKEND --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_concept.o -c ../test_arithmetic.cpp + +test_arithmetic_concept : test_arithmetic_concept.o + g++ -std=gnu++0x --coverage -o test_arithmetic_concept test_arithmetic_concept.o + +test_arithmetic_mpz.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPZ --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpz.o -c ../test_arithmetic.cpp + +test_arithmetic_mpz : test_arithmetic_mpz.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpz test_arithmetic_mpz.o -lgmp + +test_arithmetic_mpf.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPF --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpf.o -c ../test_arithmetic.cpp + +test_arithmetic_mpf : test_arithmetic_mpf.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpf test_arithmetic_mpf.o -lgmp + +test_arithmetic_mpf_50.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPF_50 --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpf_50.o -c ../test_arithmetic.cpp + +test_arithmetic_mpf_50 : test_arithmetic_mpf_50.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpf_50 test_arithmetic_mpf_50.o -lgmp + +test_arithmetic_mpq.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPQ --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpq.o -c ../test_arithmetic.cpp + +test_arithmetic_mpq : test_arithmetic_mpq.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpq test_arithmetic_mpq.o -lgmp + +test_arithmetic_mpfr.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPFR --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpfr.o -c ../test_arithmetic.cpp + +test_arithmetic_mpfr : test_arithmetic_mpfr.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpfr test_arithmetic_mpfr.o -lmpfr -lgmp + +test_arithmetic_mpfr_50.o : ../test_arithmetic.cpp $(SOURCES) + g++ -std=gnu++0x -DTEST_MPFR_50 --coverage -g -I../../../.. -I../../../../../../trunk -o test_arithmetic_mpfr_50.o -c ../test_arithmetic.cpp + +test_arithmetic_mpfr_50 : test_arithmetic_mpfr_50.o + g++ -std=gnu++0x --coverage -o test_arithmetic_mpfr_50 test_arithmetic_mpfr_50.o -lmpfr -lgmp + +test_cpp_int.o : ../test_cpp_int.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -g -I../../../.. -I../../../../../../trunk -o test_cpp_int.o -c ../test_cpp_int.cpp + +test_cpp_int : test_cpp_int.o + g++ -std=gnu++0x --coverage -o test_cpp_int test_cpp_int.o -lgmp + +test_int_io.o : ../test_int_io.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -DTEST_MPZ -DTEST_CPP_INT -g -I../../../.. -I../../../../../../trunk -o test_int_io.o -c ../test_int_io.cpp + +test_int_io : test_int_io.o + g++ -std=gnu++0x --coverage -o test_int_io test_int_io.o -lgmp + +test_float_io.o : ../test_float_io.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -g -I../../../.. -I../../../../../../trunk -o test_float_io.o -c ../test_float_io.cpp + +test_float_io : test_float_io.o + g++ -std=gnu++0x --coverage -o test_float_io test_float_io.o -lmpfr -lgmp + +test_rational_io.o : ../test_rational_io.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -DTEST_MPQ -DTEST_CPP_INT -g -I../../../.. -I../../../../../../trunk -o test_rational_io.o -c ../test_rational_io.cpp + +test_rational_io : test_rational_io.o + g++ -std=gnu++0x --coverage -o test_rational_io test_rational_io.o -lgmp + +test_gmp_conversions.o : ../test_gmp_conversions.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -g -I../../../.. -I../../../../../../trunk -o test_gmp_conversions.o -c ../test_gmp_conversions.cpp + +test_gmp_conversions : test_gmp_conversions.o + g++ -std=gnu++0x --coverage -o test_gmp_conversions test_gmp_conversions.o -lgmp + +test_mpfr_conversions.o : ../test_mpfr_conversions.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -g -I../../../.. -I../../../../../../trunk -o test_mpfr_conversions.o -c ../test_mpfr_conversions.cpp + +test_mpfr_conversions : test_mpfr_conversions.o + g++ -std=gnu++0x --coverage -o test_mpfr_conversions test_mpfr_conversions.o -lmpfr -lgmp + +test_cpp_int_conv.o : ../test_cpp_int_conv.cpp $(SOURCES) + g++ -std=gnu++0x --coverage -g -I../../../.. -I../../../../../../trunk -o test_cpp_int_conv.o -c ../test_cpp_int_conv.cpp + +test_cpp_int_conv : test_cpp_int_conv.o + g++ -std=gnu++0x --coverage -o test_cpp_int_conv test_cpp_int_conv.o + +run : test_arithmetic_cpp_int_1 test_arithmetic_cpp_int_2 test_arithmetic_cpp_int_3 test_arithmetic_cpp_dec_float test_arithmetic_concept test_arithmetic_mpz test_arithmetic_mpf test_arithmetic_mpf_50 \ +test_arithmetic_mpq test_arithmetic_mpfr test_arithmetic_mpfr_50 test_cpp_int test_int_io test_float_io test_rational_io test_gmp_conversions test_mpfr_conversions test_cpp_int_conv + ./test_arithmetic_cpp_int_1 + ./test_arithmetic_cpp_int_2 + ./test_arithmetic_cpp_int_3 + ./test_arithmetic_cpp_dec_float + ./test_arithmetic_concept + ./test_arithmetic_mpz + ./test_arithmetic_mpf + ./test_arithmetic_mpf_50 + ./test_arithmetic_mpq + ./test_arithmetic_mpfr + ./test_arithmetic_mpfr_50 + ./test_cpp_int + ./test_int_io + ./test_float_io + ./test_rational_io + ./test_gmp_conversions + ./test_mpfr_conversions + ./test_cpp_int_conv + +clean : + rm -rf *.o *.gc* test_arithmetic_cpp_int_1 test_arithmetic_cpp_int_2 test_arithmetic_cpp_int_3 test_arithmetic_cpp_dec_float test_arithmetic_concept test_arithmetic_mpz \ + test_arithmetic_mpf test_arithmetic_mpf_50 test_arithmetic_mpq test_arithmetic_mpfr test_arithmetic_mpfr_50 test_cpp_int\ + test_int_io test_float_io test_rational_io test_gmp_conversions test_mpfr_conversions test_cpp_int_conv + + + + diff --git a/test/include_test/cpp_dec_float_include_test.cpp b/test/include_test/cpp_dec_float_include_test.cpp new file mode 100644 index 00000000..bdf09e83 --- /dev/null +++ b/test/include_test/cpp_dec_float_include_test.cpp @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include + +using namespace boost::multiprecision; + +cpp_dec_float<50> a; + + diff --git a/test/include_test/cpp_int_include_test.cpp b/test/include_test/cpp_int_include_test.cpp new file mode 100644 index 00000000..e3742612 --- /dev/null +++ b/test/include_test/cpp_int_include_test.cpp @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include + +using namespace boost::multiprecision; + +number > a; +number, et_off> b; +number, et_off> c; +number, et_off> d; +number, et_off> e; + + diff --git a/test/include_test/gmp_include_test.cpp b/test/include_test/gmp_include_test.cpp new file mode 100644 index 00000000..4b07266f --- /dev/null +++ b/test/include_test/gmp_include_test.cpp @@ -0,0 +1,14 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include + +using namespace boost::multiprecision; + +mpf_float a; +mpz_int b; +mpq_rational c; + + diff --git a/test/include_test/mpfr_include_test.cpp b/test/include_test/mpfr_include_test.cpp new file mode 100644 index 00000000..f84cbb95 --- /dev/null +++ b/test/include_test/mpfr_include_test.cpp @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include + +using namespace boost::multiprecision; + +mpfr_float a; + + diff --git a/test/include_test/tommath_include_test.cpp b/test/include_test/tommath_include_test.cpp new file mode 100644 index 00000000..bc000fef --- /dev/null +++ b/test/include_test/tommath_include_test.cpp @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#include + +using namespace boost::multiprecision; + +tom_int a; + + diff --git a/test/math/log1p_expm1_test.cpp b/test/math/log1p_expm1_test.cpp new file mode 100644 index 00000000..9472123d --- /dev/null +++ b/test/math/log1p_expm1_test.cpp @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include +#include +#include +#include + +#include "table_type.hpp" + +#include "libs/math/test/log1p_expm1_test.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that when this file is first run on a new platform many of +// these tests will fail: the default accuracy is 1 epsilon which +// is too tight for most platforms. In this situation you will +// need to cast a human eye over the error rates reported and make +// a judgement as to whether they are acceptable. Either way please +// report the results to the Boost mailing list. Acceptable rates of +// error are marked up below as a series of regular expressions that +// identify the compiler/stdlib/platform/data-type/test-data/test-function +// along with the maximum expected peek and RMS mean errors for that +// test. +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*", // test data group + ".*", // test function + 500, // Max Peek error + 100); // Max mean error + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", // test function + 500, // Max Peek error + 100); // Max mean error + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 8, // Max Peek error + 5); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test(number >(), "number >"); + test(number >(), "number >"); + test(number >(), "number >"); + // there should be at least one test with expression templates off: + test(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test(number >(), "number >"); + test(number >(), "number >"); + test(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(number >(), "number >"); + test(number >(), "number >"); + test(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/powm1_sqrtp1m1_test.cpp b/test/math/powm1_sqrtp1m1_test.cpp new file mode 100644 index 00000000..a5850b3d --- /dev/null +++ b/test/math/powm1_sqrtp1m1_test.cpp @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include +#include +#include +#include + +#include "table_type.hpp" + +#include "libs/math/test/powm1_sqrtp1m1_test.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the functions log1p and expm1. The accuracy tests +// use values generated with NTL::RR at 1000-bit precision +// and our generic versions of these functions. +// +// Note that when this file is first run on a new platform many of +// these tests will fail: the default accuracy is 1 epsilon which +// is too tight for most platforms. In this situation you will +// need to cast a human eye over the error rates reported and make +// a judgement as to whether they are acceptable. Either way please +// report the results to the Boost mailing list. Acceptable rates of +// error are marked up below as a series of regular expressions that +// identify the compiler/stdlib/platform/data-type/test-data/test-function +// along with the maximum expected peek and RMS mean errors for that +// test. +// + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", // test function + 300, // Max Peek error + 50); // Max mean error + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 15, // Max Peek error + 5); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // We test two different precisions: + // 18 decimal digits triggers Boost.Math's 64-bit long double support. + // 30 decimal digits triggers Boost.Math's 128-bit long double support. + // 35 decimal digits triggers true arbitrary precision support. + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - maybe in std::exp?? Disabled for now. + //test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number >(), "number >"); + // there should be at least one test with expression templates off: + test_powm1_sqrtp1m1(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number >(), "number >"); + test_powm1_sqrtp1m1(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/table_type.hpp b/test/math/table_type.hpp new file mode 100644 index 00000000..0b78ec0f --- /dev/null +++ b/test/math/table_type.hpp @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifndef BOOST_MP_TABLE_TYPE + +#include +#include + +struct string_table_entry +{ +private: + const char* m_data; +public: + string_table_entry(const char* p) : m_data(p) {} + + template + operator T () const + { + return static_cast(m_data); + } +}; + +inline std::ostream& operator << (std::ostream& os, string_table_entry const & what) +{ + return os << static_cast(what); +} + +template +struct table_type > +{ + typedef string_table_entry type; +}; + +#define SC_(x) string_table_entry(BOOST_STRINGIZE(x)) + +#endif + diff --git a/test/math/test_bessel_i.cpp b/test/math/test_bessel_i.cpp new file mode 100644 index 00000000..a058c070 --- /dev/null +++ b/test/math/test_bessel_i.cpp @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#define SC_(x) static_cast::type>(BOOST_STRINGIZE(x)) + +#include +#include "libs/math/test/test_bessel_i.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + // + // Catch all cases come last: + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", // test function + 500, // Max Peek error + 200); // Max mean error + + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 9 decimal digits: tests the least wide arbitrary precision code + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - maybe in std::exp?? Disabled for now. + //test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + // there should be at least one test with expression templates off: + test_bessel(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_bessel_j.cpp b/test/math/test_bessel_j.cpp new file mode 100644 index 00000000..0cdd5f51 --- /dev/null +++ b/test/math/test_bessel_j.cpp @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_bessel_j.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*J0.*Tricky.*", // test data group + ".*", 10000000000L, 5000000000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*J0.*Tricky.*", // test data group + ".*", 400000000, 400000000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*J1.*Tricky.*", // test data group + ".*", 1000000000L, 500000000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*J1.*Tricky.*", // test data group + ".*", 10000000, 5000000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*JN.*Integer.*", // test data group + ".*", 50000, 15000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*(JN|j).*|.*Tricky.*", // test data group + ".*", 70000, 7000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*(JN|j).*|.*Tricky.*", // test data group + ".*", 7000, 3000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 40, 20); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - maybe in std::exp?? Disabled for now. + //test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + // there should be at least one test with expression templates off: + test_bessel(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_bessel_k.cpp b/test/math/test_bessel_k.cpp new file mode 100644 index 00000000..0fa9dc3b --- /dev/null +++ b/test/math/test_bessel_k.cpp @@ -0,0 +1,126 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_bessel_k.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp.*", // test type(s) + ".*", // test data group + ".*", 2000, 1500); // test function + + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 3000, 1000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*large.*", // test data group + ".*", 80, 50); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 50, 15); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - maybe in std::exp?? Disabled for now. + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + // there should be at least one test with expression templates off: + test_bessel(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_bessel_y.cpp b/test/math/test_bessel_y.cpp new file mode 100644 index 00000000..8e39e399 --- /dev/null +++ b/test/math/test_bessel_y.cpp @@ -0,0 +1,152 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_bessel_y.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*(Y[nv]|y).*Random.*", // test data group + ".*", 200000, 10000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*(Y[nv]|y).*Random.*", // test data group + ".*", 70000, 4000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*Y0.*", // test data group + ".*", 3000, 2000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*Y0.*", // test data group + ".*", 800, 400); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*Yn.*", // test data group + ".*", 200000, 70000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*Yn.*", // test data group + ".*", 1700, 600); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 15000, 4000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 150, 60); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - our argument reduction in std::sin isn't accurate enough: + //test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + // there should be at least one test with expression templates off: + test_bessel(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_bessel(number >(), "number >"); + test_bessel(number >(), "number >"); + test_bessel(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_beta.cpp b/test/math/test_beta.cpp new file mode 100644 index 00000000..a372f704 --- /dev/null +++ b/test/math/test_beta.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_beta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp.*", // test type(s) + "Beta Function: Medium.*", // test data group + "boost::math::beta", 2300, 1000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp.*", // test type(s) + "Beta Function: Divergent.*", // test data group + "boost::math::beta", 2200, 1000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + "Beta Function: Small.*", // test data group + "boost::math::beta", 1000, 750); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "Beta Function: Small.*", // test data group + "boost::math::beta", 8, 5); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "Beta Function: Medium.*", // test data group + "boost::math::beta", 1000, 750); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "Beta Function: Divergent.*", // test data group + "boost::math::beta", 1000, 700); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - our argument reduction in std::sin isn't accurate enough: + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_binomial_coeff.cpp b/test/math/test_binomial_coeff.cpp new file mode 100644 index 00000000..01c7ad44 --- /dev/null +++ b/test/math/test_binomial_coeff.cpp @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_binomial_coeff.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp.*", // test type(s) + ".*", // test data group + ".*", 3000, 1500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 750, 150); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 100, 20); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - our argument reduction in std::sin isn't accurate enough: + test_binomial(number >(), "number >"); + test_binomial(number >(), "number >"); + test_binomial(number >(), "number >"); + // there should be at least one test with expression templates off: + test_binomial(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_binomial(number >(), "number >"); + test_binomial(number >(), "number >"); + test_binomial(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_binomial(number >(), "number >"); + test_binomial(number >(), "number >"); + test_binomial(number > >(), "number > >"); +#endif + return 0; +} + + + + diff --git a/test/math/test_carlson.cpp b/test/math/test_carlson.cpp new file mode 100644 index 00000000..2680c392 --- /dev/null +++ b/test/math/test_carlson.cpp @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include +#include +#include +#include "libs/math/test/test_carlson.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*RJ.*", // test data group + ".*", 2700, 250); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 40, 20); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + // We have accuracy issues with gmp_float<18> - our argument reduction in std::sin isn't accurate enough: + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + // there should be at least one test with expression templates off: + test_spots(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_cbrt.cpp b/test/math/test_cbrt.cpp new file mode 100644 index 00000000..ac07d662 --- /dev/null +++ b/test/math/test_cbrt.cpp @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_cbrt.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 5, 3); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_cbrt(number >(), "number >"); + test_cbrt(number >(), "number >"); + test_cbrt(number >(), "number >"); + // there should be at least one test with expression templates off: + test_cbrt(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_cbrt(number >(), "number >"); + test_cbrt(number >(), "number >"); + test_cbrt(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_cbrt(number >(), "number >"); + test_cbrt(number >(), "number >"); + test_cbrt(number > >(), "number > >"); +#endif + return 0; +} + + + diff --git a/test/math/test_digamma.cpp b/test/math/test_digamma.cpp new file mode 100644 index 00000000..86b8f00a --- /dev/null +++ b/test/math/test_digamma.cpp @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_digamma.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*Negative.*", // test data group + ".*", 20000, 2000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*Negative.*", // test data group + ".*", 350, 40); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 80, 30); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_digamma(number >(), "number >"); + test_digamma(number >(), "number >"); + test_digamma(number >(), "number >"); + // there should be at least one test with expression templates off: + test_digamma(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_digamma(number >(), "number >"); + test_digamma(number >(), "number >"); + test_digamma(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_digamma(number >(), "number >"); + test_digamma(number >(), "number >"); + test_digamma(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ellint_1.cpp b/test/math/test_ellint_1.cpp new file mode 100644 index 00000000..bc843e30 --- /dev/null +++ b/test/math/test_ellint_1.cpp @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_ellint_1.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 1000, 200); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 40, 20); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + // there should be at least one test with expression templates off: + test_spots(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ellint_2.cpp b/test/math/test_ellint_2.cpp new file mode 100644 index 00000000..bd8c01cf --- /dev/null +++ b/test/math/test_ellint_2.cpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_ellint_2.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 300, 200); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + // there should be at least one test with expression templates off: + test_spots(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ellint_3.cpp b/test/math/test_ellint_3.cpp new file mode 100644 index 00000000..49ffdc31 --- /dev/null +++ b/test/math/test_ellint_3.cpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_ellint_3.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*", // test data group + ".*", 3000, 500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 10000, 3000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*Large.*", // test data group + ".*", 75, 40); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 60, 30); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + // there should be at least one test with expression templates off: + test_spots(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_spots(number >(), "number >"); + test_spots(number >(), "number >"); + test_spots(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_erf.cpp b/test/math/test_erf.cpp new file mode 100644 index 00000000..925b72a4 --- /dev/null +++ b/test/math/test_erf.cpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_erf.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + "Erf Function:.*", // test data group + "boost::math::erfc?", 2200, 1500);// test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + "Inverse Erf.*", // test data group + "boost::math::erfc?_inv", 2200, 1500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "Erf Function:.*", // test data group + "boost::math::erfc?", 300, 200); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "Inverse Erf.*", // test data group + "boost::math::erfc?_inv", 60, 20); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_erf(number >(), "number >"); + test_erf(number >(), "number >"); + test_erf(number >(), "number >"); + // there should be at least one test with expression templates off: + test_erf(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_erf(number >(), "number >"); + test_erf(number >(), "number >"); + test_erf(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_erf(number >(), "number >"); + test_erf(number >(), "number >"); + test_erf(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_expint.cpp b/test/math/test_expint.cpp new file mode 100644 index 00000000..c134390b --- /dev/null +++ b/test/math/test_expint.cpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_expint.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*", // test data group + ".*", 2500, 1500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 1000, 500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float.*", // test type(s) + ".*", // test data group + ".*", 250, 100); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 250, 50); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_expint(number >(), "number >"); + test_expint(number >(), "number >"); + test_expint(number >(), "number >"); + // there should be at least one test with expression templates off: + test_expint(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_expint(number >(), "number >"); + test_expint(number >(), "number >"); + test_expint(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_expint(number >(), "number >"); + test_expint(number >(), "number >"); + test_expint(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_gamma.cpp b/test/math/test_gamma.cpp new file mode 100644 index 00000000..7e944a91 --- /dev/null +++ b/test/math/test_gamma.cpp @@ -0,0 +1,131 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_gamma.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*", // test data group + "boost::math::tgamma", 4000, 2500); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "factorials", // test data group + "boost::math::tgamma", 140, 70); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "factorials", // test data group + "boost::math::lgamma", 750, 100); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "near.*", // test data group + "boost::math::tgamma", 200, 100); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "near.*", // test data group + "boost::math::lgamma", 10000000, 10000000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + "tgamma1pm1.*", // test data group + "boost::math::tgamma1pm1", 1000, 150); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + // there should be at least one test with expression templates off: + test_gamma(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_hermite.cpp b/test/math/test_hermite.cpp new file mode 100644 index 00000000..bb1c3ac1 --- /dev/null +++ b/test/math/test_hermite.cpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_hermite.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + "boost::math::hermite", 10, 5); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_hermite(number >(), "number >"); + test_hermite(number >(), "number >"); + test_hermite(number >(), "number >"); + // there should be at least one test with expression templates off: + test_hermite(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_hermite(number >(), "number >"); + test_hermite(number >(), "number >"); + test_hermite(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_hermite(number >(), "number >"); + test_hermite(number >(), "number >"); + test_hermite(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta.cpp b/test/math/test_ibeta.cpp new file mode 100644 index 00000000..2e2233c0 --- /dev/null +++ b/test/math/test_ibeta.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 1 + +#include +#include "libs/math/test/test_ibeta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*gmp_float<18>.*", // test type(s) + "(?i).*small.*", // test data group + ".*", 3000, 1000); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + "(?i).*small.*", // test data group + ".*", 2000, 500); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*small.*", // test data group + ".*", 90, 25); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 150, 50); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*large.*", // test data group + ".*", 5000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta_2.cpp b/test/math/test_ibeta_2.cpp new file mode 100644 index 00000000..e885e095 --- /dev/null +++ b/test/math/test_ibeta_2.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 2 + +#include +#include "libs/math/test/test_ibeta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*gmp_float<18>.*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 4000, 1000); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 20000, 1000); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*small.*", // test data group + ".*", 90, 25); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 200, 50); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*large.*", // test data group + ".*", 5000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta_3.cpp b/test/math/test_ibeta_3.cpp new file mode 100644 index 00000000..bc685922 --- /dev/null +++ b/test/math/test_ibeta_3.cpp @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 3 + +#include +#include "libs/math/test/test_ibeta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*small.*", // test data group + ".*", 90, 25); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 200, 50); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*large.*", // test data group + ".*", 6000000, 500000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta_4.cpp b/test/math/test_ibeta_4.cpp new file mode 100644 index 00000000..754f6b59 --- /dev/null +++ b/test/math/test_ibeta_4.cpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 4 + +#include +#include "libs/math/test/test_ibeta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*small.*", // test data group + ".*", 4000, 1000); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*small.*", // test data group + ".*", 90, 25); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*medium.*", // test data group + ".*", 200, 50); // test function + add_expected_result( + "[^|]*", // compiler + "[^|]*", // stdlib + "[^|]*", // platform + ".*", // test type(s) + "(?i).*large.*", // test data group + ".*", 5000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta_inv_1.cpp b/test/math/test_ibeta_inv_1.cpp new file mode 100644 index 00000000..47cd48f7 --- /dev/null +++ b/test/math/test_ibeta_inv_1.cpp @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 4 + +#include +#include "libs/math/test/test_ibeta_inv.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 50000000, 7000000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 1000000, 100000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + //test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_ibeta_inv_ab_4.cpp b/test/math/test_ibeta_inv_ab_4.cpp new file mode 100644 index 00000000..60bd3930 --- /dev/null +++ b/test/math/test_ibeta_inv_ab_4.cpp @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#define TEST_DATA 4 +#define FULL_TEST + +#include +#include "libs/math/test/test_ibeta_inv_ab.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 10000, 1000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + //test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_beta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_beta(number >(), "number >"); + test_beta(number >(), "number >"); + test_beta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_igamma.cpp b/test/math/test_igamma.cpp new file mode 100644 index 00000000..5f544f4f --- /dev/null +++ b/test/math/test_igamma.cpp @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" + +#include +#include "libs/math/test/test_igamma.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*large.*", // test data group + ".*", 20000000L, 1000000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 7000, 2000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + // there should be at least one test with expression templates off: + test_gamma(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_igamma_inv.cpp b/test/math/test_igamma_inv.cpp new file mode 100644 index 00000000..2cb4c4d9 --- /dev/null +++ b/test/math/test_igamma_inv.cpp @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_igamma_inv.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*small.*", // test data group + ".*", 2000000000L, 300000000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*small.*", // test data group + ".*", 30000000L, 20000000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*small.*", // test data group + ".*", 10000000L, 2500000L); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 7000, 2000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + // there should be at least one test with expression templates off: + test_gamma(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_igamma_inva.cpp b/test/math/test_igamma_inva.cpp new file mode 100644 index 00000000..5724ed7d --- /dev/null +++ b/test/math/test_igamma_inva.cpp @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_SMALL_CONSTANT(x) x + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_igamma_inva.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 7000, 2000); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + // there should be at least one test with expression templates off: + test_gamma(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_gamma(number >(), "number >"); + test_gamma(number >(), "number >"); + test_gamma(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_laguerre.cpp b/test/math/test_laguerre.cpp new file mode 100644 index 00000000..6b6aab15 --- /dev/null +++ b/test/math/test_laguerre.cpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_laguerre.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 7000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_laguerre(number >(), "number >"); + test_laguerre(number >(), "number >"); + test_laguerre(number >(), "number >"); + // there should be at least one test with expression templates off: + test_laguerre(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_laguerre(number >(), "number >"); + test_laguerre(number >(), "number >"); + test_laguerre(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_laguerre(number >(), "number >"); + test_laguerre(number >(), "number >"); + test_laguerre(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_legendre.cpp b/test/math/test_legendre.cpp new file mode 100644 index 00000000..6143b020 --- /dev/null +++ b/test/math/test_legendre.cpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_legendre.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 6000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_legendre_p(number >(), "number >"); + test_legendre_p(number >(), "number >"); + test_legendre_p(number >(), "number >"); + // there should be at least one test with expression templates off: + test_legendre_p(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_legendre_p(number >(), "number >"); + test_legendre_p(number >(), "number >"); + test_legendre_p(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_legendre_p(number >(), "number >"); + test_legendre_p(number >(), "number >"); + test_legendre_p(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_tgamma_ratio.cpp b/test/math/test_tgamma_ratio.cpp new file mode 100644 index 00000000..5c27f269 --- /dev/null +++ b/test/math/test_tgamma_ratio.cpp @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_tgamma_ratio.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*gmp_float<18>.*", // test type(s) + ".*", // test data group + ".*", 4000, 2000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*mpfr_float_backend<18>.*", // test type(s) + ".*", // test data group + ".*", 20000, 7000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 2000, 500); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number >(), "number >"); + // there should be at least one test with expression templates off: + test_tgamma_ratio(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number >(), "number >"); + test_tgamma_ratio(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/math/test_zeta.cpp b/test/math/test_zeta.cpp new file mode 100644 index 00000000..003f7abf --- /dev/null +++ b/test/math/test_zeta.cpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "table_type.hpp" +#define TEST_UDT + +#include +#include "libs/math/test/test_zeta.hpp" + +void expected_results() +{ + // + // Define the max and mean errors expected for + // various compilers and platforms. + // + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*Random values less than 1", // test data group + ".*", 6000, 3000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + ".*", // test type(s) + ".*", // test data group + ".*", 1000, 200); // test function + // + // Finish off by printing out the compiler/stdlib/platform names, + // we do this to make it easier to mark up expected error rates. + // + std::cout << "Tests run with " << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl; +} + + +int test_main(int, char* []) +{ + using namespace boost::multiprecision; + expected_results(); + // + // Test at: + // 9 decimal digits: tests the least wide arbitrary precision code + // 18 decimal digits: tests 80-bit long double approximations + // 30 decimal digits: tests 128-bit long double approximations + // 35 decimal digits: tests arbitrary precision code + // +#ifdef TEST_MPF_50 + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); + // there should be at least one test with expression templates off: + test_zeta(number, et_off>(), "number, et_off>"); +#endif +#ifdef TEST_MPFR_50 + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); + test_zeta(number >(), "number >"); + test_zeta(number > >(), "number > >"); +#endif + return 0; +} + diff --git a/test/string_data.ipp b/test/string_data.ipp new file mode 100644 index 00000000..824940ad --- /dev/null +++ b/test/string_data.ipp @@ -0,0 +1,40 @@ + {{ "1e+08", "1.e+08", "+1e+08", "1.2e+08", "+1.2e+08", "1.2e+08", "123456789.0", "123456789.0", "+123456789.0", "1.2e+08", "1.2e+08", "+1.2e+08", "1.23e+08", "+1.23e+08", "1.23e+08", "123456789.00", "123456789.00", "+123456789.00", "1.23e+08", "1.23e+08", "+1.23e+08", "1.235e+08", "+1.235e+08", "1.235e+08", "123456789.000", "123456789.000", "+123456789.000", "1.235e+08", "1.235e+08", "+1.235e+08", "1.2346e+08", "+1.2346e+08", "1.2346e+08", "123456789.0000", "123456789.0000", "+123456789.0000", "1.2346e+08", "1.2346e+08", "+1.2346e+08", "1.23457e+08", "+1.23457e+08", "1.23457e+08", "123456789.00000", "123456789.00000", "+123456789.00000", "1.23457e+08", "1.23457e+08", "+1.23457e+08", "1.234568e+08", "+1.234568e+08", "1.234568e+08", "123456789.000000", "123456789.000000", "+123456789.000000", "1.234568e+08", "1.234568e+08", "+1.234568e+08", "1.2345679e+08", "+1.2345679e+08", "1.2345679e+08", "123456789.0000000", "123456789.0000000", "+123456789.0000000", "1.2345679e+08", "1.2345679e+08", "+1.2345679e+08", "1.23456789e+08", "+1.23456789e+08", "1.23456789e+08", "123456789.00000000", "123456789.00000000", "+123456789.00000000", "123456789", "123456789.", "+123456789", "1.234567890e+08", "+1.234567890e+08", "1.234567890e+08", "123456789.000000000", "123456789.000000000", "+123456789.000000000", "123456789", "123456789.0", "+123456789", "1.2345678900e+08", "+1.2345678900e+08", "1.2345678900e+08", "123456789.0000000000", "123456789.0000000000", "+123456789.0000000000", "123456789", "123456789.00", "+123456789", "1.23456789000e+08", "+1.23456789000e+08", "1.23456789000e+08", "123456789.00000000000", "123456789.00000000000", "+123456789.00000000000", "123456789", "123456789.000", "+123456789", "1.234567890000e+08", "+1.234567890000e+08", "1.234567890000e+08", "123456789.000000000000", "123456789.000000000000", "+123456789.000000000000", "123456789", "123456789.0000", "+123456789", "1.2345678900000e+08", "+1.2345678900000e+08", "1.2345678900000e+08", "123456789.0000000000000", "123456789.0000000000000", "+123456789.0000000000000", }}, + {{ "-1e+08", "-1.e+08", "-1e+08", "-1.2e+08", "-1.2e+08", "-1.2e+08", "-123456789.0", "-123456789.0", "-123456789.0", "-1.2e+08", "-1.2e+08", "-1.2e+08", "-1.23e+08", "-1.23e+08", "-1.23e+08", "-123456789.00", "-123456789.00", "-123456789.00", "-1.23e+08", "-1.23e+08", "-1.23e+08", "-1.235e+08", "-1.235e+08", "-1.235e+08", "-123456789.000", "-123456789.000", "-123456789.000", "-1.235e+08", "-1.235e+08", "-1.235e+08", "-1.2346e+08", "-1.2346e+08", "-1.2346e+08", "-123456789.0000", "-123456789.0000", "-123456789.0000", "-1.2346e+08", "-1.2346e+08", "-1.2346e+08", "-1.23457e+08", "-1.23457e+08", "-1.23457e+08", "-123456789.00000", "-123456789.00000", "-123456789.00000", "-1.23457e+08", "-1.23457e+08", "-1.23457e+08", "-1.234568e+08", "-1.234568e+08", "-1.234568e+08", "-123456789.000000", "-123456789.000000", "-123456789.000000", "-1.234568e+08", "-1.234568e+08", "-1.234568e+08", "-1.2345679e+08", "-1.2345679e+08", "-1.2345679e+08", "-123456789.0000000", "-123456789.0000000", "-123456789.0000000", "-1.2345679e+08", "-1.2345679e+08", "-1.2345679e+08", "-1.23456789e+08", "-1.23456789e+08", "-1.23456789e+08", "-123456789.00000000", "-123456789.00000000", "-123456789.00000000", "-123456789", "-123456789.", "-123456789", "-1.234567890e+08", "-1.234567890e+08", "-1.234567890e+08", "-123456789.000000000", "-123456789.000000000", "-123456789.000000000", "-123456789", "-123456789.0", "-123456789", "-1.2345678900e+08", "-1.2345678900e+08", "-1.2345678900e+08", "-123456789.0000000000", "-123456789.0000000000", "-123456789.0000000000", "-123456789", "-123456789.00", "-123456789", "-1.23456789000e+08", "-1.23456789000e+08", "-1.23456789000e+08", "-123456789.00000000000", "-123456789.00000000000", "-123456789.00000000000", "-123456789", "-123456789.000", "-123456789", "-1.234567890000e+08", "-1.234567890000e+08", "-1.234567890000e+08", "-123456789.000000000000", "-123456789.000000000000", "-123456789.000000000000", "-123456789", "-123456789.0000", "-123456789", "-1.2345678900000e+08", "-1.2345678900000e+08", "-1.2345678900000e+08", "-123456789.0000000000000", "-123456789.0000000000000", "-123456789.0000000000000", }}, + {{ "2e+07", "2.e+07", "+2e+07", "1.5e+07", "+1.5e+07", "1.5e+07", "15432098.6", "15432098.6", "+15432098.6", "1.5e+07", "1.5e+07", "+1.5e+07", "1.54e+07", "+1.54e+07", "1.54e+07", "15432098.62", "15432098.62", "+15432098.62", "1.54e+07", "1.54e+07", "+1.54e+07", "1.543e+07", "+1.543e+07", "1.543e+07", "15432098.625", "15432098.625", "+15432098.625", "1.543e+07", "1.543e+07", "+1.543e+07", "1.5432e+07", "+1.5432e+07", "1.5432e+07", "15432098.6250", "15432098.6250", "+15432098.6250", "1.5432e+07", "1.5432e+07", "+1.5432e+07", "1.54321e+07", "+1.54321e+07", "1.54321e+07", "15432098.62500", "15432098.62500", "+15432098.62500", "1.54321e+07", "1.54321e+07", "+1.54321e+07", "1.543210e+07", "+1.543210e+07", "1.543210e+07", "15432098.625000", "15432098.625000", "+15432098.625000", "1.54321e+07", "1.543210e+07", "+1.54321e+07", "1.5432099e+07", "+1.5432099e+07", "1.5432099e+07", "15432098.6250000", "15432098.6250000", "+15432098.6250000", "15432099", "15432099.", "+15432099", "1.54320986e+07", "+1.54320986e+07", "1.54320986e+07", "15432098.62500000", "15432098.62500000", "+15432098.62500000", "15432098.6", "15432098.6", "+15432098.6", "1.543209862e+07", "+1.543209862e+07", "1.543209862e+07", "15432098.625000000", "15432098.625000000", "+15432098.625000000", "15432098.62", "15432098.62", "+15432098.62", "1.5432098625e+07", "+1.5432098625e+07", "1.5432098625e+07", "15432098.6250000000", "15432098.6250000000", "+15432098.6250000000", "15432098.625", "15432098.625", "+15432098.625", "1.54320986250e+07", "+1.54320986250e+07", "1.54320986250e+07", "15432098.62500000000", "15432098.62500000000", "+15432098.62500000000", "15432098.625", "15432098.6250", "+15432098.625", "1.543209862500e+07", "+1.543209862500e+07", "1.543209862500e+07", "15432098.625000000000", "15432098.625000000000", "+15432098.625000000000", "15432098.625", "15432098.62500", "+15432098.625", "1.5432098625000e+07", "+1.5432098625000e+07", "1.5432098625000e+07", "15432098.6250000000000", "15432098.6250000000000", "+15432098.6250000000000", }}, + {{ "-2e+07", "-2.e+07", "-2e+07", "-1.5e+07", "-1.5e+07", "-1.5e+07", "-15432098.6", "-15432098.6", "-15432098.6", "-1.5e+07", "-1.5e+07", "-1.5e+07", "-1.54e+07", "-1.54e+07", "-1.54e+07", "-15432098.62", "-15432098.62", "-15432098.62", "-1.54e+07", "-1.54e+07", "-1.54e+07", "-1.543e+07", "-1.543e+07", "-1.543e+07", "-15432098.625", "-15432098.625", "-15432098.625", "-1.543e+07", "-1.543e+07", "-1.543e+07", "-1.5432e+07", "-1.5432e+07", "-1.5432e+07", "-15432098.6250", "-15432098.6250", "-15432098.6250", "-1.5432e+07", "-1.5432e+07", "-1.5432e+07", "-1.54321e+07", "-1.54321e+07", "-1.54321e+07", "-15432098.62500", "-15432098.62500", "-15432098.62500", "-1.54321e+07", "-1.54321e+07", "-1.54321e+07", "-1.543210e+07", "-1.543210e+07", "-1.543210e+07", "-15432098.625000", "-15432098.625000", "-15432098.625000", "-1.54321e+07", "-1.543210e+07", "-1.54321e+07", "-1.5432099e+07", "-1.5432099e+07", "-1.5432099e+07", "-15432098.6250000", "-15432098.6250000", "-15432098.6250000", "-15432099", "-15432099.", "-15432099", "-1.54320986e+07", "-1.54320986e+07", "-1.54320986e+07", "-15432098.62500000", "-15432098.62500000", "-15432098.62500000", "-15432098.6", "-15432098.6", "-15432098.6", "-1.543209862e+07", "-1.543209862e+07", "-1.543209862e+07", "-15432098.625000000", "-15432098.625000000", "-15432098.625000000", "-15432098.62", "-15432098.62", "-15432098.62", "-1.5432098625e+07", "-1.5432098625e+07", "-1.5432098625e+07", "-15432098.6250000000", "-15432098.6250000000", "-15432098.6250000000", "-15432098.625", "-15432098.625", "-15432098.625", "-1.54320986250e+07", "-1.54320986250e+07", "-1.54320986250e+07", "-15432098.62500000000", "-15432098.62500000000", "-15432098.62500000000", "-15432098.625", "-15432098.6250", "-15432098.625", "-1.543209862500e+07", "-1.543209862500e+07", "-1.543209862500e+07", "-15432098.625000000000", "-15432098.625000000000", "-15432098.625000000000", "-15432098.625", "-15432098.62500", "-15432098.625", "-1.5432098625000e+07", "-1.5432098625000e+07", "-1.5432098625000e+07", "-15432098.6250000000000", "-15432098.6250000000000", "-15432098.6250000000000", }}, + {{ "2e+06", "2.e+06", "+2e+06", "1.9e+06", "+1.9e+06", "1.9e+06", "1929012.3", "1929012.3", "+1929012.3", "1.9e+06", "1.9e+06", "+1.9e+06", "1.93e+06", "+1.93e+06", "1.93e+06", "1929012.33", "1929012.33", "+1929012.33", "1.93e+06", "1.93e+06", "+1.93e+06", "1.929e+06", "+1.929e+06", "1.929e+06", "1929012.328", "1929012.328", "+1929012.328", "1.929e+06", "1.929e+06", "+1.929e+06", "1.9290e+06", "+1.9290e+06", "1.9290e+06", "1929012.3281", "1929012.3281", "+1929012.3281", "1.929e+06", "1.9290e+06", "+1.929e+06", "1.92901e+06", "+1.92901e+06", "1.92901e+06", "1929012.32812", "1929012.32812", "+1929012.32812", "1.92901e+06", "1.92901e+06", "+1.92901e+06", "1.929012e+06", "+1.929012e+06", "1.929012e+06", "1929012.328125", "1929012.328125", "+1929012.328125", "1929012", "1929012.", "+1929012", "1.9290123e+06", "+1.9290123e+06", "1.9290123e+06", "1929012.3281250", "1929012.3281250", "+1929012.3281250", "1929012.3", "1929012.3", "+1929012.3", "1.92901233e+06", "+1.92901233e+06", "1.92901233e+06", "1929012.32812500", "1929012.32812500", "+1929012.32812500", "1929012.33", "1929012.33", "+1929012.33", "1.929012328e+06", "+1.929012328e+06", "1.929012328e+06", "1929012.328125000", "1929012.328125000", "+1929012.328125000", "1929012.328", "1929012.328", "+1929012.328", "1.9290123281e+06", "+1.9290123281e+06", "1.9290123281e+06", "1929012.3281250000", "1929012.3281250000", "+1929012.3281250000", "1929012.3281", "1929012.3281", "+1929012.3281", "1.92901232812e+06", "+1.92901232812e+06", "1.92901232812e+06", "1929012.32812500000", "1929012.32812500000", "+1929012.32812500000", "1929012.32812", "1929012.32812", "+1929012.32812", "1.929012328125e+06", "+1.929012328125e+06", "1.929012328125e+06", "1929012.328125000000", "1929012.328125000000", "+1929012.328125000000", "1929012.328125", "1929012.328125", "+1929012.328125", "1.9290123281250e+06", "+1.9290123281250e+06", "1.9290123281250e+06", "1929012.3281250000000", "1929012.3281250000000", "+1929012.3281250000000", }}, + {{ "-2e+06", "-2.e+06", "-2e+06", "-1.9e+06", "-1.9e+06", "-1.9e+06", "-1929012.3", "-1929012.3", "-1929012.3", "-1.9e+06", "-1.9e+06", "-1.9e+06", "-1.93e+06", "-1.93e+06", "-1.93e+06", "-1929012.33", "-1929012.33", "-1929012.33", "-1.93e+06", "-1.93e+06", "-1.93e+06", "-1.929e+06", "-1.929e+06", "-1.929e+06", "-1929012.328", "-1929012.328", "-1929012.328", "-1.929e+06", "-1.929e+06", "-1.929e+06", "-1.9290e+06", "-1.9290e+06", "-1.9290e+06", "-1929012.3281", "-1929012.3281", "-1929012.3281", "-1.929e+06", "-1.9290e+06", "-1.929e+06", "-1.92901e+06", "-1.92901e+06", "-1.92901e+06", "-1929012.32812", "-1929012.32812", "-1929012.32812", "-1.92901e+06", "-1.92901e+06", "-1.92901e+06", "-1.929012e+06", "-1.929012e+06", "-1.929012e+06", "-1929012.328125", "-1929012.328125", "-1929012.328125", "-1929012", "-1929012.", "-1929012", "-1.9290123e+06", "-1.9290123e+06", "-1.9290123e+06", "-1929012.3281250", "-1929012.3281250", "-1929012.3281250", "-1929012.3", "-1929012.3", "-1929012.3", "-1.92901233e+06", "-1.92901233e+06", "-1.92901233e+06", "-1929012.32812500", "-1929012.32812500", "-1929012.32812500", "-1929012.33", "-1929012.33", "-1929012.33", "-1.929012328e+06", "-1.929012328e+06", "-1.929012328e+06", "-1929012.328125000", "-1929012.328125000", "-1929012.328125000", "-1929012.328", "-1929012.328", "-1929012.328", "-1.9290123281e+06", "-1.9290123281e+06", "-1.9290123281e+06", "-1929012.3281250000", "-1929012.3281250000", "-1929012.3281250000", "-1929012.3281", "-1929012.3281", "-1929012.3281", "-1.92901232812e+06", "-1.92901232812e+06", "-1.92901232812e+06", "-1929012.32812500000", "-1929012.32812500000", "-1929012.32812500000", "-1929012.32812", "-1929012.32812", "-1929012.32812", "-1.929012328125e+06", "-1.929012328125e+06", "-1.929012328125e+06", "-1929012.328125000000", "-1929012.328125000000", "-1929012.328125000000", "-1929012.328125", "-1929012.328125", "-1929012.328125", "-1.9290123281250e+06", "-1.9290123281250e+06", "-1.9290123281250e+06", "-1929012.3281250000000", "-1929012.3281250000000", "-1929012.3281250000000", }}, + {{ "2e+05", "2.e+05", "+2e+05", "2.4e+05", "+2.4e+05", "2.4e+05", "241126.5", "241126.5", "+241126.5", "2.4e+05", "2.4e+05", "+2.4e+05", "2.41e+05", "+2.41e+05", "2.41e+05", "241126.54", "241126.54", "+241126.54", "2.41e+05", "2.41e+05", "+2.41e+05", "2.411e+05", "+2.411e+05", "2.411e+05", "241126.541", "241126.541", "+241126.541", "2.411e+05", "2.411e+05", "+2.411e+05", "2.4113e+05", "+2.4113e+05", "2.4113e+05", "241126.5410", "241126.5410", "+241126.5410", "2.4113e+05", "2.4113e+05", "+2.4113e+05", "2.41127e+05", "+2.41127e+05", "2.41127e+05", "241126.54102", "241126.54102", "+241126.54102", "241127", "241127.", "+241127", "2.411265e+05", "+2.411265e+05", "2.411265e+05", "241126.541016", "241126.541016", "+241126.541016", "241126.5", "241126.5", "+241126.5", "2.4112654e+05", "+2.4112654e+05", "2.4112654e+05", "241126.5410156", "241126.5410156", "+241126.5410156", "241126.54", "241126.54", "+241126.54", "2.41126541e+05", "+2.41126541e+05", "2.41126541e+05", "241126.54101562", "241126.54101562", "+241126.54101562", "241126.541", "241126.541", "+241126.541", "2.411265410e+05", "+2.411265410e+05", "2.411265410e+05", "241126.541015625", "241126.541015625", "+241126.541015625", "241126.541", "241126.5410", "+241126.541", "2.4112654102e+05", "+2.4112654102e+05", "2.4112654102e+05", "241126.5410156250", "241126.5410156250", "+241126.5410156250", "241126.54102", "241126.54102", "+241126.54102", "2.41126541016e+05", "+2.41126541016e+05", "2.41126541016e+05", "241126.54101562500", "241126.54101562500", "+241126.54101562500", "241126.541016", "241126.541016", "+241126.541016", "2.411265410156e+05", "+2.411265410156e+05", "2.411265410156e+05", "241126.541015625000", "241126.541015625000", "+241126.541015625000", "241126.5410156", "241126.5410156", "+241126.5410156", "2.4112654101562e+05", "+2.4112654101562e+05", "2.4112654101562e+05", "241126.5410156250000", "241126.5410156250000", "+241126.5410156250000", }}, + {{ "-2e+05", "-2.e+05", "-2e+05", "-2.4e+05", "-2.4e+05", "-2.4e+05", "-241126.5", "-241126.5", "-241126.5", "-2.4e+05", "-2.4e+05", "-2.4e+05", "-2.41e+05", "-2.41e+05", "-2.41e+05", "-241126.54", "-241126.54", "-241126.54", "-2.41e+05", "-2.41e+05", "-2.41e+05", "-2.411e+05", "-2.411e+05", "-2.411e+05", "-241126.541", "-241126.541", "-241126.541", "-2.411e+05", "-2.411e+05", "-2.411e+05", "-2.4113e+05", "-2.4113e+05", "-2.4113e+05", "-241126.5410", "-241126.5410", "-241126.5410", "-2.4113e+05", "-2.4113e+05", "-2.4113e+05", "-2.41127e+05", "-2.41127e+05", "-2.41127e+05", "-241126.54102", "-241126.54102", "-241126.54102", "-241127", "-241127.", "-241127", "-2.411265e+05", "-2.411265e+05", "-2.411265e+05", "-241126.541016", "-241126.541016", "-241126.541016", "-241126.5", "-241126.5", "-241126.5", "-2.4112654e+05", "-2.4112654e+05", "-2.4112654e+05", "-241126.5410156", "-241126.5410156", "-241126.5410156", "-241126.54", "-241126.54", "-241126.54", "-2.41126541e+05", "-2.41126541e+05", "-2.41126541e+05", "-241126.54101562", "-241126.54101562", "-241126.54101562", "-241126.541", "-241126.541", "-241126.541", "-2.411265410e+05", "-2.411265410e+05", "-2.411265410e+05", "-241126.541015625", "-241126.541015625", "-241126.541015625", "-241126.541", "-241126.5410", "-241126.541", "-2.4112654102e+05", "-2.4112654102e+05", "-2.4112654102e+05", "-241126.5410156250", "-241126.5410156250", "-241126.5410156250", "-241126.54102", "-241126.54102", "-241126.54102", "-2.41126541016e+05", "-2.41126541016e+05", "-2.41126541016e+05", "-241126.54101562500", "-241126.54101562500", "-241126.54101562500", "-241126.541016", "-241126.541016", "-241126.541016", "-2.411265410156e+05", "-2.411265410156e+05", "-2.411265410156e+05", "-241126.541015625000", "-241126.541015625000", "-241126.541015625000", "-241126.5410156", "-241126.5410156", "-241126.5410156", "-2.4112654101562e+05", "-2.4112654101562e+05", "-2.4112654101562e+05", "-241126.5410156250000", "-241126.5410156250000", "-241126.5410156250000", }}, + {{ "3e+04", "3.e+04", "+3e+04", "3.0e+04", "+3.0e+04", "3.0e+04", "30140.8", "30140.8", "+30140.8", "3e+04", "3.0e+04", "+3e+04", "3.01e+04", "+3.01e+04", "3.01e+04", "30140.82", "30140.82", "+30140.82", "3.01e+04", "3.01e+04", "+3.01e+04", "3.014e+04", "+3.014e+04", "3.014e+04", "30140.818", "30140.818", "+30140.818", "3.014e+04", "3.014e+04", "+3.014e+04", "3.0141e+04", "+3.0141e+04", "3.0141e+04", "30140.8176", "30140.8176", "+30140.8176", "30141", "30141.", "+30141", "3.01408e+04", "+3.01408e+04", "3.01408e+04", "30140.81763", "30140.81763", "+30140.81763", "30140.8", "30140.8", "+30140.8", "3.014082e+04", "+3.014082e+04", "3.014082e+04", "30140.817627", "30140.817627", "+30140.817627", "30140.82", "30140.82", "+30140.82", "3.0140818e+04", "+3.0140818e+04", "3.0140818e+04", "30140.8176270", "30140.8176270", "+30140.8176270", "30140.818", "30140.818", "+30140.818", "3.01408176e+04", "+3.01408176e+04", "3.01408176e+04", "30140.81762695", "30140.81762695", "+30140.81762695", "30140.8176", "30140.8176", "+30140.8176", "3.014081763e+04", "+3.014081763e+04", "3.014081763e+04", "30140.817626953", "30140.817626953", "+30140.817626953", "30140.81763", "30140.81763", "+30140.81763", "3.0140817627e+04", "+3.0140817627e+04", "3.0140817627e+04", "30140.8176269531", "30140.8176269531", "+30140.8176269531", "30140.817627", "30140.817627", "+30140.817627", "3.01408176270e+04", "+3.01408176270e+04", "3.01408176270e+04", "30140.81762695312", "30140.81762695312", "+30140.81762695312", "30140.817627", "30140.8176270", "+30140.817627", "3.014081762695e+04", "+3.014081762695e+04", "3.014081762695e+04", "30140.817626953125", "30140.817626953125", "+30140.817626953125", "30140.81762695", "30140.81762695", "+30140.81762695", "3.0140817626953e+04", "+3.0140817626953e+04", "3.0140817626953e+04", "30140.8176269531250", "30140.8176269531250", "+30140.8176269531250", }}, + {{ "-3e+04", "-3.e+04", "-3e+04", "-3.0e+04", "-3.0e+04", "-3.0e+04", "-30140.8", "-30140.8", "-30140.8", "-3e+04", "-3.0e+04", "-3e+04", "-3.01e+04", "-3.01e+04", "-3.01e+04", "-30140.82", "-30140.82", "-30140.82", "-3.01e+04", "-3.01e+04", "-3.01e+04", "-3.014e+04", "-3.014e+04", "-3.014e+04", "-30140.818", "-30140.818", "-30140.818", "-3.014e+04", "-3.014e+04", "-3.014e+04", "-3.0141e+04", "-3.0141e+04", "-3.0141e+04", "-30140.8176", "-30140.8176", "-30140.8176", "-30141", "-30141.", "-30141", "-3.01408e+04", "-3.01408e+04", "-3.01408e+04", "-30140.81763", "-30140.81763", "-30140.81763", "-30140.8", "-30140.8", "-30140.8", "-3.014082e+04", "-3.014082e+04", "-3.014082e+04", "-30140.817627", "-30140.817627", "-30140.817627", "-30140.82", "-30140.82", "-30140.82", "-3.0140818e+04", "-3.0140818e+04", "-3.0140818e+04", "-30140.8176270", "-30140.8176270", "-30140.8176270", "-30140.818", "-30140.818", "-30140.818", "-3.01408176e+04", "-3.01408176e+04", "-3.01408176e+04", "-30140.81762695", "-30140.81762695", "-30140.81762695", "-30140.8176", "-30140.8176", "-30140.8176", "-3.014081763e+04", "-3.014081763e+04", "-3.014081763e+04", "-30140.817626953", "-30140.817626953", "-30140.817626953", "-30140.81763", "-30140.81763", "-30140.81763", "-3.0140817627e+04", "-3.0140817627e+04", "-3.0140817627e+04", "-30140.8176269531", "-30140.8176269531", "-30140.8176269531", "-30140.817627", "-30140.817627", "-30140.817627", "-3.01408176270e+04", "-3.01408176270e+04", "-3.01408176270e+04", "-30140.81762695312", "-30140.81762695312", "-30140.81762695312", "-30140.817627", "-30140.8176270", "-30140.817627", "-3.014081762695e+04", "-3.014081762695e+04", "-3.014081762695e+04", "-30140.817626953125", "-30140.817626953125", "-30140.817626953125", "-30140.81762695", "-30140.81762695", "-30140.81762695", "-3.0140817626953e+04", "-3.0140817626953e+04", "-3.0140817626953e+04", "-30140.8176269531250", "-30140.8176269531250", "-30140.8176269531250", }}, + {{ "4e+03", "4.e+03", "+4e+03", "3.8e+03", "+3.8e+03", "3.8e+03", "3767.6", "3767.6", "+3767.6", "3.8e+03", "3.8e+03", "+3.8e+03", "3.77e+03", "+3.77e+03", "3.77e+03", "3767.60", "3767.60", "+3767.60", "3.77e+03", "3.77e+03", "+3.77e+03", "3.768e+03", "+3.768e+03", "3.768e+03", "3767.602", "3767.602", "+3767.602", "3768", "3768.", "+3768", "3.7676e+03", "+3.7676e+03", "3.7676e+03", "3767.6022", "3767.6022", "+3767.6022", "3767.6", "3767.6", "+3767.6", "3.76760e+03", "+3.76760e+03", "3.76760e+03", "3767.60220", "3767.60220", "+3767.60220", "3767.6", "3767.60", "+3767.6", "3.767602e+03", "+3.767602e+03", "3.767602e+03", "3767.602203", "3767.602203", "+3767.602203", "3767.602", "3767.602", "+3767.602", "3.7676022e+03", "+3.7676022e+03", "3.7676022e+03", "3767.6022034", "3767.6022034", "+3767.6022034", "3767.6022", "3767.6022", "+3767.6022", "3.76760220e+03", "+3.76760220e+03", "3.76760220e+03", "3767.60220337", "3767.60220337", "+3767.60220337", "3767.6022", "3767.60220", "+3767.6022", "3.767602203e+03", "+3.767602203e+03", "3.767602203e+03", "3767.602203369", "3767.602203369", "+3767.602203369", "3767.602203", "3767.602203", "+3767.602203", "3.7676022034e+03", "+3.7676022034e+03", "3.7676022034e+03", "3767.6022033691", "3767.6022033691", "+3767.6022033691", "3767.6022034", "3767.6022034", "+3767.6022034", "3.76760220337e+03", "+3.76760220337e+03", "3.76760220337e+03", "3767.60220336914", "3767.60220336914", "+3767.60220336914", "3767.60220337", "3767.60220337", "+3767.60220337", "3.767602203369e+03", "+3.767602203369e+03", "3.767602203369e+03", "3767.602203369141", "3767.602203369141", "+3767.602203369141", "3767.602203369", "3767.602203369", "+3767.602203369", "3.7676022033691e+03", "+3.7676022033691e+03", "3.7676022033691e+03", "3767.6022033691406", "3767.6022033691406", "+3767.6022033691406", }}, + {{ "-4e+03", "-4.e+03", "-4e+03", "-3.8e+03", "-3.8e+03", "-3.8e+03", "-3767.6", "-3767.6", "-3767.6", "-3.8e+03", "-3.8e+03", "-3.8e+03", "-3.77e+03", "-3.77e+03", "-3.77e+03", "-3767.60", "-3767.60", "-3767.60", "-3.77e+03", "-3.77e+03", "-3.77e+03", "-3.768e+03", "-3.768e+03", "-3.768e+03", "-3767.602", "-3767.602", "-3767.602", "-3768", "-3768.", "-3768", "-3.7676e+03", "-3.7676e+03", "-3.7676e+03", "-3767.6022", "-3767.6022", "-3767.6022", "-3767.6", "-3767.6", "-3767.6", "-3.76760e+03", "-3.76760e+03", "-3.76760e+03", "-3767.60220", "-3767.60220", "-3767.60220", "-3767.6", "-3767.60", "-3767.6", "-3.767602e+03", "-3.767602e+03", "-3.767602e+03", "-3767.602203", "-3767.602203", "-3767.602203", "-3767.602", "-3767.602", "-3767.602", "-3.7676022e+03", "-3.7676022e+03", "-3.7676022e+03", "-3767.6022034", "-3767.6022034", "-3767.6022034", "-3767.6022", "-3767.6022", "-3767.6022", "-3.76760220e+03", "-3.76760220e+03", "-3.76760220e+03", "-3767.60220337", "-3767.60220337", "-3767.60220337", "-3767.6022", "-3767.60220", "-3767.6022", "-3.767602203e+03", "-3.767602203e+03", "-3.767602203e+03", "-3767.602203369", "-3767.602203369", "-3767.602203369", "-3767.602203", "-3767.602203", "-3767.602203", "-3.7676022034e+03", "-3.7676022034e+03", "-3.7676022034e+03", "-3767.6022033691", "-3767.6022033691", "-3767.6022033691", "-3767.6022034", "-3767.6022034", "-3767.6022034", "-3.76760220337e+03", "-3.76760220337e+03", "-3.76760220337e+03", "-3767.60220336914", "-3767.60220336914", "-3767.60220336914", "-3767.60220337", "-3767.60220337", "-3767.60220337", "-3.767602203369e+03", "-3.767602203369e+03", "-3.767602203369e+03", "-3767.602203369141", "-3767.602203369141", "-3767.602203369141", "-3767.602203369", "-3767.602203369", "-3767.602203369", "-3.7676022033691e+03", "-3.7676022033691e+03", "-3.7676022033691e+03", "-3767.6022033691406", "-3767.6022033691406", "-3767.6022033691406", }}, + {{ "5e+02", "5.e+02", "+5e+02", "4.7e+02", "+4.7e+02", "4.7e+02", "471.0", "471.0", "+471.0", "4.7e+02", "4.7e+02", "+4.7e+02", "4.71e+02", "+4.71e+02", "4.71e+02", "470.95", "470.95", "+470.95", "471", "471.", "+471", "4.710e+02", "+4.710e+02", "4.710e+02", "470.950", "470.950", "+470.950", "471", "471.0", "+471", "4.7095e+02", "+4.7095e+02", "4.7095e+02", "470.9503", "470.9503", "+470.9503", "470.95", "470.95", "+470.95", "4.70950e+02", "+4.70950e+02", "4.70950e+02", "470.95028", "470.95028", "+470.95028", "470.95", "470.950", "+470.95", "4.709503e+02", "+4.709503e+02", "4.709503e+02", "470.950275", "470.950275", "+470.950275", "470.9503", "470.9503", "+470.9503", "4.7095028e+02", "+4.7095028e+02", "4.7095028e+02", "470.9502754", "470.9502754", "+470.9502754", "470.95028", "470.95028", "+470.95028", "4.70950275e+02", "+4.70950275e+02", "4.70950275e+02", "470.95027542", "470.95027542", "+470.95027542", "470.950275", "470.950275", "+470.950275", "4.709502754e+02", "+4.709502754e+02", "4.709502754e+02", "470.950275421", "470.950275421", "+470.950275421", "470.9502754", "470.9502754", "+470.9502754", "4.7095027542e+02", "+4.7095027542e+02", "4.7095027542e+02", "470.9502754211", "470.9502754211", "+470.9502754211", "470.95027542", "470.95027542", "+470.95027542", "4.70950275421e+02", "+4.70950275421e+02", "4.70950275421e+02", "470.95027542114", "470.95027542114", "+470.95027542114", "470.950275421", "470.950275421", "+470.950275421", "4.709502754211e+02", "+4.709502754211e+02", "4.709502754211e+02", "470.950275421143", "470.950275421143", "+470.950275421143", "470.9502754211", "470.9502754211", "+470.9502754211", "4.7095027542114e+02", "+4.7095027542114e+02", "4.7095027542114e+02", "470.9502754211426", "470.9502754211426", "+470.9502754211426", }}, + {{ "-5e+02", "-5.e+02", "-5e+02", "-4.7e+02", "-4.7e+02", "-4.7e+02", "-471.0", "-471.0", "-471.0", "-4.7e+02", "-4.7e+02", "-4.7e+02", "-4.71e+02", "-4.71e+02", "-4.71e+02", "-470.95", "-470.95", "-470.95", "-471", "-471.", "-471", "-4.710e+02", "-4.710e+02", "-4.710e+02", "-470.950", "-470.950", "-470.950", "-471", "-471.0", "-471", "-4.7095e+02", "-4.7095e+02", "-4.7095e+02", "-470.9503", "-470.9503", "-470.9503", "-470.95", "-470.95", "-470.95", "-4.70950e+02", "-4.70950e+02", "-4.70950e+02", "-470.95028", "-470.95028", "-470.95028", "-470.95", "-470.950", "-470.95", "-4.709503e+02", "-4.709503e+02", "-4.709503e+02", "-470.950275", "-470.950275", "-470.950275", "-470.9503", "-470.9503", "-470.9503", "-4.7095028e+02", "-4.7095028e+02", "-4.7095028e+02", "-470.9502754", "-470.9502754", "-470.9502754", "-470.95028", "-470.95028", "-470.95028", "-4.70950275e+02", "-4.70950275e+02", "-4.70950275e+02", "-470.95027542", "-470.95027542", "-470.95027542", "-470.950275", "-470.950275", "-470.950275", "-4.709502754e+02", "-4.709502754e+02", "-4.709502754e+02", "-470.950275421", "-470.950275421", "-470.950275421", "-470.9502754", "-470.9502754", "-470.9502754", "-4.7095027542e+02", "-4.7095027542e+02", "-4.7095027542e+02", "-470.9502754211", "-470.9502754211", "-470.9502754211", "-470.95027542", "-470.95027542", "-470.95027542", "-4.70950275421e+02", "-4.70950275421e+02", "-4.70950275421e+02", "-470.95027542114", "-470.95027542114", "-470.95027542114", "-470.950275421", "-470.950275421", "-470.950275421", "-4.709502754211e+02", "-4.709502754211e+02", "-4.709502754211e+02", "-470.950275421143", "-470.950275421143", "-470.950275421143", "-470.9502754211", "-470.9502754211", "-470.9502754211", "-4.7095027542114e+02", "-4.7095027542114e+02", "-4.7095027542114e+02", "-470.9502754211426", "-470.9502754211426", "-470.9502754211426", }}, + {{ "6e+01", "6.e+01", "+6e+01", "5.9e+01", "+5.9e+01", "5.9e+01", "58.9", "58.9", "+58.9", "59", "59.", "+59", "5.89e+01", "+5.89e+01", "5.89e+01", "58.87", "58.87", "+58.87", "58.9", "58.9", "+58.9", "5.887e+01", "+5.887e+01", "5.887e+01", "58.869", "58.869", "+58.869", "58.87", "58.87", "+58.87", "5.8869e+01", "+5.8869e+01", "5.8869e+01", "58.8688", "58.8688", "+58.8688", "58.869", "58.869", "+58.869", "5.88688e+01", "+5.88688e+01", "5.88688e+01", "58.86878", "58.86878", "+58.86878", "58.8688", "58.8688", "+58.8688", "5.886878e+01", "+5.886878e+01", "5.886878e+01", "58.868784", "58.868784", "+58.868784", "58.86878", "58.86878", "+58.86878", "5.8868784e+01", "+5.8868784e+01", "5.8868784e+01", "58.8687844", "58.8687844", "+58.8687844", "58.868784", "58.868784", "+58.868784", "5.88687844e+01", "+5.88687844e+01", "5.88687844e+01", "58.86878443", "58.86878443", "+58.86878443", "58.8687844", "58.8687844", "+58.8687844", "5.886878443e+01", "+5.886878443e+01", "5.886878443e+01", "58.868784428", "58.868784428", "+58.868784428", "58.86878443", "58.86878443", "+58.86878443", "5.8868784428e+01", "+5.8868784428e+01", "5.8868784428e+01", "58.8687844276", "58.8687844276", "+58.8687844276", "58.868784428", "58.868784428", "+58.868784428", "5.88687844276e+01", "+5.88687844276e+01", "5.88687844276e+01", "58.86878442764", "58.86878442764", "+58.86878442764", "58.8687844276", "58.8687844276", "+58.8687844276", "5.886878442764e+01", "+5.886878442764e+01", "5.886878442764e+01", "58.868784427643", "58.868784427643", "+58.868784427643", "58.86878442764", "58.86878442764", "+58.86878442764", "5.8868784427643e+01", "+5.8868784427643e+01", "5.8868784427643e+01", "58.8687844276428", "58.8687844276428", "+58.8687844276428", }}, + {{ "-6e+01", "-6.e+01", "-6e+01", "-5.9e+01", "-5.9e+01", "-5.9e+01", "-58.9", "-58.9", "-58.9", "-59", "-59.", "-59", "-5.89e+01", "-5.89e+01", "-5.89e+01", "-58.87", "-58.87", "-58.87", "-58.9", "-58.9", "-58.9", "-5.887e+01", "-5.887e+01", "-5.887e+01", "-58.869", "-58.869", "-58.869", "-58.87", "-58.87", "-58.87", "-5.8869e+01", "-5.8869e+01", "-5.8869e+01", "-58.8688", "-58.8688", "-58.8688", "-58.869", "-58.869", "-58.869", "-5.88688e+01", "-5.88688e+01", "-5.88688e+01", "-58.86878", "-58.86878", "-58.86878", "-58.8688", "-58.8688", "-58.8688", "-5.886878e+01", "-5.886878e+01", "-5.886878e+01", "-58.868784", "-58.868784", "-58.868784", "-58.86878", "-58.86878", "-58.86878", "-5.8868784e+01", "-5.8868784e+01", "-5.8868784e+01", "-58.8687844", "-58.8687844", "-58.8687844", "-58.868784", "-58.868784", "-58.868784", "-5.88687844e+01", "-5.88687844e+01", "-5.88687844e+01", "-58.86878443", "-58.86878443", "-58.86878443", "-58.8687844", "-58.8687844", "-58.8687844", "-5.886878443e+01", "-5.886878443e+01", "-5.886878443e+01", "-58.868784428", "-58.868784428", "-58.868784428", "-58.86878443", "-58.86878443", "-58.86878443", "-5.8868784428e+01", "-5.8868784428e+01", "-5.8868784428e+01", "-58.8687844276", "-58.8687844276", "-58.8687844276", "-58.868784428", "-58.868784428", "-58.868784428", "-5.88687844276e+01", "-5.88687844276e+01", "-5.88687844276e+01", "-58.86878442764", "-58.86878442764", "-58.86878442764", "-58.8687844276", "-58.8687844276", "-58.8687844276", "-5.886878442764e+01", "-5.886878442764e+01", "-5.886878442764e+01", "-58.868784427643", "-58.868784427643", "-58.868784427643", "-58.86878442764", "-58.86878442764", "-58.86878442764", "-5.8868784427643e+01", "-5.8868784427643e+01", "-5.8868784427643e+01", "-58.8687844276428", "-58.8687844276428", "-58.8687844276428", }}, + {{ "7", "7.", "+7", "7.4e+00", "+7.4e+00", "7.4e+00", "7.4", "7.4", "+7.4", "7.4", "7.4", "+7.4", "7.36e+00", "+7.36e+00", "7.36e+00", "7.36", "7.36", "+7.36", "7.36", "7.36", "+7.36", "7.359e+00", "+7.359e+00", "7.359e+00", "7.359", "7.359", "+7.359", "7.359", "7.359", "+7.359", "7.3586e+00", "+7.3586e+00", "7.3586e+00", "7.3586", "7.3586", "+7.3586", "7.3586", "7.3586", "+7.3586", "7.35860e+00", "+7.35860e+00", "7.35860e+00", "7.35860", "7.35860", "+7.35860", "7.3586", "7.35860", "+7.3586", "7.358598e+00", "+7.358598e+00", "7.358598e+00", "7.358598", "7.358598", "+7.358598", "7.358598", "7.358598", "+7.358598", "7.3585981e+00", "+7.3585981e+00", "7.3585981e+00", "7.3585981", "7.3585981", "+7.3585981", "7.3585981", "7.3585981", "+7.3585981", "7.35859805e+00", "+7.35859805e+00", "7.35859805e+00", "7.35859805", "7.35859805", "+7.35859805", "7.35859805", "7.35859805", "+7.35859805", "7.358598053e+00", "+7.358598053e+00", "7.358598053e+00", "7.358598053", "7.358598053", "+7.358598053", "7.358598053", "7.358598053", "+7.358598053", "7.3585980535e+00", "+7.3585980535e+00", "7.3585980535e+00", "7.3585980535", "7.3585980535", "+7.3585980535", "7.3585980535", "7.3585980535", "+7.3585980535", "7.35859805346e+00", "+7.35859805346e+00", "7.35859805346e+00", "7.35859805346", "7.35859805346", "+7.35859805346", "7.35859805346", "7.35859805346", "+7.35859805346", "7.358598053455e+00", "+7.358598053455e+00", "7.358598053455e+00", "7.358598053455", "7.358598053455", "+7.358598053455", "7.358598053455", "7.358598053455", "+7.358598053455", "7.3585980534554e+00", "+7.3585980534554e+00", "7.3585980534554e+00", "7.3585980534554", "7.3585980534554", "+7.3585980534554", }}, + {{ "-7", "-7.", "-7", "-7.4e+00", "-7.4e+00", "-7.4e+00", "-7.4", "-7.4", "-7.4", "-7.4", "-7.4", "-7.4", "-7.36e+00", "-7.36e+00", "-7.36e+00", "-7.36", "-7.36", "-7.36", "-7.36", "-7.36", "-7.36", "-7.359e+00", "-7.359e+00", "-7.359e+00", "-7.359", "-7.359", "-7.359", "-7.359", "-7.359", "-7.359", "-7.3586e+00", "-7.3586e+00", "-7.3586e+00", "-7.3586", "-7.3586", "-7.3586", "-7.3586", "-7.3586", "-7.3586", "-7.35860e+00", "-7.35860e+00", "-7.35860e+00", "-7.35860", "-7.35860", "-7.35860", "-7.3586", "-7.35860", "-7.3586", "-7.358598e+00", "-7.358598e+00", "-7.358598e+00", "-7.358598", "-7.358598", "-7.358598", "-7.358598", "-7.358598", "-7.358598", "-7.3585981e+00", "-7.3585981e+00", "-7.3585981e+00", "-7.3585981", "-7.3585981", "-7.3585981", "-7.3585981", "-7.3585981", "-7.3585981", "-7.35859805e+00", "-7.35859805e+00", "-7.35859805e+00", "-7.35859805", "-7.35859805", "-7.35859805", "-7.35859805", "-7.35859805", "-7.35859805", "-7.358598053e+00", "-7.358598053e+00", "-7.358598053e+00", "-7.358598053", "-7.358598053", "-7.358598053", "-7.358598053", "-7.358598053", "-7.358598053", "-7.3585980535e+00", "-7.3585980535e+00", "-7.3585980535e+00", "-7.3585980535", "-7.3585980535", "-7.3585980535", "-7.3585980535", "-7.3585980535", "-7.3585980535", "-7.35859805346e+00", "-7.35859805346e+00", "-7.35859805346e+00", "-7.35859805346", "-7.35859805346", "-7.35859805346", "-7.35859805346", "-7.35859805346", "-7.35859805346", "-7.358598053455e+00", "-7.358598053455e+00", "-7.358598053455e+00", "-7.358598053455", "-7.358598053455", "-7.358598053455", "-7.358598053455", "-7.358598053455", "-7.358598053455", "-7.3585980534554e+00", "-7.3585980534554e+00", "-7.3585980534554e+00", "-7.3585980534554", "-7.3585980534554", "-7.3585980534554", }}, + {{ "0.9", "0.9", "+0.9", "9.2e-01", "+9.2e-01", "9.2e-01", "0.9", "0.9", "+0.9", "0.92", "0.92", "+0.92", "9.20e-01", "+9.20e-01", "9.20e-01", "0.92", "0.92", "+0.92", "0.92", "0.920", "+0.92", "9.198e-01", "+9.198e-01", "9.198e-01", "0.920", "0.920", "+0.920", "0.9198", "0.9198", "+0.9198", "9.1982e-01", "+9.1982e-01", "9.1982e-01", "0.9198", "0.9198", "+0.9198", "0.91982", "0.91982", "+0.91982", "9.19825e-01", "+9.19825e-01", "9.19825e-01", "0.91982", "0.91982", "+0.91982", "0.919825", "0.919825", "+0.919825", "9.198248e-01", "+9.198248e-01", "9.198248e-01", "0.919825", "0.919825", "+0.919825", "0.9198248", "0.9198248", "+0.9198248", "9.1982476e-01", "+9.1982476e-01", "9.1982476e-01", "0.9198248", "0.9198248", "+0.9198248", "0.91982476", "0.91982476", "+0.91982476", "9.19824757e-01", "+9.19824757e-01", "9.19824757e-01", "0.91982476", "0.91982476", "+0.91982476", "0.919824757", "0.919824757", "+0.919824757", "9.198247567e-01", "+9.198247567e-01", "9.198247567e-01", "0.919824757", "0.919824757", "+0.919824757", "0.9198247567", "0.9198247567", "+0.9198247567", "9.1982475668e-01", "+9.1982475668e-01", "9.1982475668e-01", "0.9198247567", "0.9198247567", "+0.9198247567", "0.91982475668", "0.91982475668", "+0.91982475668", "9.19824756682e-01", "+9.19824756682e-01", "9.19824756682e-01", "0.91982475668", "0.91982475668", "+0.91982475668", "0.919824756682", "0.919824756682", "+0.919824756682", "9.198247566819e-01", "+9.198247566819e-01", "9.198247566819e-01", "0.919824756682", "0.919824756682", "+0.919824756682", "0.9198247566819", "0.9198247566819", "+0.9198247566819", "9.1982475668192e-01", "+9.1982475668192e-01", "9.1982475668192e-01", "0.9198247566819", "0.9198247566819", "+0.9198247566819", }}, + {{ "-0.9", "-0.9", "-0.9", "-9.2e-01", "-9.2e-01", "-9.2e-01", "-0.9", "-0.9", "-0.9", "-0.92", "-0.92", "-0.92", "-9.20e-01", "-9.20e-01", "-9.20e-01", "-0.92", "-0.92", "-0.92", "-0.92", "-0.920", "-0.92", "-9.198e-01", "-9.198e-01", "-9.198e-01", "-0.920", "-0.920", "-0.920", "-0.9198", "-0.9198", "-0.9198", "-9.1982e-01", "-9.1982e-01", "-9.1982e-01", "-0.9198", "-0.9198", "-0.9198", "-0.91982", "-0.91982", "-0.91982", "-9.19825e-01", "-9.19825e-01", "-9.19825e-01", "-0.91982", "-0.91982", "-0.91982", "-0.919825", "-0.919825", "-0.919825", "-9.198248e-01", "-9.198248e-01", "-9.198248e-01", "-0.919825", "-0.919825", "-0.919825", "-0.9198248", "-0.9198248", "-0.9198248", "-9.1982476e-01", "-9.1982476e-01", "-9.1982476e-01", "-0.9198248", "-0.9198248", "-0.9198248", "-0.91982476", "-0.91982476", "-0.91982476", "-9.19824757e-01", "-9.19824757e-01", "-9.19824757e-01", "-0.91982476", "-0.91982476", "-0.91982476", "-0.919824757", "-0.919824757", "-0.919824757", "-9.198247567e-01", "-9.198247567e-01", "-9.198247567e-01", "-0.919824757", "-0.919824757", "-0.919824757", "-0.9198247567", "-0.9198247567", "-0.9198247567", "-9.1982475668e-01", "-9.1982475668e-01", "-9.1982475668e-01", "-0.9198247567", "-0.9198247567", "-0.9198247567", "-0.91982475668", "-0.91982475668", "-0.91982475668", "-9.19824756682e-01", "-9.19824756682e-01", "-9.19824756682e-01", "-0.91982475668", "-0.91982475668", "-0.91982475668", "-0.919824756682", "-0.919824756682", "-0.919824756682", "-9.198247566819e-01", "-9.198247566819e-01", "-9.198247566819e-01", "-0.919824756682", "-0.919824756682", "-0.919824756682", "-0.9198247566819", "-0.9198247566819", "-0.9198247566819", "-9.1982475668192e-01", "-9.1982475668192e-01", "-9.1982475668192e-01", "-0.9198247566819", "-0.9198247566819", "-0.9198247566819", }}, + {{ "0.1", "0.1", "+0.1", "1.1e-01", "+1.1e-01", "1.1e-01", "0.1", "0.1", "+0.1", "0.11", "0.11", "+0.11", "1.15e-01", "+1.15e-01", "1.15e-01", "0.11", "0.11", "+0.11", "0.115", "0.115", "+0.115", "1.150e-01", "+1.150e-01", "1.150e-01", "0.115", "0.115", "+0.115", "0.115", "0.1150", "+0.115", "1.1498e-01", "+1.1498e-01", "1.1498e-01", "0.1150", "0.1150", "+0.1150", "0.11498", "0.11498", "+0.11498", "1.14978e-01", "+1.14978e-01", "1.14978e-01", "0.11498", "0.11498", "+0.11498", "0.114978", "0.114978", "+0.114978", "1.149781e-01", "+1.149781e-01", "1.149781e-01", "0.114978", "0.114978", "+0.114978", "0.1149781", "0.1149781", "+0.1149781", "1.1497809e-01", "+1.1497809e-01", "1.1497809e-01", "0.1149781", "0.1149781", "+0.1149781", "0.11497809", "0.11497809", "+0.11497809", "1.14978095e-01", "+1.14978095e-01", "1.14978095e-01", "0.11497809", "0.11497809", "+0.11497809", "0.114978095", "0.114978095", "+0.114978095", "1.149780946e-01", "+1.149780946e-01", "1.149780946e-01", "0.114978095", "0.114978095", "+0.114978095", "0.1149780946", "0.1149780946", "+0.1149780946", "1.1497809459e-01", "+1.1497809459e-01", "1.1497809459e-01", "0.1149780946", "0.1149780946", "+0.1149780946", "0.11497809459", "0.11497809459", "+0.11497809459", "1.14978094585e-01", "+1.14978094585e-01", "1.14978094585e-01", "0.11497809459", "0.11497809459", "+0.11497809459", "0.114978094585", "0.114978094585", "+0.114978094585", "1.149780945852e-01", "+1.149780945852e-01", "1.149780945852e-01", "0.114978094585", "0.114978094585", "+0.114978094585", "0.1149780945852", "0.1149780945852", "+0.1149780945852", "1.1497809458524e-01", "+1.1497809458524e-01", "1.1497809458524e-01", "0.1149780945852", "0.1149780945852", "+0.1149780945852", }}, + {{ "-0.1", "-0.1", "-0.1", "-1.1e-01", "-1.1e-01", "-1.1e-01", "-0.1", "-0.1", "-0.1", "-0.11", "-0.11", "-0.11", "-1.15e-01", "-1.15e-01", "-1.15e-01", "-0.11", "-0.11", "-0.11", "-0.115", "-0.115", "-0.115", "-1.150e-01", "-1.150e-01", "-1.150e-01", "-0.115", "-0.115", "-0.115", "-0.115", "-0.1150", "-0.115", "-1.1498e-01", "-1.1498e-01", "-1.1498e-01", "-0.1150", "-0.1150", "-0.1150", "-0.11498", "-0.11498", "-0.11498", "-1.14978e-01", "-1.14978e-01", "-1.14978e-01", "-0.11498", "-0.11498", "-0.11498", "-0.114978", "-0.114978", "-0.114978", "-1.149781e-01", "-1.149781e-01", "-1.149781e-01", "-0.114978", "-0.114978", "-0.114978", "-0.1149781", "-0.1149781", "-0.1149781", "-1.1497809e-01", "-1.1497809e-01", "-1.1497809e-01", "-0.1149781", "-0.1149781", "-0.1149781", "-0.11497809", "-0.11497809", "-0.11497809", "-1.14978095e-01", "-1.14978095e-01", "-1.14978095e-01", "-0.11497809", "-0.11497809", "-0.11497809", "-0.114978095", "-0.114978095", "-0.114978095", "-1.149780946e-01", "-1.149780946e-01", "-1.149780946e-01", "-0.114978095", "-0.114978095", "-0.114978095", "-0.1149780946", "-0.1149780946", "-0.1149780946", "-1.1497809459e-01", "-1.1497809459e-01", "-1.1497809459e-01", "-0.1149780946", "-0.1149780946", "-0.1149780946", "-0.11497809459", "-0.11497809459", "-0.11497809459", "-1.14978094585e-01", "-1.14978094585e-01", "-1.14978094585e-01", "-0.11497809459", "-0.11497809459", "-0.11497809459", "-0.114978094585", "-0.114978094585", "-0.114978094585", "-1.149780945852e-01", "-1.149780945852e-01", "-1.149780945852e-01", "-0.114978094585", "-0.114978094585", "-0.114978094585", "-0.1149780945852", "-0.1149780945852", "-0.1149780945852", "-1.1497809458524e-01", "-1.1497809458524e-01", "-1.1497809458524e-01", "-0.1149780945852", "-0.1149780945852", "-0.1149780945852", }}, + {{ "0.01", "0.01", "+0.01", "1.4e-02", "+1.4e-02", "1.4e-02", "0.0", "0.0", "+0.0", "0.014", "0.014", "+0.014", "1.44e-02", "+1.44e-02", "1.44e-02", "0.01", "0.01", "+0.01", "0.0144", "0.0144", "+0.0144", "1.437e-02", "+1.437e-02", "1.437e-02", "0.014", "0.014", "+0.014", "0.01437", "0.01437", "+0.01437", "1.4372e-02", "+1.4372e-02", "1.4372e-02", "0.0144", "0.0144", "+0.0144", "0.014372", "0.014372", "+0.014372", "1.43723e-02", "+1.43723e-02", "1.43723e-02", "0.01437", "0.01437", "+0.01437", "0.0143723", "0.0143723", "+0.0143723", "1.437226e-02", "+1.437226e-02", "1.437226e-02", "0.014372", "0.014372", "+0.014372", "0.01437226", "0.01437226", "+0.01437226", "1.4372262e-02", "+1.4372262e-02", "1.4372262e-02", "0.0143723", "0.0143723", "+0.0143723", "0.014372262", "0.014372262", "+0.014372262", "1.43722618e-02", "+1.43722618e-02", "1.43722618e-02", "0.01437226", "0.01437226", "+0.01437226", "0.0143722618", "0.0143722618", "+0.0143722618", "1.437226182e-02", "+1.437226182e-02", "1.437226182e-02", "0.014372262", "0.014372262", "+0.014372262", "0.01437226182", "0.01437226182", "+0.01437226182", "1.4372261823e-02", "+1.4372261823e-02", "1.4372261823e-02", "0.0143722618", "0.0143722618", "+0.0143722618", "0.014372261823", "0.014372261823", "+0.014372261823", "1.43722618232e-02", "+1.43722618232e-02", "1.43722618232e-02", "0.01437226182", "0.01437226182", "+0.01437226182", "0.0143722618232", "0.0143722618232", "+0.0143722618232", "1.437226182315e-02", "+1.437226182315e-02", "1.437226182315e-02", "0.014372261823", "0.014372261823", "+0.014372261823", "0.01437226182315", "0.01437226182315", "+0.01437226182315", "1.4372261823155e-02", "+1.4372261823155e-02", "1.4372261823155e-02", "0.0143722618232", "0.0143722618232", "+0.0143722618232", }}, + {{ "-0.01", "-0.01", "-0.01", "-1.4e-02", "-1.4e-02", "-1.4e-02", "-0.0", "-0.0", "-0.0", "-0.014", "-0.014", "-0.014", "-1.44e-02", "-1.44e-02", "-1.44e-02", "-0.01", "-0.01", "-0.01", "-0.0144", "-0.0144", "-0.0144", "-1.437e-02", "-1.437e-02", "-1.437e-02", "-0.014", "-0.014", "-0.014", "-0.01437", "-0.01437", "-0.01437", "-1.4372e-02", "-1.4372e-02", "-1.4372e-02", "-0.0144", "-0.0144", "-0.0144", "-0.014372", "-0.014372", "-0.014372", "-1.43723e-02", "-1.43723e-02", "-1.43723e-02", "-0.01437", "-0.01437", "-0.01437", "-0.0143723", "-0.0143723", "-0.0143723", "-1.437226e-02", "-1.437226e-02", "-1.437226e-02", "-0.014372", "-0.014372", "-0.014372", "-0.01437226", "-0.01437226", "-0.01437226", "-1.4372262e-02", "-1.4372262e-02", "-1.4372262e-02", "-0.0143723", "-0.0143723", "-0.0143723", "-0.014372262", "-0.014372262", "-0.014372262", "-1.43722618e-02", "-1.43722618e-02", "-1.43722618e-02", "-0.01437226", "-0.01437226", "-0.01437226", "-0.0143722618", "-0.0143722618", "-0.0143722618", "-1.437226182e-02", "-1.437226182e-02", "-1.437226182e-02", "-0.014372262", "-0.014372262", "-0.014372262", "-0.01437226182", "-0.01437226182", "-0.01437226182", "-1.4372261823e-02", "-1.4372261823e-02", "-1.4372261823e-02", "-0.0143722618", "-0.0143722618", "-0.0143722618", "-0.014372261823", "-0.014372261823", "-0.014372261823", "-1.43722618232e-02", "-1.43722618232e-02", "-1.43722618232e-02", "-0.01437226182", "-0.01437226182", "-0.01437226182", "-0.0143722618232", "-0.0143722618232", "-0.0143722618232", "-1.437226182315e-02", "-1.437226182315e-02", "-1.437226182315e-02", "-0.014372261823", "-0.014372261823", "-0.014372261823", "-0.01437226182315", "-0.01437226182315", "-0.01437226182315", "-1.4372261823155e-02", "-1.4372261823155e-02", "-1.4372261823155e-02", "-0.0143722618232", "-0.0143722618232", "-0.0143722618232", }}, + {{ "0.002", "0.002", "+0.002", "1.8e-03", "+1.8e-03", "1.8e-03", "0.0", "0.0", "+0.0", "0.0018", "0.0018", "+0.0018", "1.80e-03", "+1.80e-03", "1.80e-03", "0.00", "0.00", "+0.00", "0.0018", "0.00180", "+0.0018", "1.797e-03", "+1.797e-03", "1.797e-03", "0.002", "0.002", "+0.002", "0.001797", "0.001797", "+0.001797", "1.7965e-03", "+1.7965e-03", "1.7965e-03", "0.0018", "0.0018", "+0.0018", "0.0017965", "0.0017965", "+0.0017965", "1.79653e-03", "+1.79653e-03", "1.79653e-03", "0.00180", "0.00180", "+0.00180", "0.00179653", "0.00179653", "+0.00179653", "1.796533e-03", "+1.796533e-03", "1.796533e-03", "0.001797", "0.001797", "+0.001797", "0.001796533", "0.001796533", "+0.001796533", "1.7965327e-03", "+1.7965327e-03", "1.7965327e-03", "0.0017965", "0.0017965", "+0.0017965", "0.0017965327", "0.0017965327", "+0.0017965327", "1.79653273e-03", "+1.79653273e-03", "1.79653273e-03", "0.00179653", "0.00179653", "+0.00179653", "0.00179653273", "0.00179653273", "+0.00179653273", "1.796532728e-03", "+1.796532728e-03", "1.796532728e-03", "0.001796533", "0.001796533", "+0.001796533", "0.001796532728", "0.001796532728", "+0.001796532728", "1.7965327279e-03", "+1.7965327279e-03", "1.7965327279e-03", "0.0017965327", "0.0017965327", "+0.0017965327", "0.0017965327279", "0.0017965327279", "+0.0017965327279", "1.79653272789e-03", "+1.79653272789e-03", "1.79653272789e-03", "0.00179653273", "0.00179653273", "+0.00179653273", "0.00179653272789", "0.00179653272789", "+0.00179653272789", "1.796532727894e-03", "+1.796532727894e-03", "1.796532727894e-03", "0.001796532728", "0.001796532728", "+0.001796532728", "0.001796532727894", "0.001796532727894", "+0.001796532727894", "1.7965327278944e-03", "+1.7965327278944e-03", "1.7965327278944e-03", "0.0017965327279", "0.0017965327279", "+0.0017965327279", }}, + {{ "-0.002", "-0.002", "-0.002", "-1.8e-03", "-1.8e-03", "-1.8e-03", "-0.0", "-0.0", "-0.0", "-0.0018", "-0.0018", "-0.0018", "-1.80e-03", "-1.80e-03", "-1.80e-03", "-0.00", "-0.00", "-0.00", "-0.0018", "-0.00180", "-0.0018", "-1.797e-03", "-1.797e-03", "-1.797e-03", "-0.002", "-0.002", "-0.002", "-0.001797", "-0.001797", "-0.001797", "-1.7965e-03", "-1.7965e-03", "-1.7965e-03", "-0.0018", "-0.0018", "-0.0018", "-0.0017965", "-0.0017965", "-0.0017965", "-1.79653e-03", "-1.79653e-03", "-1.79653e-03", "-0.00180", "-0.00180", "-0.00180", "-0.00179653", "-0.00179653", "-0.00179653", "-1.796533e-03", "-1.796533e-03", "-1.796533e-03", "-0.001797", "-0.001797", "-0.001797", "-0.001796533", "-0.001796533", "-0.001796533", "-1.7965327e-03", "-1.7965327e-03", "-1.7965327e-03", "-0.0017965", "-0.0017965", "-0.0017965", "-0.0017965327", "-0.0017965327", "-0.0017965327", "-1.79653273e-03", "-1.79653273e-03", "-1.79653273e-03", "-0.00179653", "-0.00179653", "-0.00179653", "-0.00179653273", "-0.00179653273", "-0.00179653273", "-1.796532728e-03", "-1.796532728e-03", "-1.796532728e-03", "-0.001796533", "-0.001796533", "-0.001796533", "-0.001796532728", "-0.001796532728", "-0.001796532728", "-1.7965327279e-03", "-1.7965327279e-03", "-1.7965327279e-03", "-0.0017965327", "-0.0017965327", "-0.0017965327", "-0.0017965327279", "-0.0017965327279", "-0.0017965327279", "-1.79653272789e-03", "-1.79653272789e-03", "-1.79653272789e-03", "-0.00179653273", "-0.00179653273", "-0.00179653273", "-0.00179653272789", "-0.00179653272789", "-0.00179653272789", "-1.796532727894e-03", "-1.796532727894e-03", "-1.796532727894e-03", "-0.001796532728", "-0.001796532728", "-0.001796532728", "-0.001796532727894", "-0.001796532727894", "-0.001796532727894", "-1.7965327278944e-03", "-1.7965327278944e-03", "-1.7965327278944e-03", "-0.0017965327279", "-0.0017965327279", "-0.0017965327279", }}, + {{ "0.0002", "0.0002", "+0.0002", "2.2e-04", "+2.2e-04", "2.2e-04", "0.0", "0.0", "+0.0", "0.00022", "0.00022", "+0.00022", "2.25e-04", "+2.25e-04", "2.25e-04", "0.00", "0.00", "+0.00", "0.000225", "0.000225", "+0.000225", "2.246e-04", "+2.246e-04", "2.246e-04", "0.000", "0.000", "+0.000", "0.0002246", "0.0002246", "+0.0002246", "2.2457e-04", "+2.2457e-04", "2.2457e-04", "0.0002", "0.0002", "+0.0002", "0.00022457", "0.00022457", "+0.00022457", "2.24567e-04", "+2.24567e-04", "2.24567e-04", "0.00022", "0.00022", "+0.00022", "0.000224567", "0.000224567", "+0.000224567", "2.245666e-04", "+2.245666e-04", "2.245666e-04", "0.000225", "0.000225", "+0.000225", "0.0002245666", "0.0002245666", "+0.0002245666", "2.2456659e-04", "+2.2456659e-04", "2.2456659e-04", "0.0002246", "0.0002246", "+0.0002246", "0.00022456659", "0.00022456659", "+0.00022456659", "2.24566591e-04", "+2.24566591e-04", "2.24566591e-04", "0.00022457", "0.00022457", "+0.00022457", "0.000224566591", "0.000224566591", "+0.000224566591", "2.245665910e-04", "+2.245665910e-04", "2.245665910e-04", "0.000224567", "0.000224567", "+0.000224567", "0.000224566591", "0.0002245665910", "+0.000224566591", "2.2456659099e-04", "+2.2456659099e-04", "2.2456659099e-04", "0.0002245666", "0.0002245666", "+0.0002245666", "0.00022456659099", "0.00022456659099", "+0.00022456659099", "2.24566590987e-04", "+2.24566590987e-04", "2.24566590987e-04", "0.00022456659", "0.00022456659", "+0.00022456659", "0.000224566590987", "0.000224566590987", "+0.000224566590987", "2.245665909868e-04", "+2.245665909868e-04", "2.245665909868e-04", "0.000224566591", "0.000224566591", "+0.000224566591", "0.0002245665909868", "0.0002245665909868", "+0.0002245665909868", "2.2456659098680e-04", "+2.2456659098680e-04", "2.2456659098680e-04", "0.0002245665910", "0.0002245665910", "+0.0002245665910", }}, + {{ "-0.0002", "-0.0002", "-0.0002", "-2.2e-04", "-2.2e-04", "-2.2e-04", "-0.0", "-0.0", "-0.0", "-0.00022", "-0.00022", "-0.00022", "-2.25e-04", "-2.25e-04", "-2.25e-04", "-0.00", "-0.00", "-0.00", "-0.000225", "-0.000225", "-0.000225", "-2.246e-04", "-2.246e-04", "-2.246e-04", "-0.000", "-0.000", "-0.000", "-0.0002246", "-0.0002246", "-0.0002246", "-2.2457e-04", "-2.2457e-04", "-2.2457e-04", "-0.0002", "-0.0002", "-0.0002", "-0.00022457", "-0.00022457", "-0.00022457", "-2.24567e-04", "-2.24567e-04", "-2.24567e-04", "-0.00022", "-0.00022", "-0.00022", "-0.000224567", "-0.000224567", "-0.000224567", "-2.245666e-04", "-2.245666e-04", "-2.245666e-04", "-0.000225", "-0.000225", "-0.000225", "-0.0002245666", "-0.0002245666", "-0.0002245666", "-2.2456659e-04", "-2.2456659e-04", "-2.2456659e-04", "-0.0002246", "-0.0002246", "-0.0002246", "-0.00022456659", "-0.00022456659", "-0.00022456659", "-2.24566591e-04", "-2.24566591e-04", "-2.24566591e-04", "-0.00022457", "-0.00022457", "-0.00022457", "-0.000224566591", "-0.000224566591", "-0.000224566591", "-2.245665910e-04", "-2.245665910e-04", "-2.245665910e-04", "-0.000224567", "-0.000224567", "-0.000224567", "-0.000224566591", "-0.0002245665910", "-0.000224566591", "-2.2456659099e-04", "-2.2456659099e-04", "-2.2456659099e-04", "-0.0002245666", "-0.0002245666", "-0.0002245666", "-0.00022456659099", "-0.00022456659099", "-0.00022456659099", "-2.24566590987e-04", "-2.24566590987e-04", "-2.24566590987e-04", "-0.00022456659", "-0.00022456659", "-0.00022456659", "-0.000224566590987", "-0.000224566590987", "-0.000224566590987", "-2.245665909868e-04", "-2.245665909868e-04", "-2.245665909868e-04", "-0.000224566591", "-0.000224566591", "-0.000224566591", "-0.0002245665909868", "-0.0002245665909868", "-0.0002245665909868", "-2.2456659098680e-04", "-2.2456659098680e-04", "-2.2456659098680e-04", "-0.0002245665910", "-0.0002245665910", "-0.0002245665910", }}, + {{ "3e-05", "3.e-05", "+3e-05", "2.8e-05", "+2.8e-05", "2.8e-05", "0.0", "0.0", "+0.0", "2.8e-05", "2.8e-05", "+2.8e-05", "2.81e-05", "+2.81e-05", "2.81e-05", "0.00", "0.00", "+0.00", "2.81e-05", "2.81e-05", "+2.81e-05", "2.807e-05", "+2.807e-05", "2.807e-05", "0.000", "0.000", "+0.000", "2.807e-05", "2.807e-05", "+2.807e-05", "2.8071e-05", "+2.8071e-05", "2.8071e-05", "0.0000", "0.0000", "+0.0000", "2.8071e-05", "2.8071e-05", "+2.8071e-05", "2.80708e-05", "+2.80708e-05", "2.80708e-05", "0.00003", "0.00003", "+0.00003", "2.80708e-05", "2.80708e-05", "+2.80708e-05", "2.807082e-05", "+2.807082e-05", "2.807082e-05", "0.000028", "0.000028", "+0.000028", "2.807082e-05", "2.807082e-05", "+2.807082e-05", "2.8070824e-05", "+2.8070824e-05", "2.8070824e-05", "0.0000281", "0.0000281", "+0.0000281", "2.8070824e-05", "2.8070824e-05", "+2.8070824e-05", "2.80708239e-05", "+2.80708239e-05", "2.80708239e-05", "0.00002807", "0.00002807", "+0.00002807", "2.80708239e-05", "2.80708239e-05", "+2.80708239e-05", "2.807082387e-05", "+2.807082387e-05", "2.807082387e-05", "0.000028071", "0.000028071", "+0.000028071", "2.807082387e-05", "2.807082387e-05", "+2.807082387e-05", "2.8070823873e-05", "+2.8070823873e-05", "2.8070823873e-05", "0.0000280708", "0.0000280708", "+0.0000280708", "2.8070823873e-05", "2.8070823873e-05", "+2.8070823873e-05", "2.80708238733e-05", "+2.80708238733e-05", "2.80708238733e-05", "0.00002807082", "0.00002807082", "+0.00002807082", "2.80708238733e-05", "2.80708238733e-05", "+2.80708238733e-05", "2.807082387335e-05", "+2.807082387335e-05", "2.807082387335e-05", "0.000028070824", "0.000028070824", "+0.000028070824", "2.807082387335e-05", "2.807082387335e-05", "+2.807082387335e-05", "2.8070823873350e-05", "+2.8070823873350e-05", "2.8070823873350e-05", "0.0000280708239", "0.0000280708239", "+0.0000280708239", }}, + {{ "-3e-05", "-3.e-05", "-3e-05", "-2.8e-05", "-2.8e-05", "-2.8e-05", "-0.0", "-0.0", "-0.0", "-2.8e-05", "-2.8e-05", "-2.8e-05", "-2.81e-05", "-2.81e-05", "-2.81e-05", "-0.00", "-0.00", "-0.00", "-2.81e-05", "-2.81e-05", "-2.81e-05", "-2.807e-05", "-2.807e-05", "-2.807e-05", "-0.000", "-0.000", "-0.000", "-2.807e-05", "-2.807e-05", "-2.807e-05", "-2.8071e-05", "-2.8071e-05", "-2.8071e-05", "-0.0000", "-0.0000", "-0.0000", "-2.8071e-05", "-2.8071e-05", "-2.8071e-05", "-2.80708e-05", "-2.80708e-05", "-2.80708e-05", "-0.00003", "-0.00003", "-0.00003", "-2.80708e-05", "-2.80708e-05", "-2.80708e-05", "-2.807082e-05", "-2.807082e-05", "-2.807082e-05", "-0.000028", "-0.000028", "-0.000028", "-2.807082e-05", "-2.807082e-05", "-2.807082e-05", "-2.8070824e-05", "-2.8070824e-05", "-2.8070824e-05", "-0.0000281", "-0.0000281", "-0.0000281", "-2.8070824e-05", "-2.8070824e-05", "-2.8070824e-05", "-2.80708239e-05", "-2.80708239e-05", "-2.80708239e-05", "-0.00002807", "-0.00002807", "-0.00002807", "-2.80708239e-05", "-2.80708239e-05", "-2.80708239e-05", "-2.807082387e-05", "-2.807082387e-05", "-2.807082387e-05", "-0.000028071", "-0.000028071", "-0.000028071", "-2.807082387e-05", "-2.807082387e-05", "-2.807082387e-05", "-2.8070823873e-05", "-2.8070823873e-05", "-2.8070823873e-05", "-0.0000280708", "-0.0000280708", "-0.0000280708", "-2.8070823873e-05", "-2.8070823873e-05", "-2.8070823873e-05", "-2.80708238733e-05", "-2.80708238733e-05", "-2.80708238733e-05", "-0.00002807082", "-0.00002807082", "-0.00002807082", "-2.80708238733e-05", "-2.80708238733e-05", "-2.80708238733e-05", "-2.807082387335e-05", "-2.807082387335e-05", "-2.807082387335e-05", "-0.000028070824", "-0.000028070824", "-0.000028070824", "-2.807082387335e-05", "-2.807082387335e-05", "-2.807082387335e-05", "-2.8070823873350e-05", "-2.8070823873350e-05", "-2.8070823873350e-05", "-0.0000280708239", "-0.0000280708239", "-0.0000280708239", }}, + {{ "4e-06", "4.e-06", "+4e-06", "3.5e-06", "+3.5e-06", "3.5e-06", "0.0", "0.0", "+0.0", "3.5e-06", "3.5e-06", "+3.5e-06", "3.51e-06", "+3.51e-06", "3.51e-06", "0.00", "0.00", "+0.00", "3.51e-06", "3.51e-06", "+3.51e-06", "3.509e-06", "+3.509e-06", "3.509e-06", "0.000", "0.000", "+0.000", "3.509e-06", "3.509e-06", "+3.509e-06", "3.5089e-06", "+3.5089e-06", "3.5089e-06", "0.0000", "0.0000", "+0.0000", "3.5089e-06", "3.5089e-06", "+3.5089e-06", "3.50885e-06", "+3.50885e-06", "3.50885e-06", "0.00000", "0.00000", "+0.00000", "3.50885e-06", "3.50885e-06", "+3.50885e-06", "3.508853e-06", "+3.508853e-06", "3.508853e-06", "0.000004", "0.000004", "+0.000004", "3.508853e-06", "3.508853e-06", "+3.508853e-06", "3.5088530e-06", "+3.5088530e-06", "3.5088530e-06", "0.0000035", "0.0000035", "+0.0000035", "3.508853e-06", "3.5088530e-06", "+3.508853e-06", "3.50885298e-06", "+3.50885298e-06", "3.50885298e-06", "0.00000351", "0.00000351", "+0.00000351", "3.50885298e-06", "3.50885298e-06", "+3.50885298e-06", "3.508852984e-06", "+3.508852984e-06", "3.508852984e-06", "0.000003509", "0.000003509", "+0.000003509", "3.508852984e-06", "3.508852984e-06", "+3.508852984e-06", "3.5088529842e-06", "+3.5088529842e-06", "3.5088529842e-06", "0.0000035089", "0.0000035089", "+0.0000035089", "3.5088529842e-06", "3.5088529842e-06", "+3.5088529842e-06", "3.50885298417e-06", "+3.50885298417e-06", "3.50885298417e-06", "0.00000350885", "0.00000350885", "+0.00000350885", "3.50885298417e-06", "3.50885298417e-06", "+3.50885298417e-06", "3.508852984169e-06", "+3.508852984169e-06", "3.508852984169e-06", "0.000003508853", "0.000003508853", "+0.000003508853", "3.508852984169e-06", "3.508852984169e-06", "+3.508852984169e-06", "3.5088529841687e-06", "+3.5088529841687e-06", "3.5088529841687e-06", "0.0000035088530", "0.0000035088530", "+0.0000035088530", }}, + {{ "-4e-06", "-4.e-06", "-4e-06", "-3.5e-06", "-3.5e-06", "-3.5e-06", "-0.0", "-0.0", "-0.0", "-3.5e-06", "-3.5e-06", "-3.5e-06", "-3.51e-06", "-3.51e-06", "-3.51e-06", "-0.00", "-0.00", "-0.00", "-3.51e-06", "-3.51e-06", "-3.51e-06", "-3.509e-06", "-3.509e-06", "-3.509e-06", "-0.000", "-0.000", "-0.000", "-3.509e-06", "-3.509e-06", "-3.509e-06", "-3.5089e-06", "-3.5089e-06", "-3.5089e-06", "-0.0000", "-0.0000", "-0.0000", "-3.5089e-06", "-3.5089e-06", "-3.5089e-06", "-3.50885e-06", "-3.50885e-06", "-3.50885e-06", "-0.00000", "-0.00000", "-0.00000", "-3.50885e-06", "-3.50885e-06", "-3.50885e-06", "-3.508853e-06", "-3.508853e-06", "-3.508853e-06", "-0.000004", "-0.000004", "-0.000004", "-3.508853e-06", "-3.508853e-06", "-3.508853e-06", "-3.5088530e-06", "-3.5088530e-06", "-3.5088530e-06", "-0.0000035", "-0.0000035", "-0.0000035", "-3.508853e-06", "-3.5088530e-06", "-3.508853e-06", "-3.50885298e-06", "-3.50885298e-06", "-3.50885298e-06", "-0.00000351", "-0.00000351", "-0.00000351", "-3.50885298e-06", "-3.50885298e-06", "-3.50885298e-06", "-3.508852984e-06", "-3.508852984e-06", "-3.508852984e-06", "-0.000003509", "-0.000003509", "-0.000003509", "-3.508852984e-06", "-3.508852984e-06", "-3.508852984e-06", "-3.5088529842e-06", "-3.5088529842e-06", "-3.5088529842e-06", "-0.0000035089", "-0.0000035089", "-0.0000035089", "-3.5088529842e-06", "-3.5088529842e-06", "-3.5088529842e-06", "-3.50885298417e-06", "-3.50885298417e-06", "-3.50885298417e-06", "-0.00000350885", "-0.00000350885", "-0.00000350885", "-3.50885298417e-06", "-3.50885298417e-06", "-3.50885298417e-06", "-3.508852984169e-06", "-3.508852984169e-06", "-3.508852984169e-06", "-0.000003508853", "-0.000003508853", "-0.000003508853", "-3.508852984169e-06", "-3.508852984169e-06", "-3.508852984169e-06", "-3.5088529841687e-06", "-3.5088529841687e-06", "-3.5088529841687e-06", "-0.0000035088530", "-0.0000035088530", "-0.0000035088530", }}, + {{ "4e-07", "4.e-07", "+4e-07", "4.4e-07", "+4.4e-07", "4.4e-07", "0.0", "0.0", "+0.0", "4.4e-07", "4.4e-07", "+4.4e-07", "4.39e-07", "+4.39e-07", "4.39e-07", "0.00", "0.00", "+0.00", "4.39e-07", "4.39e-07", "+4.39e-07", "4.386e-07", "+4.386e-07", "4.386e-07", "0.000", "0.000", "+0.000", "4.386e-07", "4.386e-07", "+4.386e-07", "4.3861e-07", "+4.3861e-07", "4.3861e-07", "0.0000", "0.0000", "+0.0000", "4.3861e-07", "4.3861e-07", "+4.3861e-07", "4.38607e-07", "+4.38607e-07", "4.38607e-07", "0.00000", "0.00000", "+0.00000", "4.38607e-07", "4.38607e-07", "+4.38607e-07", "4.386066e-07", "+4.386066e-07", "4.386066e-07", "0.000000", "0.000000", "+0.000000", "4.386066e-07", "4.386066e-07", "+4.386066e-07", "4.3860662e-07", "+4.3860662e-07", "4.3860662e-07", "0.0000004", "0.0000004", "+0.0000004", "4.3860662e-07", "4.3860662e-07", "+4.3860662e-07", "4.38606623e-07", "+4.38606623e-07", "4.38606623e-07", "0.00000044", "0.00000044", "+0.00000044", "4.38606623e-07", "4.38606623e-07", "+4.38606623e-07", "4.386066230e-07", "+4.386066230e-07", "4.386066230e-07", "0.000000439", "0.000000439", "+0.000000439", "4.38606623e-07", "4.386066230e-07", "+4.38606623e-07", "4.3860662302e-07", "+4.3860662302e-07", "4.3860662302e-07", "0.0000004386", "0.0000004386", "+0.0000004386", "4.3860662302e-07", "4.3860662302e-07", "+4.3860662302e-07", "4.38606623021e-07", "+4.38606623021e-07", "4.38606623021e-07", "0.00000043861", "0.00000043861", "+0.00000043861", "4.38606623021e-07", "4.38606623021e-07", "+4.38606623021e-07", "4.386066230211e-07", "+4.386066230211e-07", "4.386066230211e-07", "0.000000438607", "0.000000438607", "+0.000000438607", "4.386066230211e-07", "4.386066230211e-07", "+4.386066230211e-07", "4.3860662302109e-07", "+4.3860662302109e-07", "4.3860662302109e-07", "0.0000004386066", "0.0000004386066", "+0.0000004386066", }}, + {{ "-4e-07", "-4.e-07", "-4e-07", "-4.4e-07", "-4.4e-07", "-4.4e-07", "-0.0", "-0.0", "-0.0", "-4.4e-07", "-4.4e-07", "-4.4e-07", "-4.39e-07", "-4.39e-07", "-4.39e-07", "-0.00", "-0.00", "-0.00", "-4.39e-07", "-4.39e-07", "-4.39e-07", "-4.386e-07", "-4.386e-07", "-4.386e-07", "-0.000", "-0.000", "-0.000", "-4.386e-07", "-4.386e-07", "-4.386e-07", "-4.3861e-07", "-4.3861e-07", "-4.3861e-07", "-0.0000", "-0.0000", "-0.0000", "-4.3861e-07", "-4.3861e-07", "-4.3861e-07", "-4.38607e-07", "-4.38607e-07", "-4.38607e-07", "-0.00000", "-0.00000", "-0.00000", "-4.38607e-07", "-4.38607e-07", "-4.38607e-07", "-4.386066e-07", "-4.386066e-07", "-4.386066e-07", "-0.000000", "-0.000000", "-0.000000", "-4.386066e-07", "-4.386066e-07", "-4.386066e-07", "-4.3860662e-07", "-4.3860662e-07", "-4.3860662e-07", "-0.0000004", "-0.0000004", "-0.0000004", "-4.3860662e-07", "-4.3860662e-07", "-4.3860662e-07", "-4.38606623e-07", "-4.38606623e-07", "-4.38606623e-07", "-0.00000044", "-0.00000044", "-0.00000044", "-4.38606623e-07", "-4.38606623e-07", "-4.38606623e-07", "-4.386066230e-07", "-4.386066230e-07", "-4.386066230e-07", "-0.000000439", "-0.000000439", "-0.000000439", "-4.38606623e-07", "-4.386066230e-07", "-4.38606623e-07", "-4.3860662302e-07", "-4.3860662302e-07", "-4.3860662302e-07", "-0.0000004386", "-0.0000004386", "-0.0000004386", "-4.3860662302e-07", "-4.3860662302e-07", "-4.3860662302e-07", "-4.38606623021e-07", "-4.38606623021e-07", "-4.38606623021e-07", "-0.00000043861", "-0.00000043861", "-0.00000043861", "-4.38606623021e-07", "-4.38606623021e-07", "-4.38606623021e-07", "-4.386066230211e-07", "-4.386066230211e-07", "-4.386066230211e-07", "-0.000000438607", "-0.000000438607", "-0.000000438607", "-4.386066230211e-07", "-4.386066230211e-07", "-4.386066230211e-07", "-4.3860662302109e-07", "-4.3860662302109e-07", "-4.3860662302109e-07", "-0.0000004386066", "-0.0000004386066", "-0.0000004386066", }}, + {{ "5e-08", "5.e-08", "+5e-08", "5.5e-08", "+5.5e-08", "5.5e-08", "0.0", "0.0", "+0.0", "5.5e-08", "5.5e-08", "+5.5e-08", "5.48e-08", "+5.48e-08", "5.48e-08", "0.00", "0.00", "+0.00", "5.48e-08", "5.48e-08", "+5.48e-08", "5.483e-08", "+5.483e-08", "5.483e-08", "0.000", "0.000", "+0.000", "5.483e-08", "5.483e-08", "+5.483e-08", "5.4826e-08", "+5.4826e-08", "5.4826e-08", "0.0000", "0.0000", "+0.0000", "5.4826e-08", "5.4826e-08", "+5.4826e-08", "5.48258e-08", "+5.48258e-08", "5.48258e-08", "0.00000", "0.00000", "+0.00000", "5.48258e-08", "5.48258e-08", "+5.48258e-08", "5.482583e-08", "+5.482583e-08", "5.482583e-08", "0.000000", "0.000000", "+0.000000", "5.482583e-08", "5.482583e-08", "+5.482583e-08", "5.4825828e-08", "+5.4825828e-08", "5.4825828e-08", "0.0000001", "0.0000001", "+0.0000001", "5.4825828e-08", "5.4825828e-08", "+5.4825828e-08", "5.48258279e-08", "+5.48258279e-08", "5.48258279e-08", "0.00000005", "0.00000005", "+0.00000005", "5.48258279e-08", "5.48258279e-08", "+5.48258279e-08", "5.482582788e-08", "+5.482582788e-08", "5.482582788e-08", "0.000000055", "0.000000055", "+0.000000055", "5.482582788e-08", "5.482582788e-08", "+5.482582788e-08", "5.4825827878e-08", "+5.4825827878e-08", "5.4825827878e-08", "0.0000000548", "0.0000000548", "+0.0000000548", "5.4825827878e-08", "5.4825827878e-08", "+5.4825827878e-08", "5.48258278776e-08", "+5.48258278776e-08", "5.48258278776e-08", "0.00000005483", "0.00000005483", "+0.00000005483", "5.48258278776e-08", "5.48258278776e-08", "+5.48258278776e-08", "5.482582787764e-08", "+5.482582787764e-08", "5.482582787764e-08", "0.000000054826", "0.000000054826", "+0.000000054826", "5.482582787764e-08", "5.482582787764e-08", "+5.482582787764e-08", "5.4825827877636e-08", "+5.4825827877636e-08", "5.4825827877636e-08", "0.0000000548258", "0.0000000548258", "+0.0000000548258", }}, + {{ "-5e-08", "-5.e-08", "-5e-08", "-5.5e-08", "-5.5e-08", "-5.5e-08", "-0.0", "-0.0", "-0.0", "-5.5e-08", "-5.5e-08", "-5.5e-08", "-5.48e-08", "-5.48e-08", "-5.48e-08", "-0.00", "-0.00", "-0.00", "-5.48e-08", "-5.48e-08", "-5.48e-08", "-5.483e-08", "-5.483e-08", "-5.483e-08", "-0.000", "-0.000", "-0.000", "-5.483e-08", "-5.483e-08", "-5.483e-08", "-5.4826e-08", "-5.4826e-08", "-5.4826e-08", "-0.0000", "-0.0000", "-0.0000", "-5.4826e-08", "-5.4826e-08", "-5.4826e-08", "-5.48258e-08", "-5.48258e-08", "-5.48258e-08", "-0.00000", "-0.00000", "-0.00000", "-5.48258e-08", "-5.48258e-08", "-5.48258e-08", "-5.482583e-08", "-5.482583e-08", "-5.482583e-08", "-0.000000", "-0.000000", "-0.000000", "-5.482583e-08", "-5.482583e-08", "-5.482583e-08", "-5.4825828e-08", "-5.4825828e-08", "-5.4825828e-08", "-0.0000001", "-0.0000001", "-0.0000001", "-5.4825828e-08", "-5.4825828e-08", "-5.4825828e-08", "-5.48258279e-08", "-5.48258279e-08", "-5.48258279e-08", "-0.00000005", "-0.00000005", "-0.00000005", "-5.48258279e-08", "-5.48258279e-08", "-5.48258279e-08", "-5.482582788e-08", "-5.482582788e-08", "-5.482582788e-08", "-0.000000055", "-0.000000055", "-0.000000055", "-5.482582788e-08", "-5.482582788e-08", "-5.482582788e-08", "-5.4825827878e-08", "-5.4825827878e-08", "-5.4825827878e-08", "-0.0000000548", "-0.0000000548", "-0.0000000548", "-5.4825827878e-08", "-5.4825827878e-08", "-5.4825827878e-08", "-5.48258278776e-08", "-5.48258278776e-08", "-5.48258278776e-08", "-0.00000005483", "-0.00000005483", "-0.00000005483", "-5.48258278776e-08", "-5.48258278776e-08", "-5.48258278776e-08", "-5.482582787764e-08", "-5.482582787764e-08", "-5.482582787764e-08", "-0.000000054826", "-0.000000054826", "-0.000000054826", "-5.482582787764e-08", "-5.482582787764e-08", "-5.482582787764e-08", "-5.4825827877636e-08", "-5.4825827877636e-08", "-5.4825827877636e-08", "-0.0000000548258", "-0.0000000548258", "-0.0000000548258", }}, + {{ "7e-09", "7.e-09", "+7e-09", "6.9e-09", "+6.9e-09", "6.9e-09", "0.0", "0.0", "+0.0", "6.9e-09", "6.9e-09", "+6.9e-09", "6.85e-09", "+6.85e-09", "6.85e-09", "0.00", "0.00", "+0.00", "6.85e-09", "6.85e-09", "+6.85e-09", "6.853e-09", "+6.853e-09", "6.853e-09", "0.000", "0.000", "+0.000", "6.853e-09", "6.853e-09", "+6.853e-09", "6.8532e-09", "+6.8532e-09", "6.8532e-09", "0.0000", "0.0000", "+0.0000", "6.8532e-09", "6.8532e-09", "+6.8532e-09", "6.85323e-09", "+6.85323e-09", "6.85323e-09", "0.00000", "0.00000", "+0.00000", "6.85323e-09", "6.85323e-09", "+6.85323e-09", "6.853228e-09", "+6.853228e-09", "6.853228e-09", "0.000000", "0.000000", "+0.000000", "6.853228e-09", "6.853228e-09", "+6.853228e-09", "6.8532285e-09", "+6.8532285e-09", "6.8532285e-09", "0.0000000", "0.0000000", "+0.0000000", "6.8532285e-09", "6.8532285e-09", "+6.8532285e-09", "6.85322848e-09", "+6.85322848e-09", "6.85322848e-09", "0.00000001", "0.00000001", "+0.00000001", "6.85322848e-09", "6.85322848e-09", "+6.85322848e-09", "6.853228485e-09", "+6.853228485e-09", "6.853228485e-09", "0.000000007", "0.000000007", "+0.000000007", "6.853228485e-09", "6.853228485e-09", "+6.853228485e-09", "6.8532284847e-09", "+6.8532284847e-09", "6.8532284847e-09", "0.0000000069", "0.0000000069", "+0.0000000069", "6.8532284847e-09", "6.8532284847e-09", "+6.8532284847e-09", "6.85322848470e-09", "+6.85322848470e-09", "6.85322848470e-09", "0.00000000685", "0.00000000685", "+0.00000000685", "6.8532284847e-09", "6.85322848470e-09", "+6.8532284847e-09", "6.853228484704e-09", "+6.853228484704e-09", "6.853228484704e-09", "0.000000006853", "0.000000006853", "+0.000000006853", "6.853228484704e-09", "6.853228484704e-09", "+6.853228484704e-09", "6.8532284847045e-09", "+6.8532284847045e-09", "6.8532284847045e-09", "0.0000000068532", "0.0000000068532", "+0.0000000068532", }}, + {{ "-7e-09", "-7.e-09", "-7e-09", "-6.9e-09", "-6.9e-09", "-6.9e-09", "-0.0", "-0.0", "-0.0", "-6.9e-09", "-6.9e-09", "-6.9e-09", "-6.85e-09", "-6.85e-09", "-6.85e-09", "-0.00", "-0.00", "-0.00", "-6.85e-09", "-6.85e-09", "-6.85e-09", "-6.853e-09", "-6.853e-09", "-6.853e-09", "-0.000", "-0.000", "-0.000", "-6.853e-09", "-6.853e-09", "-6.853e-09", "-6.8532e-09", "-6.8532e-09", "-6.8532e-09", "-0.0000", "-0.0000", "-0.0000", "-6.8532e-09", "-6.8532e-09", "-6.8532e-09", "-6.85323e-09", "-6.85323e-09", "-6.85323e-09", "-0.00000", "-0.00000", "-0.00000", "-6.85323e-09", "-6.85323e-09", "-6.85323e-09", "-6.853228e-09", "-6.853228e-09", "-6.853228e-09", "-0.000000", "-0.000000", "-0.000000", "-6.853228e-09", "-6.853228e-09", "-6.853228e-09", "-6.8532285e-09", "-6.8532285e-09", "-6.8532285e-09", "-0.0000000", "-0.0000000", "-0.0000000", "-6.8532285e-09", "-6.8532285e-09", "-6.8532285e-09", "-6.85322848e-09", "-6.85322848e-09", "-6.85322848e-09", "-0.00000001", "-0.00000001", "-0.00000001", "-6.85322848e-09", "-6.85322848e-09", "-6.85322848e-09", "-6.853228485e-09", "-6.853228485e-09", "-6.853228485e-09", "-0.000000007", "-0.000000007", "-0.000000007", "-6.853228485e-09", "-6.853228485e-09", "-6.853228485e-09", "-6.8532284847e-09", "-6.8532284847e-09", "-6.8532284847e-09", "-0.0000000069", "-0.0000000069", "-0.0000000069", "-6.8532284847e-09", "-6.8532284847e-09", "-6.8532284847e-09", "-6.85322848470e-09", "-6.85322848470e-09", "-6.85322848470e-09", "-0.00000000685", "-0.00000000685", "-0.00000000685", "-6.8532284847e-09", "-6.85322848470e-09", "-6.8532284847e-09", "-6.853228484704e-09", "-6.853228484704e-09", "-6.853228484704e-09", "-0.000000006853", "-0.000000006853", "-0.000000006853", "-6.853228484704e-09", "-6.853228484704e-09", "-6.853228484704e-09", "-6.8532284847045e-09", "-6.8532284847045e-09", "-6.8532284847045e-09", "-0.0000000068532", "-0.0000000068532", "-0.0000000068532", }}, + {{ "9e-10", "9.e-10", "+9e-10", "8.6e-10", "+8.6e-10", "8.6e-10", "0.0", "0.0", "+0.0", "8.6e-10", "8.6e-10", "+8.6e-10", "8.57e-10", "+8.57e-10", "8.57e-10", "0.00", "0.00", "+0.00", "8.57e-10", "8.57e-10", "+8.57e-10", "8.567e-10", "+8.567e-10", "8.567e-10", "0.000", "0.000", "+0.000", "8.567e-10", "8.567e-10", "+8.567e-10", "8.5665e-10", "+8.5665e-10", "8.5665e-10", "0.0000", "0.0000", "+0.0000", "8.5665e-10", "8.5665e-10", "+8.5665e-10", "8.56654e-10", "+8.56654e-10", "8.56654e-10", "0.00000", "0.00000", "+0.00000", "8.56654e-10", "8.56654e-10", "+8.56654e-10", "8.566536e-10", "+8.566536e-10", "8.566536e-10", "0.000000", "0.000000", "+0.000000", "8.566536e-10", "8.566536e-10", "+8.566536e-10", "8.5665356e-10", "+8.5665356e-10", "8.5665356e-10", "0.0000000", "0.0000000", "+0.0000000", "8.5665356e-10", "8.5665356e-10", "+8.5665356e-10", "8.56653561e-10", "+8.56653561e-10", "8.56653561e-10", "0.00000000", "0.00000000", "+0.00000000", "8.56653561e-10", "8.56653561e-10", "+8.56653561e-10", "8.566535606e-10", "+8.566535606e-10", "8.566535606e-10", "0.000000001", "0.000000001", "+0.000000001", "8.566535606e-10", "8.566535606e-10", "+8.566535606e-10", "8.5665356059e-10", "+8.5665356059e-10", "8.5665356059e-10", "0.0000000009", "0.0000000009", "+0.0000000009", "8.5665356059e-10", "8.5665356059e-10", "+8.5665356059e-10", "8.56653560588e-10", "+8.56653560588e-10", "8.56653560588e-10", "0.00000000086", "0.00000000086", "+0.00000000086", "8.56653560588e-10", "8.56653560588e-10", "+8.56653560588e-10", "8.566535605881e-10", "+8.566535605881e-10", "8.566535605881e-10", "0.000000000857", "0.000000000857", "+0.000000000857", "8.566535605881e-10", "8.566535605881e-10", "+8.566535605881e-10", "8.5665356058806e-10", "+8.5665356058806e-10", "8.5665356058806e-10", "0.0000000008567", "0.0000000008567", "+0.0000000008567", }}, + {{ "-9e-10", "-9.e-10", "-9e-10", "-8.6e-10", "-8.6e-10", "-8.6e-10", "-0.0", "-0.0", "-0.0", "-8.6e-10", "-8.6e-10", "-8.6e-10", "-8.57e-10", "-8.57e-10", "-8.57e-10", "-0.00", "-0.00", "-0.00", "-8.57e-10", "-8.57e-10", "-8.57e-10", "-8.567e-10", "-8.567e-10", "-8.567e-10", "-0.000", "-0.000", "-0.000", "-8.567e-10", "-8.567e-10", "-8.567e-10", "-8.5665e-10", "-8.5665e-10", "-8.5665e-10", "-0.0000", "-0.0000", "-0.0000", "-8.5665e-10", "-8.5665e-10", "-8.5665e-10", "-8.56654e-10", "-8.56654e-10", "-8.56654e-10", "-0.00000", "-0.00000", "-0.00000", "-8.56654e-10", "-8.56654e-10", "-8.56654e-10", "-8.566536e-10", "-8.566536e-10", "-8.566536e-10", "-0.000000", "-0.000000", "-0.000000", "-8.566536e-10", "-8.566536e-10", "-8.566536e-10", "-8.5665356e-10", "-8.5665356e-10", "-8.5665356e-10", "-0.0000000", "-0.0000000", "-0.0000000", "-8.5665356e-10", "-8.5665356e-10", "-8.5665356e-10", "-8.56653561e-10", "-8.56653561e-10", "-8.56653561e-10", "-0.00000000", "-0.00000000", "-0.00000000", "-8.56653561e-10", "-8.56653561e-10", "-8.56653561e-10", "-8.566535606e-10", "-8.566535606e-10", "-8.566535606e-10", "-0.000000001", "-0.000000001", "-0.000000001", "-8.566535606e-10", "-8.566535606e-10", "-8.566535606e-10", "-8.5665356059e-10", "-8.5665356059e-10", "-8.5665356059e-10", "-0.0000000009", "-0.0000000009", "-0.0000000009", "-8.5665356059e-10", "-8.5665356059e-10", "-8.5665356059e-10", "-8.56653560588e-10", "-8.56653560588e-10", "-8.56653560588e-10", "-0.00000000086", "-0.00000000086", "-0.00000000086", "-8.56653560588e-10", "-8.56653560588e-10", "-8.56653560588e-10", "-8.566535605881e-10", "-8.566535605881e-10", "-8.566535605881e-10", "-0.000000000857", "-0.000000000857", "-0.000000000857", "-8.566535605881e-10", "-8.566535605881e-10", "-8.566535605881e-10", "-8.5665356058806e-10", "-8.5665356058806e-10", "-8.5665356058806e-10", "-0.0000000008567", "-0.0000000008567", "-0.0000000008567", }}, diff --git a/test/test.hpp b/test/test.hpp new file mode 100644 index 00000000..d8606f45 --- /dev/null +++ b/test/test.hpp @@ -0,0 +1,271 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// + +#ifndef BOOST_MULTIPRECISION_TEST_HPP +#define BOOST_MULTIPRECISION_TEST_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace detail{ + +template +inline typename boost::disable_if_c::value || boost::multiprecision::is_unsigned_number::value, T>::type + abs(const T& a) +{ + return a < 0 ? -a : a; +} + +template +inline typename boost::enable_if_c::value || boost::multiprecision::is_unsigned_number::value, T>::type + abs(const T& a) +{ + return a; +} + +} + +template +T relative_error(T a, T b) +{ + using std::abs; + using detail::abs; + + T min_val = (std::numeric_limits::min)(); + T max_val = (std::numeric_limits::max)(); + + if((a != 0) && (b != 0)) + { + // TODO: use isfinite: + if(abs(b) >= max_val) + { + if(abs(a) >= max_val) + return 0; // one infinity is as good as another! + } + // If the result is denormalised, treat all denorms as equivalent: + if((a < min_val) && (a > 0)) + a = min_val; + else if((a > -min_val) && (a < 0)) + a = -min_val; + if((b < min_val) && (b > 0)) + b = min_val; + else if((b > -min_val) && (b < 0)) + b = -min_val; + return (std::max)(abs(T((a-b)/a)), abs(T((a-b)/b))) / std::numeric_limits::epsilon(); + } + + // Handle special case where one or both are zero: + if(min_val == 0) + return abs(T(a-b)); + if(abs(a) < min_val) + a = min_val; + if(abs(b) < min_val) + b = min_val; + return (std::max)(abs(T((a-b)/a)), abs(T((a-b)/b))) / std::numeric_limits::epsilon(); +} + +enum +{ + warn_on_fail, + error_on_fail, + abort_on_fail +}; + +template +inline T epsilon_of(const T&) +{ + BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); + return std::numeric_limits::epsilon(); +} + +template +inline int digits_of(const T&) +{ + return std::numeric_limits::is_specialized ? std::numeric_limits::digits10 + 2 : std::numeric_limits::digits10 + 2; +} + +inline std::ostream& report_where(const char* file, int line, const char* function) +{ + if(function) + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "In function: "<< function << std::endl; + BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << ":" << line; + return BOOST_LIGHTWEIGHT_TEST_OSTREAM; +} + +#define BOOST_MP_REPORT_WHERE report_where(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION) + +inline void report_severity(int severity) +{ + if(severity == error_on_fail) + ++boost::detail::test_errors(); + else if(severity == abort_on_fail) + { + ++boost::detail::test_errors(); + abort(); + } +} + +#define BOOST_MP_REPORT_SEVERITY(severity) report_severity(severity) + +template +void report_unexpected_exception(const E& e, int severity, const char* file, int line, const char* function) +{ + report_where(file, line, function) << " Unexpected exception of type " << typeid(e).name() << std::endl; + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Errot message was: " << e.what() << std::endl; + BOOST_MP_REPORT_SEVERITY(severity); +} + +#define BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) \ + catch(const std::exception& e) \ + { report_unexpected_exception(e, severity, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); }\ + catch(...)\ + { std::cout << "Exception of unknown type was thrown" << std::endl; report_severity(severity); } + + +#define BOOST_CHECK_IMP(x, severity)\ + try{ if(x){}else{\ + BOOST_MP_REPORT_WHERE << " Failed predicate: " << BOOST_STRINGIZE(x) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_CHECK(x) BOOST_CHECK_IMP(x, error_on_fail) +#define BOOST_WARN(x) BOOST_CHECK_IMP(x, warn_on_fail) +#define BOOST_REQUIRE(x) BOOST_CHECK_IMP(x, abort_on_fail) + +#define BOOST_CLOSE_IMP(x, y, tol, severity)\ + try{ if(relative_error(x, y) > tol){\ + BOOST_MP_REPORT_WHERE << " Failed check for closeness: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(5) << std::fixed\ + << "Relative error was: " << relative_error(x, y) << "eps\n"\ + << "Tolerance was: " << tol << "eps" << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_EQUAL_IMP(x, y, severity)\ + try{ if(x != y){\ + BOOST_MP_REPORT_WHERE << " Failed check for equality: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_NE_IMP(x, y, severity)\ + try{ if(!(x != y)){\ + BOOST_MP_REPORT_WHERE << " Failed check for non-equality: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_LT_IMP(x, y, severity)\ + try{ if(!(x < y)){\ + BOOST_MP_REPORT_WHERE << " Failed check for less than: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_GT_IMP(x, y, severity)\ + try{ if(!(x > y)){\ + BOOST_MP_REPORT_WHERE << " Failed check for greater than: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_LE_IMP(x, y, severity)\ + try{ if(!(x <= y)){\ + BOOST_MP_REPORT_WHERE << " Failed check for less-than-equal-to: \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_GE_IMP(x, y, severity)\ + try{ if(!(x >= y)){\ + BOOST_MP_REPORT_WHERE << " Failed check for greater-than-equal-to \n" \ + << std::setprecision(digits_of(x)) << std::scientific\ + << "Value of LHS was: " << x << "\n"\ + << "Value of RHS was: " << y << "\n"\ + << std::setprecision(3) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + }BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_MT_CHECK_THROW_IMP(x, E, severity)\ + try{ \ + x;\ + BOOST_MP_REPORT_WHERE << " Expected exception not thrown in expression " << BOOST_STRINGIZE(x) << std::endl;\ + BOOST_MP_REPORT_SEVERITY(severity);\ + }\ + catch(const E&){}\ + BOOST_MP_UNEXPECTED_EXCEPTION_CHECK(severity) + +#define BOOST_CHECK_CLOSE(x, y, tol) BOOST_CLOSE_IMP(x, y, ((tol / (100 * epsilon_of(x)))), error_on_fail) +#define BOOST_WARN_CLOSE(x, y, tol) BOOST_CLOSE_IMP(x, y, (tol / (100 * epsilon_of(x))), warn_on_fail) +#define BOOST_REQUIRE_CLOSE(x, y, tol) BOOST_CLOSE_IMP(x, y, (tol / (100 * epsilon_of(x))), abort_on_fail) + +#define BOOST_CHECK_CLOSE_FRACTION(x, y, tol) BOOST_CLOSE_IMP(x, y, ((tol / (epsilon_of(x)))), error_on_fail) +#define BOOST_WARN_CLOSE_FRACTION(x, y, tol) BOOST_CLOSE_IMP(x, y, (tol / (epsilon_of(x))), warn_on_fail) +#define BOOST_REQUIRE_CLOSE_FRACTION(x, y, tol) BOOST_CLOSE_IMP(x, y, (tol / (epsilon_of(x))), abort_on_fail) + +#define BOOST_CHECK_EQUAL(x, y) BOOST_EQUAL_IMP(x, y, error_on_fail) +#define BOOST_WARN_EQUAL(x, y) BOOST_EQUAL_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_EQUAL(x, y) BOOST_EQUAL_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_NE(x, y) BOOST_NE_IMP(x, y, error_on_fail) +#define BOOST_WARN_NE(x, y) BOOST_NE_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_NE(x, y) BOOST_NE_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_LT(x, y) BOOST_LT_IMP(x, y, error_on_fail) +#define BOOST_WARN_LT(x, y) BOOST_LT_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_LT(x, y) BOOST_LT_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_GT(x, y) BOOST_GT_IMP(x, y, error_on_fail) +#define BOOST_WARN_GT(x, y) BOOST_GT_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_GT(x, y) BOOST_GT_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_LE(x, y) BOOST_LE_IMP(x, y, error_on_fail) +#define BOOST_WARN_LE(x, y) BOOST_LE_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_LE(x, y) BOOST_LE_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_GE(x, y) BOOST_GE_IMP(x, y, error_on_fail) +#define BOOST_WARN_GE(x, y) BOOST_GE_IMP(x, y, warn_on_fail) +#define BOOST_REQUIRE_GE(x, y) BOOST_GE_IMP(x, y, abort_on_fail) + +#define BOOST_CHECK_THROW(x, E) BOOST_MT_CHECK_THROW_IMP(x, E, error_on_fail) +#define BOOST_WARN_THROW(x, E) BOOST_MT_CHECK_THROW_IMP(x, E, warn_on_fail) +#define BOOST_REQUIRE_THROW(x, E) BOOST_MT_CHECK_THROW_IMP(x, E, abort_on_fail) + +#endif diff --git a/test/test_acos.cpp b/test/test_acos.cpp new file mode 100644 index 00000000..44bee8a5 --- /dev/null +++ b/test/test_acos.cpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + // + // Test with some exact binary values as input - this tests our code + // rather than the test data: + // + static const boost::array, 13> exact_data = + {{ + {{ 0.5, static_cast("1.04719755119659774615421446109316762806572313312503527365831486410260546876206966620934494178070568932738269550442743555") }}, + {{ 0.25, static_cast("1.31811607165281796574566425464604046984639096659071471685354851741333314266208327690226867044304393238598144034722708676") }}, + {{0.75, static_cast("0.722734247813415611178377352641333362025218486424440267626754132583707381914630264964827610939101303690078815991333621490") }}, + {{1 - std::ldexp(1.0, -20), static_cast("0.00138106804176241718210883847756746694048570648553426714212025111150044290934710742282266738617709904634187850607042604204") }}, + {{std::ldexp(1.0, -20), static_cast("1.57079537312058021283676140197495835299636605165647561806789944133748780804448843729970624018104090863783682329820313127") }}, + {{1, static_cast("0") }}, + + {{0, static_cast("1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404325664115332") }}, + + {{ -0.5, static_cast("2.09439510239319549230842892218633525613144626625007054731662972820521093752413933241868988356141137865476539100885487110") }}, + {{ -0.25, static_cast("1.82347658193697527271697912863346241435077843278439110412139607489448326362412572172576615489907313559616664616605521989") }}, + {{-0.75, static_cast("2.41885840577637762728426603063816952217195091295066555334819045972410902437157873366320721440301576429206927052194868516") }}, + {{-1 + std::ldexp(1.0, -20), static_cast("3.14021158554803082128053454480193541725668369288957155383282434119631596337686189120521215795593996893580620800721188061") }}, + {{-std::ldexp(1.0, -20), static_cast("1.57079728046921302562588198130454453120080334771863020290704515097032859824172056132832858516107615934431126321507917538") }}, + {{-1, static_cast("3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230665") }}, + }}; + unsigned max_err = 0; + for(unsigned k = 0; k < exact_data.size(); k++) + { + T val = acos(exact_data[k][0]); + T e = relative_error(val, exact_data[k][1]); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); + BOOST_TEST(asin(T(0)) == 0); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_arithmetic.cpp b/test/test_arithmetic.cpp new file mode 100644 index 00000000..dd97caf4 --- /dev/null +++ b/test/test_arithmetic.cpp @@ -0,0 +1,1891 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#ifdef TEST_VLD +#include +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && \ + !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) \ + && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\ + && !defined(TEST_CPP_INT_1) && !defined(TEST_CPP_INT_2) && !defined(TEST_CPP_INT_3) \ + && !defined(TEST_CPP_INT_1A) && !defined(TEST_CPP_INT_2A) && !defined(TEST_CPP_INT_3A) \ + && !defined(TEST_CPP_INT_BR) && !defined(TEST_ARITHMETIC_BACKEND) +# define TEST_MPF_50 +# define TEST_MPF +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT +# define TEST_MPQ +# define TEST_TOMMATH +# define TEST_CPP_INT_1 +# define TEST_CPP_INT_2 +# define TEST_CPP_INT_3 +# define TEST_CPP_INT_1A +# define TEST_CPP_INT_2A +# define TEST_CPP_INT_3A +# define TEST_CPP_INT_BR +# define TEST_ARITHMETIC_BACKEND + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_ARITHMETIC_BACKEND) +# include "../performance/arithmetic_backend.hpp" +#endif +#if defined(TEST_MPF_50) || defined(TEST_MPF) || defined(TEST_MPZ) || defined(TEST_MPQ) || defined(TEST_MPZ_BOOST_RATIONAL) +#include +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif +#if defined(TEST_MPFR) || defined(TEST_MPFR_50) +#include +#endif +#if defined(TEST_TOMMATH) || defined(TEST_TOMMATH_BOOST_RATIONAL) +#include +#include +#endif +#if defined(TEST_CPP_INT_1) || defined(TEST_CPP_INT_2) || defined(TEST_CPP_INT_3) || defined(TEST_CPP_INT_BR) || defined(TEST_CPP_INT_1A) || defined(TEST_CPP_INT_2A) || defined(TEST_CPP_INT_3A) +#include +#endif + +template +struct is_boost_rational : public boost::mpl::false_{}; + +#if defined(TEST_TOMMATH_BOOST_RATIONAL) || defined(TEST_MPZ_BOOST_RATIONAL) +#include + +#define NO_MIXED_OPS + +template +struct is_boost_rational > : public boost::mpl::true_{}; + +namespace boost{ namespace multiprecision{ + +#ifdef TEST_TOMMATH_BOOST_RATIONAL +template<> +struct number_category > : public mpl::int_ {}; +#endif +#ifdef TEST_MPZ_BOOST_RATIONAL +template<> +struct number_category > : public mpl::int_ {}; +#endif + +}} + +#endif + +#ifdef BOOST_MSVC +// warning C4127: conditional expression is constant +#pragma warning(disable:4127) +#endif + +#define BOOST_TEST_THROW(x, EX)\ + try { x; BOOST_ERROR("Expected exception not thrown"); } \ + catch(const EX&){}\ + catch(...){ BOOST_ERROR("Incorrect exception type thrown"); } + +#undef BOOST_TEST +#define BOOST_TEST(x)\ + try {\ + if(x){}else{ BOOST_ERROR("Value was zero: "); }\ + }\ + catch(const std::exception& e){ \ + BOOST_ERROR("Unexpected exception: ");\ + BOOST_LIGHTWEIGHT_TEST_OSTREAM << e.what() << std::endl;\ + } + +bool isfloat(float){ return true; } +bool isfloat(double){ return true; } +bool isfloat(long double){ return true; } +template bool isfloat(T){ return false; } + +namespace detail{ + +template +typename boost::multiprecision::detail::expression::result_type + abs(boost::multiprecision::detail::expression const& v) +{ + typedef typename boost::multiprecision::detail::expression::result_type result_type; + return v < 0 ? result_type(-v) : result_type(v); +} + +} + +#define BOOST_TEST_CLOSE(x, y, tol)\ + if(x == 0){\ + BOOST_TEST(y == 0); }\ + else if(!isfloat(x)){\ + BOOST_TEST(x == y); }\ + else if((x != y) && (detail::abs((x-y)/x) > tol))\ + {\ + BOOST_ERROR("Expected tolerance was exceeded: ");\ + BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::setprecision(34) << "(x-y)/x = " << detail::abs((x-y)/x) \ + << " tolerance = " << tol << std::endl;\ + } + +template +struct is_twos_complement_integer : public boost::mpl::true_ {}; + +#ifdef TEST_TOMMATH +template <> +struct is_twos_complement_integer : public boost::mpl::false_ {}; +#endif +#if defined(TEST_CPP_INT_1) || defined(TEST_CPP_INT_2) || defined(TEST_CPP_INT_3) || defined(TEST_CPP_INT_BR) || defined(TEST_CPP_INT_1A) || defined(TEST_CPP_INT_2A) || defined(TEST_CPP_INT_3A) +template +struct is_twos_complement_integer, ExpressionTemplates> > : public boost::mpl::false_ {}; +#endif + +#define BOOST_TEST_EQUAL(a, b) BOOST_TEST((a) == (b)) + + +template +struct related_type +{ + typedef T type; +}; + +#ifdef TEST_MPQ +template <> +struct related_type +{ + typedef boost::multiprecision::mpz_int type; +}; +#endif +#if defined(TEST_MPF_50) || defined(TEST_MPF) +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::gmp_float > type; +}; +template <> +struct related_type +{ + typedef boost::multiprecision::mpz_int type; +}; +#endif +#ifdef TEST_CPP_DEC_FLOAT +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::cpp_dec_float > type; +}; +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR) +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::mpfr_float_backend > type; +}; +#endif +#if defined(TEST_CPP_INT_1) || defined(TEST_CPP_INT_2) || defined(TEST_CPP_INT_3) || defined(TEST_CPP_INT_BR) || defined(TEST_CPP_INT_1A) || defined(TEST_CPP_INT_2A) || defined(TEST_CPP_INT_3A) +template <> +struct related_type +{ + typedef boost::multiprecision::int256_t type; +}; +template +struct related_type, ET> > +{ + typedef boost::multiprecision::number, ET> type; +}; +#endif +template +void test_comparisons(Val, Val, const boost::mpl::false_) +{} + +int normalize_compare_result(int r) +{ + return r > 0 ? 1 : r < 0 ? -1 : 0; +} + +template +void test_comparisons(Val a, Val b, const boost::mpl::true_) +{ + Real r1(a); + Real r2(b); + Real z(1); + + int cr = a < b ? -1 : a > b ? 1 : 0; + + BOOST_TEST_EQUAL(r1 == r2, a == b); + BOOST_TEST_EQUAL(r1 != r2, a != b); + BOOST_TEST_EQUAL(r1 <= r2, a <= b); + BOOST_TEST_EQUAL(r1 < r2, a < b); + BOOST_TEST_EQUAL(r1 >= r2, a >= b); + BOOST_TEST_EQUAL(r1 > r2, a > b); + + BOOST_TEST_EQUAL(r1 == b, a == b); + BOOST_TEST_EQUAL(r1 != b, a != b); + BOOST_TEST_EQUAL(r1 <= b, a <= b); + BOOST_TEST_EQUAL(r1 < b, a < b); + BOOST_TEST_EQUAL(r1 >= b, a >= b); + BOOST_TEST_EQUAL(r1 > b, a > b); + + BOOST_TEST_EQUAL(a == r2, a == b); + BOOST_TEST_EQUAL(a != r2, a != b); + BOOST_TEST_EQUAL(a <= r2, a <= b); + BOOST_TEST_EQUAL(a < r2, a < b); + BOOST_TEST_EQUAL(a >= r2, a >= b); + BOOST_TEST_EQUAL(a > r2, a > b); + + BOOST_TEST_EQUAL(r1*z == r2, a == b); + BOOST_TEST_EQUAL(r1*z != r2, a != b); + BOOST_TEST_EQUAL(r1*z <= r2, a <= b); + BOOST_TEST_EQUAL(r1*z < r2, a < b); + BOOST_TEST_EQUAL(r1*z >= r2, a >= b); + BOOST_TEST_EQUAL(r1*z > r2, a > b); + + BOOST_TEST_EQUAL(r1 == r2*z, a == b); + BOOST_TEST_EQUAL(r1 != r2*z, a != b); + BOOST_TEST_EQUAL(r1 <= r2*z, a <= b); + BOOST_TEST_EQUAL(r1 < r2*z, a < b); + BOOST_TEST_EQUAL(r1 >= r2*z, a >= b); + BOOST_TEST_EQUAL(r1 > r2*z, a > b); + + BOOST_TEST_EQUAL(r1*z == r2*z, a == b); + BOOST_TEST_EQUAL(r1*z != r2*z, a != b); + BOOST_TEST_EQUAL(r1*z <= r2*z, a <= b); + BOOST_TEST_EQUAL(r1*z < r2*z, a < b); + BOOST_TEST_EQUAL(r1*z >= r2*z, a >= b); + BOOST_TEST_EQUAL(r1*z > r2*z, a > b); + + BOOST_TEST_EQUAL(r1*z == b, a == b); + BOOST_TEST_EQUAL(r1*z != b, a != b); + BOOST_TEST_EQUAL(r1*z <= b, a <= b); + BOOST_TEST_EQUAL(r1*z < b, a < b); + BOOST_TEST_EQUAL(r1*z >= b, a >= b); + BOOST_TEST_EQUAL(r1*z > b, a > b); + + BOOST_TEST_EQUAL(a == r2*z, a == b); + BOOST_TEST_EQUAL(a != r2*z, a != b); + BOOST_TEST_EQUAL(a <= r2*z, a <= b); + BOOST_TEST_EQUAL(a < r2*z, a < b); + BOOST_TEST_EQUAL(a >= r2*z, a >= b); + BOOST_TEST_EQUAL(a > r2*z, a > b); + + BOOST_TEST_EQUAL(normalize_compare_result(r1.compare(r2)), cr); + BOOST_TEST_EQUAL(normalize_compare_result(r2.compare(r1)), -cr); + BOOST_TEST_EQUAL(normalize_compare_result(r1.compare(b)), cr); + BOOST_TEST_EQUAL(normalize_compare_result(r2.compare(a)), -cr); +} + +template +void test_conditional(Real v, Exp e) +{ + // + // Verify that Exp is usable in Boolean contexts, and has the same value as v: + // + if(e) + { + BOOST_TEST(v); + } + else + { + BOOST_TEST(!v); + } + if(!e) + { + BOOST_TEST(!v); + } + else + { + BOOST_TEST(v); + } +} + +template +void test_complement(Real a, Real b, Real c, const boost::mpl::true_&) +{ + int i = 1020304; + int j = 56789123; + int sign_mask = ~0; + if(std::numeric_limits::is_signed) + { + BOOST_TEST(~a == (~i & sign_mask)); + c = a & ~b; + BOOST_TEST(c == (i & (~j & sign_mask))); + c = ~(a | b); + BOOST_TEST(c == (~(i | j) & sign_mask)); + } + else + { + BOOST_TEST((~a & a) == 0); + } +} + +template +void test_complement(Real, Real, Real, const boost::mpl::false_&) +{ +} + +template +void test_integer_ops(const T&){} + +template +void test_rational(const boost::mpl::true_&) +{ + Real a(2); + a /= 3; + BOOST_TEST(numerator(a) == 2); + BOOST_TEST(denominator(a) == 3); + Real b(4); + b /= 6; + BOOST_TEST(a == b); + + // + // Check IO code: + // + std::stringstream ss; + ss << a; + ss >> b; + BOOST_CHECK_EQUAL(a, b); +} + +template +void test_rational(const boost::mpl::false_&) +{ + Real a(2); + a /= 3; + BOOST_TEST(numerator(a) == 2); + BOOST_TEST(denominator(a) == 3); + Real b(4); + b /= 6; + BOOST_TEST(a == b); + + BOOST_CHECK_THROW(Real(a / 0), std::overflow_error); + BOOST_CHECK_THROW(Real("3.14"), std::runtime_error); + b = Real("2/3"); + BOOST_CHECK_EQUAL(a, b); + // + // Check IO code: + // + std::stringstream ss; + ss << a; + ss >> b; + BOOST_CHECK_EQUAL(a, b); +} + +template +void test_integer_ops(const boost::mpl::int_&) +{ + test_rational(is_boost_rational()); +} + +template +void test_signed_integer_ops(const boost::mpl::true_&) +{ + Real a(20); + Real b(7); + Real c(5); + BOOST_TEST(-a % c == 0); + BOOST_TEST(-a % b == -20 % 7); + BOOST_TEST(-a % -b == -20 % -7); + BOOST_TEST(a % -b == 20 % -7); + BOOST_TEST(-a % 7 == -20 % 7); + BOOST_TEST(-a % -7 == -20 % -7); + BOOST_TEST(a % -7 == 20 % -7); + BOOST_TEST(-a % 7u == -20 % 7); + BOOST_TEST(-a % a == 0); + BOOST_TEST(-a % 5 == 0); + BOOST_TEST(-a % -5 == 0); + BOOST_TEST(a % -5 == 0); + + b = -b; + BOOST_TEST(a % b == 20 % -7); + a = -a; + BOOST_TEST(a % b == -20 % -7); + BOOST_TEST(a % -7 == -20 % -7); + b = 7; + BOOST_TEST(a % b == -20 % 7); + BOOST_TEST(a % 7 == -20 % 7); + BOOST_TEST(a % 7u == -20 % 7); + + a = 20; + a %= b; + BOOST_TEST(a == 20 % 7); + a = -20; + a %= b; + BOOST_TEST(a == -20 % 7); + a = 20; + a %= -b; + BOOST_TEST(a == 20 % -7); + a = -20; + a %= -b; + BOOST_TEST(a == -20 % -7); + a = 5; + a %= b - a; + BOOST_TEST(a == 5 % (7-5)); + a = -20; + a %= 7; + BOOST_TEST(a == -20 % 7); + a = 20; + a %= -7; + BOOST_TEST(a == 20 % -7); + a = -20; + a %= -7; + BOOST_TEST(a == -20 % -7); +#ifndef BOOST_NO_LONG_LONG + a = -20; + a %= 7uLL; + BOOST_TEST(a == -20 % 7); + a = 20; + a %= -7LL; + BOOST_TEST(a == 20 % -7); + a = -20; + a %= -7LL; + BOOST_TEST(a == -20 % -7); +#endif + a = 400; + b = 45; + BOOST_TEST(gcd(a, -45) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(a, -45) == boost::math::lcm(400, 45)); + BOOST_TEST(gcd(-400, b) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(-400, b) == boost::math::lcm(400, 45)); + a = -20; + BOOST_TEST(abs(a) == 20); + BOOST_TEST(abs(-a) == 20); + BOOST_TEST(abs(+a) == 20); + a = 20; + BOOST_TEST(abs(a) == 20); + BOOST_TEST(abs(-a) == 20); + BOOST_TEST(abs(+a) == 20); + a = -400; + b = 45; + BOOST_TEST(gcd(a, b) == boost::math::gcd(-400, 45)); + BOOST_TEST(lcm(a, b) == boost::math::lcm(-400, 45)); + BOOST_TEST(gcd(a, 45) == boost::math::gcd(-400, 45)); + BOOST_TEST(lcm(a, 45) == boost::math::lcm(-400, 45)); + BOOST_TEST(gcd(-400, b) == boost::math::gcd(-400, 45)); + BOOST_TEST(lcm(-400, b) == boost::math::lcm(-400, 45)); + Real r; + divide_qr(a, b, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + BOOST_TEST(integer_modulus(a, 57) == abs(a % 57)); + b = -57; + divide_qr(a, b, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + BOOST_TEST(integer_modulus(a, -57) == abs(a % -57)); + a = 458; + divide_qr(a, b, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + BOOST_TEST(integer_modulus(a, -57) == abs(a % -57)); +} +template +void test_signed_integer_ops(const boost::mpl::false_&) +{ +} + +template +void test_integer_ops(const boost::mpl::int_&) +{ + test_signed_integer_ops(boost::mpl::bool_::is_signed>()); + + Real a(20); + Real b(7); + Real c(5); + BOOST_TEST(a % b == 20 % 7); + BOOST_TEST(a % 7 == 20 % 7); + BOOST_TEST(a % 7u == 20 % 7); + BOOST_TEST(a % a == 0); + BOOST_TEST(a % c == 0); + BOOST_TEST(a % 5 == 0); + a = a % (b + 0); + BOOST_TEST(a == 20 % 7); + a = 20; + c = (a + 2) % (a - 1); + BOOST_TEST(c == 22 % 19); + c = 5; + a = b % (a - 15); + BOOST_TEST(a == 7 % 5); + a = 20; + + a = 20; + a %= 7; + BOOST_TEST(a == 20 % 7); +#ifndef BOOST_NO_LONG_LONG + a = 20; + a %= 7uLL; + BOOST_TEST(a == 20 % 7); +#endif + a = 20; + BOOST_TEST(++a == 21); + BOOST_TEST(--a == 20); + BOOST_TEST(a++ == 20); + BOOST_TEST(a == 21); + BOOST_TEST(a-- == 21); + BOOST_TEST(a == 20); + a = 2000; + a <<= 20; + BOOST_TEST(a == 2000L << 20); + a >>= 20; + BOOST_TEST(a == 2000); + a <<= 20u; + BOOST_TEST(a == 2000L << 20); + a >>= 20u; + BOOST_TEST(a == 2000); + BOOST_TEST_THROW(a <<= -20, std::out_of_range); + BOOST_TEST_THROW(a >>= -20, std::out_of_range); + BOOST_TEST_THROW(Real(a << -20), std::out_of_range); + BOOST_TEST_THROW(Real(a >> -20), std::out_of_range); +#ifndef BOOST_NO_LONG_LONG + if(sizeof(long long) > sizeof(std::size_t)) + { + // extreme values should trigger an exception: + BOOST_TEST_THROW(a >>= (1uLL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + BOOST_TEST_THROW(a <<= (1uLL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + BOOST_TEST_THROW(a >>= -(1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + BOOST_TEST_THROW(a <<= -(1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + BOOST_TEST_THROW(a >>= (1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + BOOST_TEST_THROW(a <<= (1LL << (sizeof(long long) * CHAR_BIT - 2)), std::out_of_range); + // Unless they fit within range: + a = 2000L; + BOOST_TEST((a <<= 20uLL) == (2000L << 20)); + a = 2000; + BOOST_TEST((a <<= 20LL) == (2000L << 20)); + + BOOST_TEST_THROW(Real(a >> (1uLL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + BOOST_TEST_THROW(Real(a <<= (1uLL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + BOOST_TEST_THROW(Real(a >>= -(1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + BOOST_TEST_THROW(Real(a <<= -(1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + BOOST_TEST_THROW(Real(a >>= (1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + BOOST_TEST_THROW(Real(a <<= (1LL << (sizeof(long long) * CHAR_BIT - 2))), std::out_of_range); + // Unless they fit within range: + a = 2000L; + BOOST_TEST(Real(a << 20uLL) == (2000L << 20)); + a = 2000; + BOOST_TEST(Real(a << 20LL) == (2000L << 20)); + } +#endif + a = 20; + b = a << 20; + BOOST_TEST(b == (20 << 20)); + b = a >> 2; + BOOST_TEST(b == (20 >> 2)); + b = (a + 2) << 10; + BOOST_TEST(b == (22 << 10)); + b = (a + 3) >> 3; + BOOST_TEST(b == (23 >> 3)); + // + // Bit fiddling: + // + int i = 1020304; + int j = 56789123; + int k = 4523187; + a = i; + b = j; + c = a; + c &= b; + BOOST_TEST(c == (i & j)); + c = a; + c &= j; + BOOST_TEST(c == (i & j)); + c = a; + c &= a + b; + BOOST_TEST(c == (i & (i + j))); + BOOST_TEST((a & b) == (i & j)); + c = k; + a = a & (b + k); + BOOST_TEST(a == (i & (j + k))); + a = i; + a = (b + k) & a; + BOOST_TEST(a == (i & (j + k))); + a = i; + c = a & b & k; + BOOST_TEST(c == (i&j&k)); + c = a; + c &= (c+b); + BOOST_TEST(c == (i & (i+j))); + c = a & (b | 1); + BOOST_TEST(c == (i & (j | 1))); + + test_complement(a, b, c, typename is_twos_complement_integer::type()); + + a = i; + b = j; + c = a; + c |= b; + BOOST_TEST(c == (i | j)); + c = a; + c |= j; + BOOST_TEST(c == (i | j)); + c = a; + c |= a + b; + BOOST_TEST(c == (i | (i + j))); + BOOST_TEST((a | b) == (i | j)); + c = k; + a = a | (b + k); + BOOST_TEST(a == (i | (j + k))); + a = i; + a = (b + k) | a; + BOOST_TEST(a == (i | (j + k))); + a = i; + c = a | b | k; + BOOST_TEST(c == (i|j|k)); + c = a; + c |= (c + b); + BOOST_TEST(c == (i | (i+j))); + c = a | (b | 1); + BOOST_TEST(c == (i | (j | 1))); + + a = i; + b = j; + c = a; + c ^= b; + BOOST_TEST(c == (i ^ j)); + c = a; + c ^= j; + BOOST_TEST(c == (i ^ j)); + c = a; + c ^= a + b; + BOOST_TEST(c == (i ^ (i + j))); + BOOST_TEST((a ^ b) == (i ^ j)); + c = k; + a = a ^ (b + k); + BOOST_TEST(a == (i ^ (j + k))); + a = i; + a = (b + k) ^ a; + BOOST_TEST(a == (i ^ (j + k))); + a = i; + c = a ^ b ^ k; + BOOST_TEST(c == (i^j^k)); + c = a; + c ^= (c + b); + BOOST_TEST(c == (i ^ (i+j))); + c = a ^ (b | 1); + BOOST_TEST(c == (i ^ (j | 1))); + + a = i; + b = j; + c = k; + // + // Non-member functions: + // + a = 400; + b = 45; + BOOST_TEST(gcd(a, b) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(a, b) == boost::math::lcm(400, 45)); + BOOST_TEST(gcd(a, 45) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(a, 45) == boost::math::lcm(400, 45)); + BOOST_TEST(gcd(a, 45u) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(a, 45u) == boost::math::lcm(400, 45)); + BOOST_TEST(gcd(400, b) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(400, b) == boost::math::lcm(400, 45)); + BOOST_TEST(gcd(400u, b) == boost::math::gcd(400, 45)); + BOOST_TEST(lcm(400u, b) == boost::math::lcm(400, 45)); + + // + // Conditionals involving 2 arg functions: + // + test_conditional(Real(gcd(a, b)), gcd(a, b)); + + Real r; + divide_qr(a, b, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + divide_qr(a + 0, b, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + divide_qr(a, b+0, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + divide_qr(a+0, b+0, c, r); + BOOST_TEST(c == a / b); + BOOST_TEST(r == a % b); + BOOST_TEST(integer_modulus(a, 57) == a % 57); + for(unsigned i = 0; i < 20; ++i) + { + if(std::numeric_limits::is_specialized && (!std::numeric_limits::is_bounded || ((int)i * 17 < std::numeric_limits::digits))) + { + BOOST_TEST(lsb(Real(1) << (i * 17)) == i * 17); + BOOST_TEST(bit_test(Real(1) << (i * 17), i * 17)); + BOOST_TEST(!bit_test(Real(1) << (i * 17), i * 17 + 1)); + if(i) + { + BOOST_TEST(!bit_test(Real(1) << (i * 17), i * 17 - 1)); + } + Real zero(0); + BOOST_TEST(bit_test(bit_set(zero, i * 17), i * 17)); + zero = 0; + BOOST_TEST(bit_flip(zero, i*17) == Real(1) << i * 17); + zero = Real(1) << i * 17; + BOOST_TEST(bit_flip(zero, i * 17) == 0); + zero = Real(1) << i * 17; + BOOST_TEST(bit_unset(zero, i * 17) == 0); + } + } + // + // pow, powm: + // + BOOST_TEST(pow(Real(3), 4) == 81); + BOOST_TEST(pow(Real(3) + Real(0), 4) == 81); + BOOST_TEST(powm(Real(3), Real(4), Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3), Real(4), 13) == 81 % 13); + BOOST_TEST(powm(Real(3), Real(4), Real(13) + 0) == 81 % 13); + BOOST_TEST(powm(Real(3), Real(4) + 0, Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3), Real(4) + 0, 13) == 81 % 13); + BOOST_TEST(powm(Real(3), Real(4) + 0, Real(13) + 0) == 81 % 13); + BOOST_TEST(powm(Real(3), 4 + 0, Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3), 4 + 0, 13) == 81 % 13); + BOOST_TEST(powm(Real(3), 4 + 0, Real(13) + 0) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4), Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4), 13) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4), Real(13) + 0) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4) + 0, Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4) + 0, 13) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, Real(4) + 0, Real(13) + 0) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, 4 + 0, Real(13)) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, 4 + 0, 13) == 81 % 13); + BOOST_TEST(powm(Real(3) + 0, 4 + 0, Real(13) + 0) == 81 % 13); + // + // Conditionals involving 3 arg functions: + // + test_conditional(Real(powm(Real(3), Real(4), Real(13))), powm(Real(3), Real(4), Real(13))); + + // + // Things that are expected errors: + // + BOOST_CHECK_THROW(Real("3.14"), std::runtime_error); + BOOST_CHECK_THROW(Real("3L"), std::runtime_error); + BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error); + // + // Extra tests added for full coverage: + // + a = 20; + b = 7; + c = 20 % b; + BOOST_TEST(c == (20 % 7)); + c = 20 % (b + 0); + BOOST_TEST(c == (20 % 7)); + c = a & 10; + BOOST_TEST(c == (20 & 10)); + c = 10 & a; + BOOST_TEST(c == (20 & 10)); + c = (a + 0) & (b + 0); + BOOST_TEST(c == (20 & 7)); + c = 10 & (a + 0); + BOOST_TEST(c == (20 & 10)); + c = 10 | a; + BOOST_TEST(c == (20 | 10)); + c = (a + 0) | (b + 0); + BOOST_TEST(c == (20 | 7)) + c = 20 | (b + 0); + BOOST_TEST(c == (20 | 7)); + c = a ^ 7; + BOOST_TEST(c == (20 ^ 7)); + c = 20 ^ b; + BOOST_TEST(c == (20 ^ 7)); + c = (a + 0) ^ (b + 0); + BOOST_TEST(c == (20 ^ 7)); + c = 20 ^ (b + 0); + BOOST_TEST(c == (20 ^ 7)); +} + +template +void test_float_ops(const T&){} + +template +void test_float_ops(const boost::mpl::int_&) +{ + BOOST_TEST(abs(Real(2)) == 2); + BOOST_TEST(abs(Real(-2)) == 2); + BOOST_TEST(fabs(Real(2)) == 2); + BOOST_TEST(fabs(Real(-2)) == 2); + BOOST_TEST(floor(Real(5) / 2) == 2); + BOOST_TEST(ceil(Real(5) / 2) == 3); + BOOST_TEST(floor(Real(-5) / 2) == -3); + BOOST_TEST(ceil(Real(-5) / 2) == -2); + BOOST_TEST(trunc(Real(5) / 2) == 2); + BOOST_TEST(trunc(Real(-5) / 2) == -2); + // + // ldexp and frexp, these pretty much have to be implemented by each backend: + // + BOOST_TEST(ldexp(Real(2), 5) == 64); + BOOST_TEST(ldexp(Real(2), -5) == Real(2) / 32); + Real v(512); + int exp; + Real r = frexp(v, &exp); + BOOST_TEST(r == 0.5); + BOOST_TEST(exp == 10); + BOOST_TEST(v == 512); + v = 1 / v; + r = frexp(v, &exp); + BOOST_TEST(r == 0.5); + BOOST_TEST(exp == -8); + typedef typename Real::backend_type::exponent_type e_type; + BOOST_TEST(ldexp(Real(2), e_type(5)) == 64); + BOOST_TEST(ldexp(Real(2), e_type(-5)) == Real(2) / 32); + v = 512; + e_type exp2; + r = frexp(v, &exp2); + BOOST_TEST(r == 0.5); + BOOST_TEST(exp2 == 10); + BOOST_TEST(v == 512); + v = 1 / v; + r = frexp(v, &exp2); + BOOST_TEST(r == 0.5); + BOOST_TEST(exp2 == -8); + // + // pow and exp: + // + v = 3.25; + r = pow(v, 0); + BOOST_TEST(r == 1); + r = pow(v, 1); + BOOST_TEST(r == 3.25); + r = pow(v, 2); + BOOST_TEST(r == boost::math::pow<2>(3.25)); + r = pow(v, 3); + BOOST_TEST(r == boost::math::pow<3>(3.25)); + r = pow(v, 4); + BOOST_TEST(r == boost::math::pow<4>(3.25)); + r = pow(v, 5); + BOOST_TEST(r == boost::math::pow<5>(3.25)); + r = pow(v, 6); + BOOST_TEST(r == boost::math::pow<6>(3.25)); + r = pow(v, 25); + BOOST_TEST(r == boost::math::pow<25>(Real(3.25))); + // + // Things that are expected errors: + // + BOOST_CHECK_THROW(Real("3.14L"), std::runtime_error); + if(std::numeric_limits::is_specialized) + { + if(std::numeric_limits::has_infinity) + { + BOOST_CHECK(boost::math::isinf(Real(20) / 0u)); + } + else + { + BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error); + } + } +} + +template +struct lexical_cast_target_type +{ + typedef typename boost::mpl::if_< + boost::is_signed, + boost::intmax_t, + typename boost::mpl::if_< + boost::is_unsigned, + boost::uintmax_t, + T + >::type + >::type type; +}; + +template +void test_negative_mixed(boost::mpl::true_ const&) +{ + typedef typename lexical_cast_target_type::type target_type; + typedef typename boost::mpl::if_< + boost::is_convertible, + typename boost::mpl::if_c::value && (sizeof(Num) < sizeof(int)), int, Num>::type, + Real + >::type cast_type; + typedef typename boost::mpl::if_< + boost::is_convertible, + Num, + Real + >::type simple_cast_type; + std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl; + static const int left_shift = std::numeric_limits::digits - 1; + Num n1 = -static_cast(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10)); + Num n2 = -1; + Num n3 = 0; + Num n4 = -20; + Num n5 = -8; + + test_comparisons(n1, n2, boost::is_convertible()); + test_comparisons(n1, n3, boost::is_convertible()); + test_comparisons(n3, n1, boost::is_convertible()); + test_comparisons(n2, n1, boost::is_convertible()); + test_comparisons(n1, n1, boost::is_convertible()); + test_comparisons(n3, n3, boost::is_convertible()); + + // Default construct: + BOOST_TEST(Real(n1) == static_cast(n1)); + BOOST_TEST(Real(n2) == static_cast(n2)); + BOOST_TEST(Real(n3) == static_cast(n3)); + BOOST_TEST(Real(n4) == static_cast(n4)); + BOOST_TEST(static_cast(n1) == Real(n1)); + BOOST_TEST(static_cast(n2) == Real(n2)); + BOOST_TEST(static_cast(n3) == Real(n3)); + BOOST_TEST(static_cast(n4) == Real(n4)); + BOOST_TEST(Real(n1).template convert_to() == n1); + BOOST_TEST(Real(n2).template convert_to() == n2); + BOOST_TEST(Real(n3).template convert_to() == n3); + BOOST_TEST(Real(n4).template convert_to() == n4); +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + BOOST_TEST(static_cast(Real(n1)) == n1); + BOOST_TEST(static_cast(Real(n2)) == n2); + BOOST_TEST(static_cast(Real(n3)) == n3); + BOOST_TEST(static_cast(Real(n4)) == n4); +#endif +#if defined(TEST_MPFR) || defined(TEST_MPFR_50) + Num tol = 10 * std::numeric_limits::epsilon(); +#else + Num tol = 0; +#endif + std::ios_base::fmtflags f = boost::is_floating_point::value ? std::ios_base::scientific : std::ios_base::fmtflags(0); + if(std::numeric_limits::digits <= std::numeric_limits::digits) + { + BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + } + BOOST_TEST_CLOSE(n2, boost::lexical_cast(Real(n2).str(0, f)), 0); + BOOST_TEST_CLOSE(n3, boost::lexical_cast(Real(n3).str(0, f)), 0); + BOOST_TEST_CLOSE(n4, boost::lexical_cast(Real(n4).str(0, f)), 0); + // Assignment: + Real r(0); + BOOST_TEST(r != static_cast(n1)); + r = static_cast(n1); + BOOST_TEST(r == static_cast(n1)); + r = static_cast(n2); + BOOST_TEST(r == static_cast(n2)); + r = static_cast(n3); + BOOST_TEST(r == static_cast(n3)); + r = static_cast(n4); + BOOST_TEST(r == static_cast(n4)); + // Addition: + r = static_cast(n2); + BOOST_TEST(r + static_cast(n4) == static_cast(n2 + n4)); + BOOST_TEST(Real(r + static_cast(n4)) == static_cast(n2 + n4)); + r += static_cast(n4); + BOOST_TEST(r == static_cast(n2 + n4)); + // subtraction: + r = static_cast(n4); + BOOST_TEST(r - static_cast(n5) == static_cast(n4 - n5)); + BOOST_TEST(Real(r - static_cast(n5)) == static_cast(n4 - n5)); + r -= static_cast(n5); + BOOST_TEST(r == static_cast(n4 - n5)); + // Multiplication: + r = static_cast(n2); + BOOST_TEST(r * static_cast(n4) == static_cast(n2 * n4)); + BOOST_TEST(Real(r * static_cast(n4)) == static_cast(n2 * n4)); + r *= static_cast(n4); + BOOST_TEST(r == static_cast(n2 * n4)); + // Division: + r = static_cast(n1); + BOOST_TEST(r / static_cast(n5) == static_cast(n1 / n5)); + BOOST_TEST(Real(r / static_cast(n5)) == static_cast(n1 / n5)); + r /= static_cast(n5); + BOOST_TEST(r == static_cast(n1 / n5)); + // + // Extra cases for full coverage: + // + r = Real(n4) + static_cast(n5); + BOOST_TEST(r == static_cast(n4 + n5)); + r = static_cast(n4) + Real(n5); + BOOST_TEST(r == static_cast(n4 + n5)); + r = Real(n4) - static_cast(n5); + BOOST_TEST(r == static_cast(n4 - n5)); + r = static_cast(n4) - Real(n5); + BOOST_TEST(r == static_cast(n4 - n5)); + r = static_cast(n4) * Real(n5); + BOOST_TEST(r == static_cast(n4 * n5)); + r = static_cast(4 * n4) / Real(4); + BOOST_TEST(r == static_cast(n4)); + + Real a, b, c; + a = 20; + b = 30; + c = -a + b; + BOOST_TEST(c == 10); + c = b + -a; + BOOST_TEST(c == 10); + n4 = 30; + c = -a + static_cast(n4); + BOOST_TEST(c == 10); + c = static_cast(n4) + -a; + BOOST_TEST(c == 10); + c = -a + -b; + BOOST_TEST(c == -50); + n4 = 4; + c = -(a + b) + static_cast(n4); + BOOST_TEST(c == -50+4); + n4 = 50; + c = (a + b) - static_cast(n4); + BOOST_TEST(c == 0); + c = (a + b) - static_cast(n4); + BOOST_TEST(c == 0); + c = a - -(b + static_cast(n4)); + BOOST_TEST(c == 20 - -(30 + 50)); + c = -(b + static_cast(n4)) - a; + BOOST_TEST(c == -(30 + 50) - 20); + c = a - -b; + BOOST_TEST(c == 50); + c = -a - b; + BOOST_TEST(c == -50); + c = -a - static_cast(n4); + BOOST_TEST(c == -20 - 50); + c = static_cast(n4) - -a; + BOOST_TEST(c == 50 + 20); + c = -(a + b) - Real(n4); + BOOST_TEST(c == -(20 + 30) - 50); + c = static_cast(n4) - (a + b); + BOOST_TEST(c == 0); + c = (a + b) * static_cast(n4); + BOOST_TEST(c == 50 * 50); + c = static_cast(n4) * (a + b); + BOOST_TEST(c == 50 * 50); + c = a * -(b + static_cast(n4)); + BOOST_TEST(c == 20 * -(30 + 50)); + c = -(b + static_cast(n4)) * a; + BOOST_TEST(c == 20 * -(30 + 50)); + c = a * -b; + BOOST_TEST(c == 20 * -30); + c = -a * b; + BOOST_TEST(c == 20 * -30); + c = -a * static_cast(n4); + BOOST_TEST(c == -20 * 50); + c = static_cast(n4) * -a; + BOOST_TEST(c == -20 * 50); + c = -(a + b) + a; + BOOST_TEST(-50 + 20); + c = static_cast(n4) - (a + b); + BOOST_TEST(c == 0); + Real d = 10; + c = (a + b) / d; + BOOST_TEST(c == 5); + c = (a + b) / (d + 0); + BOOST_TEST(c == 5); + c = (a + b) / static_cast(n4); + BOOST_TEST(c == 1); + c = static_cast(n4) / (a + b); + BOOST_TEST(c == 1); + d = 50; + c = d / -(a + b); + BOOST_TEST(c == -1); + c = -(a + b) / d; + BOOST_TEST(c == -1); + d = 2; + c = a / -d; + BOOST_TEST(c == 20 / -2); + c = -a / d; + BOOST_TEST(c == 20 / -2); + d = 50; + c = -d / static_cast(n4); + BOOST_TEST(c == -1); + c = static_cast(n4) / -d; + BOOST_TEST(c == -1); + c = static_cast(n4) + a; + BOOST_TEST(c == 70); + c = static_cast(n4) - a; + BOOST_TEST(c == 30); + c = static_cast(n4) * a; + BOOST_TEST(c == 50 * 20); + + n1 = -2; + n2 = -3; + n3 = -4; + a = static_cast(n1); + b = static_cast(n2); + c = static_cast(n3); + d = a + b * c; + BOOST_TEST(d == -2 + -3 * -4); + d = static_cast(n1) + b * c; + BOOST_TEST(d == -2 + -3 * -4); + d = a + static_cast(n2) * c; + BOOST_TEST(d == -2 + -3 * -4); + d = a + b * static_cast(n3); + BOOST_TEST(d == -2 + -3 * -4); + d = static_cast(n1) + static_cast(n2) * c; + BOOST_TEST(d == -2 + -3 * -4); + d = static_cast(n1) + b * static_cast(n3); + BOOST_TEST(d == -2 + -3 * -4); + a += static_cast(n2) * c; + BOOST_TEST(a == -2 + -3 * -4); + a = static_cast(n1); + a += b * static_cast(n3); + BOOST_TEST(a == -2 + -3 * -4); + a = static_cast(n1); + + d = b * c + a; + BOOST_TEST(d == -2 + -3 * -4); + d = b * c + static_cast(n1); + BOOST_TEST(d == -2 + -3 * -4); + d = static_cast(n2) * c + a; + BOOST_TEST(d == -2 + -3 * -4); + d = b * static_cast(n3) + a; + BOOST_TEST(d == -2 + -3 * -4); + d = static_cast(n2) * c + static_cast(n1); + BOOST_TEST(d == -2 + -3 * -4); + d = b * static_cast(n3) + static_cast(n1); + BOOST_TEST(d == -2 + -3 * -4); + + a = -20; + d = a - b * c; + BOOST_TEST(d == -20 - -3 * -4); + n1 = -20; + d = static_cast(n1) - b * c; + BOOST_TEST(d == -20 - -3 * -4); + d = a - static_cast(n2) * c; + BOOST_TEST(d == -20 - -3 * -4); + d = a - b * static_cast(n3); + BOOST_TEST(d == -20 - -3 * -4); + d = static_cast(n1) - static_cast(n2) * c; + BOOST_TEST(d == -20 - -3 * -4); + d = static_cast(n1) - b * static_cast(n3); + BOOST_TEST(d == -20 - -3 * -4); + a -= static_cast(n2) * c; + BOOST_TEST(a == -20 - -3 * -4); + a = static_cast(n1); + a -= b * static_cast(n3); + BOOST_TEST(a == -20 - -3 * -4); + + a = -2; + d = b * c - a; + BOOST_TEST(d == -3 * -4 - -2); + n1 = -2; + d = b * c - static_cast(n1); + BOOST_TEST(d == -3 * -4 - -2); + d = static_cast(n2) * c - a; + BOOST_TEST(d == -3 * -4 - -2); + d = b * static_cast(n3) - a; + BOOST_TEST(d == -3 * -4 - -2); + d = static_cast(n2) * c - static_cast(n1); + BOOST_TEST(d == -3 * -4 - -2); + d = b * static_cast(n3) - static_cast(n1); + BOOST_TEST(d == -3 * -4 - -2); +} + +template +void test_negative_mixed(boost::mpl::false_ const&) +{ +} + +template +void test_mixed(const boost::mpl::false_&) +{ +} + +template +void test_mixed(const boost::mpl::true_&) +{ + typedef typename lexical_cast_target_type::type target_type; + typedef typename boost::mpl::if_< + boost::is_convertible, + typename boost::mpl::if_c::value && (sizeof(Num) < sizeof(int)), int, Num>::type, + Real + >::type cast_type; + typedef typename boost::mpl::if_< + boost::is_convertible, + Num, + Real + >::type simple_cast_type; + + if(std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && std::numeric_limits::digits < std::numeric_limits::digits) + return; + + std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl; + static const int left_shift = std::numeric_limits::digits - 1; + Num n1 = static_cast(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10)); + Num n2 = 1; + Num n3 = 0; + Num n4 = 20; + Num n5 = 8; + + test_comparisons(n1, n2, boost::is_convertible()); + test_comparisons(n1, n3, boost::is_convertible()); + test_comparisons(n1, n1, boost::is_convertible()); + test_comparisons(n3, n1, boost::is_convertible()); + test_comparisons(n2, n1, boost::is_convertible()); + test_comparisons(n3, n3, boost::is_convertible()); + + // Default construct: + BOOST_TEST(Real(n1) == static_cast(n1)); + BOOST_TEST(Real(n2) == static_cast(n2)); + BOOST_TEST(Real(n3) == static_cast(n3)); + BOOST_TEST(Real(n4) == static_cast(n4)); + BOOST_TEST(Real(n1).template convert_to() == n1); + BOOST_TEST(Real(n2).template convert_to() == n2); + BOOST_TEST(Real(n3).template convert_to() == n3); + BOOST_TEST(Real(n4).template convert_to() == n4); +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + BOOST_TEST(static_cast(Real(n1)) == n1); + BOOST_TEST(static_cast(Real(n2)) == n2); + BOOST_TEST(static_cast(Real(n3)) == n3); + BOOST_TEST(static_cast(Real(n4)) == n4); +#endif + BOOST_TEST(static_cast(n1) == Real(n1)); + BOOST_TEST(static_cast(n2) == Real(n2)); + BOOST_TEST(static_cast(n3) == Real(n3)); + BOOST_TEST(static_cast(n4) == Real(n4)); +#if defined(TEST_MPFR) || defined(TEST_MPFR_50) + Num tol = 10 * std::numeric_limits::epsilon(); +#else + Num tol = 0; +#endif + std::ios_base::fmtflags f = boost::is_floating_point::value ? std::ios_base::scientific : std::ios_base::fmtflags(0); + if(std::numeric_limits::digits <= std::numeric_limits::digits) + { + BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + } + BOOST_TEST_CLOSE(n2, boost::lexical_cast(Real(n2).str(0, f)), 0); + BOOST_TEST_CLOSE(n3, boost::lexical_cast(Real(n3).str(0, f)), 0); + BOOST_TEST_CLOSE(n4, boost::lexical_cast(Real(n4).str(0, f)), 0); + // Assignment: + Real r(0); + BOOST_TEST(r != static_cast(n1)); + r = static_cast(n1); + BOOST_TEST(r == static_cast(n1)); + r = static_cast(n2); + BOOST_TEST(r == static_cast(n2)); + r = static_cast(n3); + BOOST_TEST(r == static_cast(n3)); + r = static_cast(n4); + BOOST_TEST(r == static_cast(n4)); + // Addition: + r = static_cast(n2); + BOOST_TEST(r + static_cast(n4) == static_cast(n2 + n4)); + BOOST_TEST(Real(r + static_cast(n4)) == static_cast(n2 + n4)); + r += static_cast(n4); + BOOST_TEST(r == static_cast(n2 + n4)); + // subtraction: + r = static_cast(n4); + BOOST_TEST(r - static_cast(n5) == static_cast(n4 - n5)); + BOOST_TEST(Real(r - static_cast(n5)) == static_cast(n4 - n5)); + r -= static_cast(n5); + BOOST_TEST(r == static_cast(n4 - n5)); + // Multiplication: + r = static_cast(n2); + BOOST_TEST(r * static_cast(n4) == static_cast(n2 * n4)); + BOOST_TEST(Real(r * static_cast(n4)) == static_cast(n2 * n4)); + r *= static_cast(n4); + BOOST_TEST(r == static_cast(n2 * n4)); + // Division: + r = static_cast(n1); + BOOST_TEST(r / static_cast(n5) == static_cast(n1 / n5)); + BOOST_TEST(Real(r / static_cast(n5)) == static_cast(n1 / n5)); + r /= static_cast(n5); + BOOST_TEST(r == static_cast(n1 / n5)); + // + // special cases for full coverage: + // + r = static_cast(n5) + Real(n4); + BOOST_TEST(r == static_cast(n4 + n5)); + r = static_cast(n4) - Real(n5); + BOOST_TEST(r == static_cast(n4 - n5)); + r = static_cast(n4) * Real(n5); + BOOST_TEST(r == static_cast(n4 * n5)); + r = static_cast(4 * n4) / Real(4); + BOOST_TEST(r == static_cast(n4)); + + typedef boost::mpl::bool_< + (!std::numeric_limits::is_specialized || std::numeric_limits::is_signed) + && (!std::numeric_limits::is_specialized || std::numeric_limits::is_signed)> signed_tag; + + test_negative_mixed(signed_tag()); + + n1 = 2; + n2 = 3; + n3 = 4; + Real a(n1), b(n2), c(n3), d; + d = a + b * c; + BOOST_TEST(d == 2 + 3 * 4); + d = static_cast(n1) + b * c; + BOOST_TEST(d == 2 + 3 * 4); + d = a + static_cast(n2) * c; + BOOST_TEST(d == 2 + 3 * 4); + d = a + b * static_cast(n3); + BOOST_TEST(d == 2 + 3 * 4); + d = static_cast(n1) + static_cast(n2) * c; + BOOST_TEST(d == 2 + 3 * 4); + d = static_cast(n1) + b * static_cast(n3); + BOOST_TEST(d == 2 + 3 * 4); + a += static_cast(n2) * c; + BOOST_TEST(a == 2 + 3 * 4); + a = static_cast(n1); + a += b * static_cast(n3); + BOOST_TEST(a == 2 + 3 * 4); + a = static_cast(n1); + + d = b * c + a; + BOOST_TEST(d == 2 + 3 * 4); + d = b * c + static_cast(n1); + BOOST_TEST(d == 2 + 3 * 4); + d = static_cast(n2) * c + a; + BOOST_TEST(d == 2 + 3 * 4); + d = b * static_cast(n3) + a; + BOOST_TEST(d == 2 + 3 * 4); + d = static_cast(n2) * c + static_cast(n1); + BOOST_TEST(d == 2 + 3 * 4); + d = b * static_cast(n3) + static_cast(n1); + BOOST_TEST(d == 2 + 3 * 4); + + a = 20; + d = a - b * c; + BOOST_TEST(d == 20 - 3 * 4); + n1 = 20; + d = static_cast(n1) - b * c; + BOOST_TEST(d == 20 - 3 * 4); + d = a - static_cast(n2) * c; + BOOST_TEST(d == 20 - 3 * 4); + d = a - b * static_cast(n3); + BOOST_TEST(d == 20 - 3 * 4); + d = static_cast(n1) - static_cast(n2) * c; + BOOST_TEST(d == 20 - 3 * 4); + d = static_cast(n1) - b * static_cast(n3); + BOOST_TEST(d == 20 - 3 * 4); + a -= static_cast(n2) * c; + BOOST_TEST(a == 20 - 3 * 4); + a = static_cast(n1); + a -= b * static_cast(n3); + BOOST_TEST(a == 20 - 3 * 4); + + a = 2; + d = b * c - a; + BOOST_TEST(d == 3 * 4 - 2); + n1 = 2; + d = b * c - static_cast(n1); + BOOST_TEST(d == 3 * 4 - 2); + d = static_cast(n2) * c - a; + BOOST_TEST(d == 3 * 4 - 2); + d = b * static_cast(n3) - a; + BOOST_TEST(d == 3 * 4 - a); + d = static_cast(n2) * c - static_cast(n1); + BOOST_TEST(d == 3 * 4 - 2); + d = b * static_cast(n3) - static_cast(n1); + BOOST_TEST(d == 3 * 4 - 2); +} + +template +void test_members(Real) +{ + // + // Test sign and zero functions: + // + Real a = 20; + Real b = 30; + BOOST_TEST(a.sign() > 0); + BOOST_TEST(!a.is_zero()); + if(std::numeric_limits::is_signed) + { + a = -20; + BOOST_TEST(a.sign() < 0); + BOOST_TEST(!a.is_zero()); + } + a = 0; + BOOST_TEST(a.sign() == 0); + BOOST_TEST(a.is_zero()); + + a = 20; + b = 30; + a.swap(b); + BOOST_TEST(a == 30); + BOOST_TEST(b == 20); +} + +template +void test_members(boost::rational) +{ +} + +template +void test_signed_ops(const boost::mpl::true_&) +{ + Real a(8); + Real b(64); + Real c(500); + Real d(1024); + Real ac; + BOOST_TEST(-a == -8); + ac = a; + ac = ac - b; + BOOST_TEST(ac == 8 - 64); + ac = a; + ac -= a + b; + BOOST_TEST(ac == -64); + ac = a; + ac -= b - a; + BOOST_TEST(ac == 16 - 64); + ac = -a; + BOOST_TEST(ac == -8); + ac = a; + ac -= -a; + BOOST_TEST(ac == 16); + ac = a; + ac += -a; + BOOST_TEST(ac == 0); + ac = b; + ac /= -a; + BOOST_TEST(ac == -8); + ac = a; + ac *= -a; + BOOST_TEST(ac == -64); + ac = a + -b; + BOOST_TEST(ac == 8 - 64); + ac = -a + b; + BOOST_TEST(ac == -8+64); + ac = -a + -b; + BOOST_TEST(ac == -72); + ac = a + - + -b; // lots of unary operators!! + BOOST_TEST(ac == 72); + test_conditional(Real(-a), -a); +} +template +void test_signed_ops(const boost::mpl::false_&) +{ +} + +template +void test() +{ +#ifndef NO_MIXED_OPS + boost::multiprecision::is_number tag; + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); +#ifdef BOOST_HAS_LONG_LONG + test_mixed(tag); + test_mixed(tag); +#endif + test_mixed(tag); + test_mixed(tag); + test_mixed(tag); + + typedef typename related_type::type related_type; + boost::mpl::bool_::value && !boost::is_same::value> tag2; + + test_mixed(tag2); + +#endif + // + // Integer only functions: + // + test_integer_ops(typename boost::multiprecision::number_category::type()); + // + // Real number only functions: + // + test_float_ops(typename boost::multiprecision::number_category::type()); + // + // Test basic arithmetic: + // + Real a(8); + Real b(64); + Real c(500); + Real d(1024); + BOOST_TEST(a + b == 72); + a += b; + BOOST_TEST(a == 72); + BOOST_TEST(a - b == 8); + a -= b; + BOOST_TEST(a == 8); + BOOST_TEST(a * b == 8*64L); + a *= b; + BOOST_TEST(a == 8*64L); + BOOST_TEST(a / b == 8); + a /= b; + BOOST_TEST(a == 8); + Real ac(a); + BOOST_TEST(ac == a); + ac = a * c; + BOOST_TEST(ac == 8*500L); + ac = 8*500L; + ac = ac + b + c; + BOOST_TEST(ac == 8*500L+64+500); + ac = a; + ac = b + c + ac; + BOOST_TEST(ac == 8+64+500); + ac = ac - b + c; + BOOST_TEST(ac == 8+64+500-64+500); + ac = a; + ac = b + c - ac; + BOOST_TEST(ac == -8+64+500); + ac = a; + ac = ac * b; + BOOST_TEST(ac == 8*64); + ac = a; + ac *= b * ac; + BOOST_TEST(ac == 8*8*64); + ac = b; + ac = ac / a; + BOOST_TEST(ac == 64/8); + ac = b; + ac /= ac / a; + BOOST_TEST(ac == 64 / (64/8)); + ac = a; + ac = b + ac * a; + BOOST_TEST(ac == 64 * 2); + ac = a; + ac = b - ac * a; + BOOST_TEST(ac == 0); + ac = a; + ac = b * (ac + a); + BOOST_TEST(ac == 64 * (16)); + ac = a; + ac = b / (ac * 1); + BOOST_TEST(ac == 64 / 8); + ac = a; + ac = ac + b; + BOOST_TEST(ac == 8 + 64); + ac = a; + ac = a + ac; + BOOST_TEST(ac == 16); + ac = a; + ac = a - ac; + BOOST_TEST(ac == 0); + ac = a; + ac += a + b; + BOOST_TEST(ac == 80); + ac = a; + ac += b + a; + BOOST_TEST(ac == 80); + ac = +a; + BOOST_TEST(ac == 8); + ac = 8; + ac = a * ac; + BOOST_TEST(ac == 8*8); + ac = a; + ac = a; + ac += +a; + BOOST_TEST(ac == 16); + ac = a; + ac += b - a; + BOOST_TEST(ac == 8 + 64-8); + ac = a; + ac += b*c; + BOOST_TEST(ac == 8 + 64 * 500); + ac = a; + ac = a; + ac -= +a; + BOOST_TEST(ac == 0); + ac = a; + if(std::numeric_limits::is_signed || is_twos_complement_integer::value) + { + ac = a; + ac -= c - b; + BOOST_TEST(ac == 8 - (500-64)); + ac = a; + ac -= b*c; + BOOST_TEST(ac == 8 - 500*64); + } + ac = a; + ac += ac * b; + BOOST_TEST(ac == 8 + 8 * 64); + if(std::numeric_limits::is_signed || is_twos_complement_integer::value) + { + ac = a; + ac -= ac * b; + BOOST_TEST(ac == 8 - 8 * 64); + } + ac = a * 8; + ac *= +a; + BOOST_TEST(ac == 64 * 8); + ac = a; + ac *= b * c; + BOOST_TEST(ac == 8 * 64 * 500); + ac = a; + ac *= b / a; + BOOST_TEST(ac == 8 * 64 / 8); + ac = a; + ac *= b + c; + BOOST_TEST(ac == 8 * (64 + 500)); + ac = b; + ac /= +a; + BOOST_TEST(ac == 8); + ac = b; + ac /= b / a; + BOOST_TEST(ac == 64 / (64/8)); + ac = b; + ac /= a + Real(0); + BOOST_TEST(ac == 8); + // + // simple tests with immediate values, these calls can be optimised in many backends: + // + ac = a + b; + BOOST_TEST(ac == 72); + ac = a + +b; + BOOST_TEST(ac == 72); + ac = +a + b; + BOOST_TEST(ac == 72); + ac = +a + +b; + BOOST_TEST(ac == 72); + ac = a; + ac = b / ac; + BOOST_TEST(ac == b / a); + // + // Comparisons: + // + BOOST_TEST((a == b) == false); + BOOST_TEST((a != b) == true); + BOOST_TEST((a <= b) == true); + BOOST_TEST((a < b) == true); + BOOST_TEST((a >= b) == false); + BOOST_TEST((a > b) == false); + + BOOST_TEST((a+b == b) == false); + BOOST_TEST((a+b != b) == true); + BOOST_TEST((a+b >= b) == true); + BOOST_TEST((a+b > b) == true); + BOOST_TEST((a+b <= b) == false); + BOOST_TEST((a+b < b) == false); + + BOOST_TEST((a == b+a) == false); + BOOST_TEST((a != b+a) == true); + BOOST_TEST((a <= b+a) == true); + BOOST_TEST((a < b+a) == true); + BOOST_TEST((a >= b+a) == false); + BOOST_TEST((a > b+a) == false); + + BOOST_TEST((a+b == b+a) == true); + BOOST_TEST((a+b != b+a) == false); + BOOST_TEST((a+b <= b+a) == true); + BOOST_TEST((a+b < b+a) == false); + BOOST_TEST((a+b >= b+a) == true); + BOOST_TEST((a+b > b+a) == false); + + BOOST_TEST((8 == b+a) == false); + BOOST_TEST((8 != b+a) == true); + BOOST_TEST((8 <= b+a) == true); + BOOST_TEST((8 < b+a) == true); + BOOST_TEST((8 >= b+a) == false); + BOOST_TEST((8 > b+a) == false); + BOOST_TEST((800 == b+a) == false); + BOOST_TEST((800 != b+a) == true); + BOOST_TEST((800 >= b+a) == true); + BOOST_TEST((800 > b+a) == true); + BOOST_TEST((800 <= b+a) == false); + BOOST_TEST((800 < b+a) == false); + BOOST_TEST((72 == b+a) == true); + BOOST_TEST((72 != b+a) == false); + BOOST_TEST((72 <= b+a) == true); + BOOST_TEST((72 < b+a) == false); + BOOST_TEST((72 >= b+a) == true); + BOOST_TEST((72 > b+a) == false); + + test_members(a); + // + // Use in Boolean context: + // + a = 0; + if(a) + { + BOOST_ERROR("Unexpected non-zero result"); + } + if(!a){} + else + { + BOOST_ERROR("Unexpected zero result"); + } + b = 2; + if(!b) + { + BOOST_ERROR("Unexpected zero result"); + } + if(b){} + else + { + BOOST_ERROR("Unexpected non-zero result"); + } + if(a && b) + { + BOOST_ERROR("Unexpected zero result"); + } + if(!(a || b)) + { + BOOST_ERROR("Unexpected zero result"); + } + if(a + b){} + else + { + BOOST_ERROR("Unexpected zero result"); + } + if(b - 2) + { + BOOST_ERROR("Unexpected non-zero result"); + } + // + // Test iostreams: + // + std::stringstream ss; + a = 20; + b = 2; + ss << a; + ss >> c; + BOOST_TEST(a == c); + ss.clear(); + ss << a + b; + ss >> c; + BOOST_TEST(c == 22); + BOOST_TEST(c == a + b); + // + // More cases for complete code coverage: + // + a = 20; + b = 30; + swap(a, b); + BOOST_TEST(a == 30); + BOOST_TEST(b == 20); + a = 20; + b = 30; + std::swap(a, b); + BOOST_TEST(a == 30); + BOOST_TEST(b == 20); + a = 20; + b = 30; + a = a + b * 2; + BOOST_TEST(a == 20 + 30 * 2); + a = 100; + a = a - b * 2; + BOOST_TEST(a == 100 - 30 * 2); + a = 20; + a = a * (b + 2); + BOOST_TEST(a == 20 * (32)); + a = 20; + a = (b + 2) * a; + BOOST_TEST(a == 20 * (32)); + a = 90; + b = 2; + a = a / (b + 0); + BOOST_TEST(a == 45); + a = 20; + b = 30; + c = (a * b) + 22; + BOOST_TEST(c == 20 * 30 + 22); + c = 22 + (a * b); + BOOST_TEST(c == 20 * 30 + 22); + c = 10; + ac = a + b * c; + BOOST_TEST(ac == 20 + 30 * 10); + ac = b * c + a; + BOOST_TEST(ac == 20 + 30 * 10); + a = a + b * c; + BOOST_TEST(a == 20 + 30 * 10); + a = 20; + b = a + b * c; + BOOST_TEST(b == 20 + 30 * 10); + b = 30; + c = a + b * c; + BOOST_TEST(c == 20 + 30 * 10); + + // + // Test conditionals: + // + a = 20; + test_conditional(a, +a); + test_conditional(a, (a + 0)); + + test_signed_ops(boost::mpl::bool_::is_signed>()); +} + + +int main() +{ +#ifdef TEST_ARITHMETIC_BACKEND + test > >(); + test > >(); + test > >(); +#endif +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); +#endif +#ifdef TEST_MPF + boost::multiprecision::mpf_float::default_precision(1000); + BOOST_TEST(boost::multiprecision::mpf_float::default_precision() == 1000); + test(); +#endif +#ifdef TEST_MPZ + test(); + test > >(); +#endif +#ifdef TEST_MPQ + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test, boost::multiprecision::et_off> >(); + test >, boost::multiprecision::et_on> >(); +#endif +#ifdef TEST_MPFR + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_TOMMATH + test(); + test > >(); +#endif +#ifdef TEST_TOMMATH_BOOST_RATIONAL + test >(); +#endif +#ifdef TEST_MPZ_BOOST_RATIONAL + test >(); +#endif +#ifdef TEST_CPP_INT_1 + test(); + test(); + test(); +#endif +#ifdef TEST_CPP_INT_1A + test(); + test(); + test(); +#endif +#ifdef TEST_CPP_INT_2 + test(); + test, boost::multiprecision::et_off> >(); + test > >(); +#endif +#ifdef TEST_CPP_INT_2A + test(); + test, boost::multiprecision::et_off> >(); + test > >(); +#endif +#ifdef TEST_CPP_INT_3 + // Again with "trivial" backends: + test > >(); + test > >(); + test > >(); +#endif +#ifdef TEST_CPP_INT_3A + // Again with "trivial" checked backends: + test > >(); + test > >(); + test > >(); +#endif +#ifdef TEST_CPP_INT_BR + test >(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_asin.cpp b/test/test_asin.cpp new file mode 100644 index 00000000..6f4acb22 --- /dev/null +++ b/test/test_asin.cpp @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + // + // Test with some exact binary values as input - this tests our code + // rather than the test data: + // + static const boost::array, 6> exact_data = + {{ + {{ 0.5, static_cast("0.523598775598298873077107230546583814032861566562517636829157432051302734381034833104672470890352844663691347752213717775") }}, + {{ 0.25, static_cast("0.252680255142078653485657436993710972252193733096838193633923778740575060481021222411748742228014601605092602909414066566") }}, + {{0.75, static_cast("0.848062078981481008052944338998418080073366213263112642860718163570200821228474234349189801731957230300995227265307531834") }}, + {{std::ldexp(1.0, -20), static_cast("9.53674316406394560289664793089102218648031077292419572854816420395098616062014311172490017625353237219958438022056661501e-7") }}, + {{ 1 - std::ldexp(1.0, -20), static_cast("1.56941525875313420204921285316218397515809899320201864334535204504240776023375739189119474528488143494473216475057072728") }}, + {{ 1, static_cast("1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404325664115332354692230477529111586267970406424055872514205135096926055277982231147447746519098221440548783296672306423782411689339158263560095457282428346173017430522716332410669680363012457064") }}, + }}; + unsigned max_err = 0; + for(unsigned k = 0; k < exact_data.size(); k++) + { + T val = asin(exact_data[k][0]); + T e = relative_error(val, exact_data[k][1]); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = asin(-exact_data[k][0]); + e = relative_error(val, T(-exact_data[k][1])); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); + BOOST_TEST(asin(T(0)) == 0); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_atan.cpp b/test/test_atan.cpp new file mode 100644 index 00000000..07ed5b10 --- /dev/null +++ b/test/test_atan.cpp @@ -0,0 +1,269 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#ifdef BOOST_MSVC +#pragma warning(disable:4127) +#endif + +template +T atan2_def(T y, T x) +{ + T t; + t.backend() = boost::multiprecision::default_ops::get_constant_pi(); + T t2; + if(x) + t2 = atan(y / x); + else + t2 = y.sign() * t / 2; + return t2 + (t / 2) * (1 - x.sign()) * T(y.sign() + 0.5).sign(); +} + +template +struct is_mpfr_type : public boost::mpl::false_ {}; + +#ifdef TEST_MPFR_50 +template +struct is_mpfr_type > > : public boost::mpl::true_{}; +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-101", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666668666666666666667e-97", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666667e-93", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666667e-89", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666668666666666666666666666666666666666666666666666666666666666666667e-85", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666666666666666666666666666666666666666666666666666667e-81", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-77", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666668666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-73", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-69", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238e-65", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666668666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238e-61", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238e-57", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238095238095238095238095238e-53", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666668666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238095238095238095238095238095238096349206349206349e-49", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238095238095238095238095238206349206349206349206349206349206349206349206349e-45", + "9.999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238095238095238095249206349206349206349206349206349206349206349206349206349206349206349206349206349e-41", + "9.99999999999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666666666666666666666523809523809523809523809523809523809523809523809523809523809523809523809634920634920634920634920634920634920634920634920634920634920634920634920544011544011544011544011544011544011544e-37", + "9.999999999999999999999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666666666666666666686666666666666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095238095238206349206349206349206349206349206349206349206349206349206349206340115440115440115440115440115440115440115440115440115440115440116209346209346209e-33", + "9.999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666666666665238095238095238095238095238095238095238095238095238095249206349206349206349206349206349206349206349206349206349115440115440115440115440115440115440115440115440115440116209346209346209346209346209346209346209346209346209346202679543e-29", + "9.99999999999999999999999999999999999999999999999666666666666666666666666666666666666666666666666866666666666666666666666666666666666666666666666523809523809523809523809523809523809523809523809634920634920634920634920634920634920634920634920544011544011544011544011544011544011544011544011620934620934620934620934620934620934620934620934554267954267954267954267954267954267954267954268013091483679719e-25", + "9.999999999999999999999999999999999999999666666666666666666666666666666666666666686666666666666666666666666666666666666665238095238095238095238095238095238095238206349206349206349206349206349206349206340115440115440115440115440115440115440116209346209346209346209346209346209346209279542679542679542679542679542679542679548561895620719150130914836797189738366208428128459088211410192834341441152586663e-21", + "9.999999999999999999999999999999966666666666666666666666666666666866666666666666666666666666666665238095238095238095238095238095249206349206349206349206349206349115440115440115440115440115440116209346209346209346209346209346202679542679542679542679542679542738366208954444248561895620719149604599047323505527839893164970569113274066834438351466215243304983108499463325146458811824271509689681318218133e-17", + "9.999999999999999999999996666666666666666666666668666666666666666666666665238095238095238095238096349206349206349206349205440115440115440115440116209346209346209346209345542679542679542679542680130914836797189738366208428128459088211410192834817631628777139613052925311641589740930163598087002528653948764327011735444703713649735994600714288656350334489593033695272837185114343249547095046272603174268e-13", + "9.999999999999999666666666666666686666666666666665238095238095238206349206349206340115440115440116209346209346209279542679542679548561895620719149604599047323505575458940784018179051162265592202726621494746410579611835097095566286199717626418813764642659343446728207455753397291482030056516178836684094391777365260695851470017381944166954115569576329193296454393446430574957840819236721213626802085619e-9", + "0.00009999999966666666866666665238095249206349115440116209346202679542738366208428128463850116128619335776637836253560167434464812879197215298894881707269927081030999737549925482008672363799937606915962379247584324159094536421375755997513179578610677454920512897850953612762990732913046921088456079984429888220262137400213929962691532176198436788640624698990926490105259050461938357510947570244880435664081", + "0.78539816339744830961566084581987572104929234984377645524373614807695410157155224965700870633552926699553702162832057666177346115238764555793133985203212027936257102567548463027638991115573723873259549110720274391648336153211891205844669579131780047728641214173086508715261358166205334840181506228531843114675165157889704372038023024070731352292884109197314759000283263263720511663034603673798537790236", + "1.5706963267952299525626550249873704896065212085331517483940102693584808194810202180293789115097723406333076648941055516492022741759833189628737308869915412879148320539754700057326930986734751013960313584219296445913757777000240665569182597868494941800236191544832206381775972559949762275927455637707925634113006817837919481411335451596526426779712759369563859151046126747697908496855825977735219514481", + "1.5707963167948966192313220249730847754318980330208862438222342009158129649367552929648110725556184185509578339104318071142673796252326115673007840833450909541260947278453938016119958041324233151995987794877839930865561434524027270213271053829179745357590596408023867275770197075707094053216000680544580256094089113804288267449089904640326828789035666143699659867092108718279796583028512542392495421779", + "1.5707963267938966192313216916397514424319180330208862438208054294872415364764378326474936031472490101815502336217205184029120016698547471043186681600526965471042074304163483259318452680435202095109230279463923963492870040904012032740805456738144599352893425202988524603439218707929425378295371082108281620406379082813613862672159901100496534463976107550806601465567059619048829495421806391510160463001", + "1.5707963267948965192313216916397514420985846996878862438208056294872415364764378306473507460043918673244073765899887723711659699238229101634817272120007484952330785592874771970616254211570733230640365810600043257395046296021443620234312981206088055277773974880349347475097997796620171523611445056144296707974573126845590321623615288317089359131170138395627805178532322154433252386274406088878525130896", + "1.5707963267948966192213216916397514420985846996875529104874726294872415364764378326473507460043918673044073765899744866568802556381086244491974416088261453206299039561128740224575416159622681282588417758651991386266175167241223840014532761425201608391327088433455208280958809539778973505942839152244275827508237604782514078980809178018719474972957865632271450490908284680846718670522639450168825443945", + "1.5707963267948966192313206916397514420985846996875529104874722961539082034764378326473507460043918673244073765899744866566802556381086244491960130373975738920584753846844454510289702985019506679413814584048816783091570881436029034819727566620006803196521893628268096302936831517800951527920861130266253182819592915368594665061395258604800061112367475630116742454513973110064559653064241192080164878504", + "1.5707963267948966192313216915397514420985846996875529104874722961539082031431044993143507460043918673244073765899744866568802556381086244491940130373975738920584753846843025938861131556448078107985386012620245354520143421118568717359410106302546485736203322199696666822417350998320432047401380610785733702300121487566396862863593060802602258914565277827918940256045031718123167711672299800138772937113", + "1.5707963267948966192313216916397414420985846996875529104874722961539082031431044993140174126710588673244073765899744866568802556381086244491960130373975738920584553846843025938861131556448078107985243155477388211663000563975725860216552963445403628593347290453664920790671319252288686015654237753642876559442969539514448810915541112750654206966513329776061797398902251498342947931452519580358553156893", + "1.5707963267948966192313216916397514410985846996875529104874722961539082031431044993140174126710585339910740435899744866568802556381086244491960130373975738920584753846843025938861129556448078107985243155477388211663000563975711574502267249159689342879063004739379206504957033538002971729941063150468273384839794936339845636311255398464939921252227615490256602593707446303537753126257714385553358352607", + "1.5707963267948966192313216916397514420984846996875529104874722961539082031431044993140174126710585339910740432566411533238802556381086244491960130373975738920584753846843025938861131556448078107985243135477388211663000563975711574502267249159689342879061576167950635076385604966574543158512491721896844813411223507768417064883795081004622460934767298029939142275136017732109181697686285814124786923127", + "1.5707963267948966192313216916397514420985846896875529104874722961539082031431044993140174126710585339910740432566411533235469223047756244491960130373975738920584753846843025938861131556448078107985243155477388211663000563775711574502267249159689342879061576167950635076385604966574400301369634579039701956268380650625559922026652223861765318077624440887081999419104271700363149951654539782378755175984", + "1.5707963267948966192313216916397514420985846996865529104874722961539082031431044993140174126710585339910740432566411533235469223047752911158626800373975738920584753846843025938861131556448078107985243155477388211663000563975711574502267249157689342879061576167950635076385604966574400301369634579039701956268366364911274207740937938147481032363338726601367713704818557414648864237368825496664469462809", + "1.5707963267948966192313216916397514420985846996875528104874722961539082031431044993140174126710585339910740432566411533235469223047752911158626797040642405590584753846843025938861131556448078107985243155477388211663000563975711574502267249159689342879061576167930635076385604966574400301369634579039701956268366364911274207740937938147479603791910155172796285133390128843220292808797396925235898034238", + "1.5707963267948966192313216916397514420985846996875529104774722961539082031431044993140174126710585339910740432566411533235469223047752911158626797040642405587251420513513025938861131556448078107985243155477388211663000563975711574502267249159689342879061576167950635076385604966574200301369634579039701956268366364911274207740937938147479603791910155172796285133389985986077435665940254068093055177095", + "1.570796326794896619231321691639751442098584699687552910487471296153908203143104499314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552780155644807810798524315547738821166300056397571157450226724915968934287906157616795063507638560496657440030136963457903969995626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296053908203143104499314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477798524315547738821166300056397571157450226724915968934287906157616795063507638560496657440030136963457903970195626836636491127418774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153898203143104499314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214738821166300056397571157450226724915968934287906157616795063507638560496657440030136963457903970195626836636491127420774093793814747960359191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908202143104499314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832967056397571157450226724915968934287906157616795063507638560496657440030136963457903970195626836636491127420774093793814747960379191015517279628513138998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143004499314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824450226724915968934287906157616795063507638560496657440030136963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566592025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104489314017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582968934287906157616795063507638560496657440030136963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499313017412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582635600954573157616795063507638560496657440030136963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017312671058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582635600954572824283461730507638560496657440030136963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412661058533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582635600954572824283461730174305227163657440030136963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671057533991074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582635600954572824283461730174305227163324106696803963457903970195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058533891074043256641153323546922304775291115862679704064240558725142051350969260552779822311474477465190982214405487832966723064237824116893391582635600954572824283461730174305227163324106696803630124570637195626836636491127420774093793814747960379191015517279628513338998598607743566594025406809304089138", + }}; + + T arg = static_cast("1e-100"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = atan(arg); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = atan(-arg); + e = relative_error(val, T(-T(data[k]))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + arg *= 10000; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 10); + BOOST_TEST(atan(T(0)) == 0); + + // + // And again, but test all the phases of atan2: + // + arg = static_cast("1e-100"); + unsigned err; + for(unsigned k = 0; k < data.size(); k++) + { + T val = atan2(arg, 1); + T e = relative_error(val, atan2_def(arg, T(1))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = atan2(-arg, 1); + e = relative_error(val, atan2_def(T(-arg), T(1))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = atan2(arg, -1); + e = relative_error(val, atan2_def(arg, T(-1))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = atan2(-arg, -1); + e = relative_error(val, atan2_def(T(-arg), T(-1))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + arg *= 10000; + } + // + // special cases: + // + err = relative_error(T(atan2(T(0), T(1))), atan2_def(T(0), T(1))).template convert_to(); + if(err > max_err) + max_err = err; + err = relative_error(T(atan2(T(0), T(-1))), atan2_def(T(0), T(-1))).template convert_to(); + if(err > max_err) + max_err = err; + + T pi; + pi.backend() = boost::multiprecision::default_ops::get_constant_pi(); + + err = relative_error(T(atan2(T(1), T(0))), T(pi / 2)).template convert_to(); + if(err > max_err) + max_err = err; + + err = relative_error(T(atan2(T(-1), T(0))), T(pi / -2)).template convert_to(); + if(err > max_err) + max_err = err; + + T mv = (std::numeric_limits::max)(); + err = relative_error(T(atan2(mv, T(1))), T(pi / 2)).template convert_to(); + if(err > max_err) + max_err = err; + err = relative_error(T(atan2(-mv, T(1))), T(pi / -2)).template convert_to(); + if(err > max_err) + max_err = err; + + if(std::numeric_limits::has_infinity) + { + mv = (std::numeric_limits::infinity)(); + err = relative_error(T(atan2(mv, T(1))), T(pi / 2)).template convert_to(); + if(err > max_err) + max_err = err; + err = relative_error(T(atan2(-mv, T(1))), T(pi / -2)).template convert_to(); + if(err > max_err) + max_err = err; + } + + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 2000); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_checked_cpp_int.cpp b/test/test_checked_cpp_int.cpp new file mode 100644 index 00000000..847760d2 --- /dev/null +++ b/test/test_checked_cpp_int.cpp @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include "test.hpp" + +template +void test() +{ + using namespace boost::multiprecision; + typedef Number test_type; + + if(std::numeric_limits::is_bounded) + { + test_type val = (std::numeric_limits::max)(); + BOOST_CHECK_THROW(++val, std::overflow_error); + val = (std::numeric_limits::max)(); + BOOST_CHECK_THROW(test_type(1 + val), std::overflow_error); + BOOST_CHECK_THROW(test_type(val + 1), std::overflow_error); + BOOST_CHECK_THROW(test_type(2 * val), std::overflow_error); + val /= 2; + val += 1; + BOOST_CHECK_THROW(test_type(2 * val), std::overflow_error); + + if(std::numeric_limits::is_signed) + { + val = (std::numeric_limits::min)(); + BOOST_CHECK_THROW(--val, std::overflow_error); + val = (std::numeric_limits::min)(); + BOOST_CHECK_THROW(test_type(val - 1), std::overflow_error); + BOOST_CHECK_THROW(test_type(2 * val), std::overflow_error); + val /= 2; + val -= 1; + BOOST_CHECK_THROW(test_type(2 * val), std::overflow_error); + } + else + { + val = (std::numeric_limits::min)(); + BOOST_CHECK_THROW(--val, std::range_error); + val = (std::numeric_limits::min)(); + BOOST_CHECK_THROW(test_type(val - 1), std::range_error); + } + } + + if(std::numeric_limits::is_signed) + { + test_type a = -1; + test_type b = 1; + BOOST_CHECK_THROW(test_type(a | b), std::range_error); + BOOST_CHECK_THROW(test_type(a & b), std::range_error); + BOOST_CHECK_THROW(test_type(a ^ b), std::range_error); + } + else + { + // Constructing from a negative value is not allowed: + BOOST_CHECK_THROW(test_type(-2), std::range_error); + BOOST_CHECK_THROW(test_type("-2"), std::range_error); + } + if(std::numeric_limits::digits < std::numeric_limits::digits) + { + long long llm = (std::numeric_limits::max)(); + test_type t; + BOOST_CHECK_THROW(t = llm, std::range_error); + BOOST_CHECK_THROW(t = static_cast(llm), std::range_error); + unsigned long long ullm = (std::numeric_limits::max)(); + BOOST_CHECK_THROW(t = ullm, std::range_error); + BOOST_CHECK_THROW(t = static_cast(ullm), std::range_error); + + static const checked_uint512_t big = (std::numeric_limits::max)(); + BOOST_CHECK_THROW(t = static_cast(big), std::range_error); + } + // + // String errors: + // + BOOST_CHECK_THROW(test_type("12A"), std::runtime_error); + BOOST_CHECK_THROW(test_type("0658"), std::runtime_error); + + if(std::numeric_limits::is_signed) + { + BOOST_CHECK_THROW(test_type(-2).str(0, std::ios_base::hex), std::runtime_error); + BOOST_CHECK_THROW(test_type(-2).str(0, std::ios_base::oct), std::runtime_error); + } +} + +int main() +{ + using namespace boost::multiprecision; + + test > >(); + test(); + test(); + test > >(); + test > >(); + + // + // We also need to test type with "odd" bit counts in order to ensure full code coverage: + // + test > >(); + test > >(); + test > >(); + test > >(); + return boost::report_errors(); +} + + + diff --git a/test/test_constants.cpp b/test/test_constants.cpp new file mode 100644 index 00000000..b7f6afe9 --- /dev/null +++ b/test/test_constants.cpp @@ -0,0 +1,198 @@ +// Copyright John Maddock 2012. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_CPP_DEC_FLOAT +# define TEST_MPFR_50 + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include "test.hpp" + +static const char* ln2 = +"0.693147180559945309417232121458176568075500134360255254120680009493393621969694" +"71560586332699641868754200148102057068573368552023575813055703267075163507596193" +"07275708283714351903070386238916734711233501153644979552391204751726815749320651" +"55524734139525882950453007095326366642654104239157814952043740430385500801944170" +"64167151864471283996817178454695702627163106454615025720740248163777338963855069" +"52606683411372738737229289564935470257626520988596932019650585547647033067936544" +"32547632744951250406069438147104689946506220167720424524529612687946546193165174" +"68139267250410380254625965686914419287160829380317271436778265487756648508567407" +"76484514644399404614226031930967354025744460703080960850474866385231381816767514" +"38667476647890881437141985494231519973548803751658612753529166100071053558249879" +"41472950929311389715599820565439287170007218085761025236889213244971389320378439" +"35308877482597017155910708823683627589842589185353024363421436706118923678919237" +"23146723217205340164925687274778234453534764811494186423867767744060695626573796" +"00867076257199184734022651462837904883062033061144630073719489002743643965002580" +"93651944304119115060809487930678651588709006052034684297361938412896525565396860" +"22194122924207574321757489097706752687115817051137009158942665478595964890653058" +"46025866838294002283300538207400567705304678700184162404418833232798386349001563" +"12188956065055315127219939833203075140842609147900126516824344389357247278820548" +"62715527418772430024897945401961872339808608316648114909306675193393128904316413" +"70681397776498176974868903887789991296503619270710889264105230924783917373501229" +"84242049956893599220660220465494151061391878857442455775102068370308666194808964" +"12186807790208181588580001688115973056186676199187395200766719214592236720602539" +"59543654165531129517598994005600036651356756905124592682574394648316833262490180" +"38242408242314523061409638057007025513877026817851630690255137032340538021450190" +"15374029509942262995779647427138157363801729873940704242179972266962979939312706" +"93574724049338653087975872169964512944649188377115670167859880498183889678413493" +"83140140731664727653276359192335112333893387095132090592721854713289754707978913" +"84445466676192702885533423429899321803769154973340267546758873236778342916191810" +"43011609169526554785973289176354555674286387746398710191243175425588830120677921" +"02803412068797591430812833072303008834947057924965910058600123415617574132724659" +"43068435465211135021544341539955381856522750221424566440006276183303206472725721" +"97515290827856842132079598863896727711955221881904660395700977470651261950527893" +"22960889314056254334425523920620303439417773579455921259019925591148440242390125" +"54259003129537051922061506434583787873002035414421785758013236451660709914383145" +"00498589668857722214865288216941812704886075897220321666312837832915676307498729" +"85746389282693735098407780493950049339987626475507031622161390348452994249172483" +"73406136622638349368111684167056925214751383930638455371862687797328895558871634" +"429756244755392366369488877823890174981027"; +static const char* pi = +"3.141592653589793238462643383279502884197169399375105820974944592307816406286208" +"99862803482534211706798214808651328230664709384460955058223172535940812848111745" +"02841027019385211055596446229489549303819644288109756659334461284756482337867831" +"65271201909145648566923460348610454326648213393607260249141273724587006606315588" +"17488152092096282925409171536436789259036001133053054882046652138414695194151160" +"94330572703657595919530921861173819326117931051185480744623799627495673518857527" +"24891227938183011949129833673362440656643086021394946395224737190702179860943702" +"77053921717629317675238467481846766940513200056812714526356082778577134275778960" +"91736371787214684409012249534301465495853710507922796892589235420199561121290219" +"60864034418159813629774771309960518707211349999998372978049951059731732816096318" +"59502445945534690830264252230825334468503526193118817101000313783875288658753320" +"83814206171776691473035982534904287554687311595628638823537875937519577818577805" +"32171226806613001927876611195909216420198938095257201065485863278865936153381827" +"96823030195203530185296899577362259941389124972177528347913151557485724245415069" +"59508295331168617278558890750983817546374649393192550604009277016711390098488240" +"12858361603563707660104710181942955596198946767837449448255379774726847104047534" +"64620804668425906949129331367702898915210475216205696602405803815019351125338243" +"00355876402474964732639141992726042699227967823547816360093417216412199245863150" +"30286182974555706749838505494588586926995690927210797509302955321165344987202755" +"96023648066549911988183479775356636980742654252786255181841757467289097777279380" +"00816470600161452491921732172147723501414419735685481613611573525521334757418494" +"68438523323907394143334547762416862518983569485562099219222184272550254256887671" +"79049460165346680498862723279178608578438382796797668145410095388378636095068006" +"42251252051173929848960841284886269456042419652850222106611863067442786220391949" +"45047123713786960956364371917287467764657573962413890865832645995813390478027590" +"09946576407895126946839835259570982582262052248940772671947826848260147699090264" +"01363944374553050682034962524517493996514314298091906592509372216964615157098583" +"87410597885959772975498930161753928468138268683868942774155991855925245953959431" +"04997252468084598727364469584865383673622262609912460805124388439045124413654976" +"27807977156914359977001296160894416948685558484063534220722258284886481584560285" +"06016842739452267467678895252138522549954666727823986456596116354886230577456498" +"03559363456817432411251507606947945109659609402522887971089314566913686722874894" +"05601015033086179286809208747609178249385890097149096759852613655497818931297848" +"21682998948722658804857564014270477555132379641451523746234364542858444795265867" +"82105114135473573952311342716610213596953623144295248493718711014576540359027993" +"44037420073105785390621983874478084784896833214457138687519435064302184531910484" +"81005370614680674919278191197939952061419663428754440643745123718192179998391015" +"91956181467514269123974894090718649423196"; +static const char* e = +"2.718281828459045235360287471352662497757247093699959574966967627724076630353547" +"59457138217852516642742746639193200305992181741359662904357290033429526059563073" +"81323286279434907632338298807531952510190115738341879307021540891499348841675092" +"44761460668082264800168477411853742345442437107539077744992069551702761838606261" +"33138458300075204493382656029760673711320070932870912744374704723069697720931014" +"16928368190255151086574637721112523897844250569536967707854499699679468644549059" +"87931636889230098793127736178215424999229576351482208269895193668033182528869398" +"49646510582093923982948879332036250944311730123819706841614039701983767932068328" +"23764648042953118023287825098194558153017567173613320698112509961818815930416903" +"51598888519345807273866738589422879228499892086805825749279610484198444363463244" +"96848756023362482704197862320900216099023530436994184914631409343173814364054625" +"31520961836908887070167683964243781405927145635490613031072085103837505101157477" +"04171898610687396965521267154688957035035402123407849819334321068170121005627880" +"23519303322474501585390473041995777709350366041699732972508868769664035557071622" +"68447162560798826517871341951246652010305921236677194325278675398558944896970964" +"09754591856956380236370162112047742722836489613422516445078182442352948636372141" +"74023889344124796357437026375529444833799801612549227850925778256209262264832627" +"79333865664816277251640191059004916449982893150566047258027786318641551956532442" +"58698294695930801915298721172556347546396447910145904090586298496791287406870504" +"89585867174798546677575732056812884592054133405392200011378630094556068816674001" +"69842055804033637953764520304024322566135278369511778838638744396625322498506549" +"95886234281899707733276171783928034946501434558897071942586398772754710962953741" +"52111513683506275260232648472870392076431005958411661205452970302364725492966693" +"81151373227536450988890313602057248176585118063036442812314965507047510254465011" +"72721155519486685080036853228183152196003735625279449515828418829478761085263981" +"39559900673764829224437528718462457803619298197139914756448826260390338144182326" +"25150974827987779964373089970388867782271383605772978824125611907176639465070633" +"04527954661855096666185664709711344474016070462621568071748187784437143698821855" +"96709591025968620023537185887485696522000503117343920732113908032936344797273559" +"55277349071783793421637012050054513263835440001863239914907054797780566978533580" +"48966906295119432473099587655236812859041383241160722602998330535370876138939639" +"17795745401613722361878936526053815584158718692553860616477983402543512843961294" +"60352913325942794904337299085731580290958631382683291477116396337092400316894586" +"36060645845925126994655724839186564209752685082307544254599376917041977780085362" +"73094171016343490769642372229435236612557250881477922315197477806056967253801718" +"07763603462459278778465850656050780844211529697521890874019660906651803516501792" +"50461950136658543663271254963990854914420001457476081930221206602433009641270489" +"43903971771951806990869986066365832322787"; + +template +inline bool is_mpfr(const T&) +{ + return false; +} +#if defined(TEST_MPFR_50) +template +inline bool is_mpfr(const boost::multiprecision::number, ET>&) +{ + return true; +} +#endif + +template +void test() +{ + typedef typename T::backend_type backend_type; + T num, expect; + num.backend() = boost::multiprecision::default_ops::get_constant_pi(); + expect = static_cast(pi); + BOOST_CHECK_CLOSE_FRACTION(num, expect, std::numeric_limits::epsilon() * (is_mpfr(num) ? 1200 : 2)); + num.backend() = boost::multiprecision::default_ops::get_constant_ln2(); + expect = static_cast(ln2); + BOOST_CHECK_CLOSE_FRACTION(num, expect, std::numeric_limits::epsilon() * (is_mpfr(num) ? 30 : 1)); + num.backend() = boost::multiprecision::default_ops::get_constant_e(); + expect = static_cast(e); + BOOST_CHECK_CLOSE_FRACTION(num, expect, std::numeric_limits::epsilon() * (is_mpfr(num) ? 2 : 1)); +} + +int main() +{ +#ifdef TEST_MPFR_50 + test > >(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test > >(); +#endif +#ifdef TEST_MPF_50 + test > >(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_constexpr.cpp b/test/test_constexpr.cpp new file mode 100644 index 00000000..ca84ad3e --- /dev/null +++ b/test/test_constexpr.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +#ifndef BOOST_NO_CONSTEXPR + +template +void silence_unused(const T&){} + +template +void test1() +{ + constexpr T i1 = 2u; + constexpr T i2; + constexpr T i3 = -3; + constexpr T i4(i1); + + silence_unused(i1); + silence_unused(i2); + silence_unused(i3); + silence_unused(i4); +} +template +void test2() +{ + constexpr T i1 = 2u; + constexpr T i2; + constexpr T i3 = -3; + + silence_unused(i1); + silence_unused(i2); + silence_unused(i3); +} +template +void test3() +{ + constexpr T i1 = 2u; + constexpr T i2; + + silence_unused(i1); + silence_unused(i2); +} + +using namespace boost::multiprecision; + +template void test1, et_off> >(); +template void test1, et_off> >(); +template void test3, et_off> >(); +template void test2, et_off> >(); + +#endif diff --git a/test/test_cos.cpp b/test/test_cos.cpp new file mode 100644 index 00000000..55c6540b --- /dev/null +++ b/test/test_cos.cpp @@ -0,0 +1,316 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "-2.37609908807915949996042688873953402912174184373388399043229539427530802169622688886435380890546981798452174137747437590e-1", + "8.03406366226813589517543567844755380935198206635917017883860879215939165740799963435747185200486086864198723786516760875e-1", + "8.60219386510802105228997694366289682807721120146423711696179175800635220710279361583231346318224971127450760223168489952e-1", + "-1.36768951513839774357595871594675554406872039078811749027554673949684004409484639336417431285061889554892096426752261915e-1", + "-9.66210139195431691033548069227792927999642647449593184440815029076272297050360196975341458076547426373476590671462150981e-1", + "-6.12007278553856790723803948280976098970972124581361775428331444376106018942231526074915731012122426588769327127413045994e-1", + "4.91927698740873688392439262912409276430264703350691359723802294639643655296838880236042651349290074585311025856549893171e-1", + "9.93232596718899824059271235487971663771012607519717340071654721877802691370866768064059943491135925674950430467047724563e-1", + "2.77789911520199551017947550534057049374212876971194676010301098598339529915403722848373365985645657342475739669568931563e-1", + "-7.77955945956221239101360662190442739163791527953499629555756394261998892874934847131138921705713935365505245406994428077e-1", + "-8.80676278306736581575818642341143682410874043182925227659938804267878718513212454821032629378618345485453587099696563832e-1", + "9.54652155963865007116798560589970996367213754762169439269792747771200843006278637115722685610960738675814993576019945344e-2", + "9.54658201427917718824191302196929158303422390793460018465335986921801519149657723689322277773550748806000948225466432438e-1", + "6.44358700620889799575033272322899136331490664925359198096632560532437137894857803619177106562399406351419810452110265174e-1", + "-4.55304635273050571206400777159475409897339683148730716647371922365967582339285347105376503917296765204188604297021364549e-1", + "-9.97202532932553753622481171186283382950122646390227670693679248197349800205205290898290539070732778341271049474946533154e-1", + "-3.17489525058325500707686194437148362752290391406825231198381521862930317513649081353670386166519524315810546189268634469e-1", + "7.51160186640147504067744846462384089742696250681200524524912647858645140367792164416711871535116761744380912486921554617e-1", + "8.99610194168373157174515848193119670768490559799348397680196213249921436405001710937402190319584272526657508442591319630e-1", + "-5.39963892484342940823660554048696208293700871414984387094529796385334086703752106515008832585578915389731907422242902573e-2", + "-9.41455348900839346761557896365239742769987576963330061702397697388879776230596944312519157729410022380228287314835345969e-1", + "-6.75595816763857390859268297670835380459024839344154743310231115864242050771191159334664874097564054770066166961642073448e-1", + "4.17894201894880415042381733708896725748531223743344790054523182948440843948904650988733732381978194392219295696279423635e-1", + "9.99447981389824371458566861195586395552622718284098766856978062347139060489410032781030191080200904443096549587568037683e-1", + "3.56640095868759075150409032448421838265699043643228482503057299699740924345262819242042067863780263400092250418388628640e-1", + "-7.23065426868134142613141384486526262450487633432466529798821958977732347646832059032382447792655111641456570392189752211e-1", + "-9.16988391192434436877664999042786024703848714036221388727578305299843547352325574309860356272561772723624753484063972217e-1", + "1.24341855683226931265962750806821531283439413068694552738675989282017066737438591268502070364982899342633928417210588531e-2", + "9.26624413643579136646620112107410908114766812511471130116341925013001661546817531064974089666536893346764523464250445838e-1", + "7.05664607841658050248613256866289182754229289446384595719719495272020558391145537620968819401219414243210529013148958366e-1", + "-3.79761093422301890838671114556341706055562482358183402807224298533060188038450560241345615647754569347252101282386222173e-1", + "-9.99965058979463689113370264378210962384824970050865061898892508056811665771886385589295806419278045318841717598003331419e-1", + "-3.95173919871548266286836251448043149039940610894391718791244019288314418437411707835924620250473697245151743147215758686e-1", + "6.93720251624319621941983929806434090162802383400620564454074825718151625795576680427510026452063593762417421561201654156e-1", + "9.32780816819880202610269817418700102084277332259524791943833699964920012022753227823298655560837271746316929623378078695e-1", + "2.91495208658083070508005579692813621670878962971611104453227900103973434149303469066898102622556226584993895360896300290e-2", + "-9.10191043170480685360743788297835112117551819731152897291272407935139876953384666161532187572493791297095784055525159185e-1", + "-7.34513075127503122343910106816656237074878218180284276449954797048122379869002663646507706411949095015624141821039453971e-1", + "3.40971254411713599427147477626159847871020791931107106418841144080445813896332252160005593096670674809345703079384115052e-1", + "9.98752871506016936810666998588493462933191829230756181478046320353377054175122206889047094521687205093218701141334147081e-1", + "4.33024359542714849537532946954507232835434973891665238942502273464321666207117525270650546741831354943253652514490075246e-1", + "-6.63175408268187738636594884921931867786416057472876635147295424128144233911929585327601381618059327766986981109409782838e-1", + "-9.46960160806563725719808910991708075372282242401645009270517113290439792088443109178772446465191984149998211903724560065e-1", + "-7.06828182905581345108929510344440443421290640066613022421187316650733628538705972455891575947230299102119854983197703150e-2", + "8.92183656127948379886438402777950080111433733329436790239129260607557296960582455582584117031260710927499215646838011844e-1", + "7.62091330231640362984555508176991632755732840163230620595759320390970951235395195394649584713540498911356433919369698423e-1", + "-3.01591765120371930643555588643712101466544136366607065361801475091335195383846047491935017919396438040414024941341524187e-1", + "-9.95813515236177554177387795413035497724212540625760091518605741283184405719984044075159457509720410668598540884613985023e-1", + "-4.70125959152223022135690700550251564040118601846181392455764893020377582359429013073566263451488554529709131439092909247e-1", + "6.31483718775865440843182928017874708719203714677143270278178885379757350754752477512514449375355491054871712891789652146e-1", + "1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "3.87481045630097871028201331640164477694000480353342897357083794605539506785023570062767753819472037935010414476627195076e-1", + "-6.99716878554812023132822640034166338740077082416915046841339368979161296335086955803240899441098534898926193252558848693e-1", + "-9.29735101124991407032113033015438177585645722877060262785796302722011806301680288369763295777635760805579255008366302180e-1", + "-2.07925797310208845709174899248298159909010721767168338004516304026594885686024530923209628704670627250569637267490913462e-2", + "9.13621640053945104047985280883096238900189007462190433514805702721127019097915088259906184736442916334750420359005079959e-1", + "7.28814716527795995795780587639833705107995825167970668466246348938821997240383021826681253777014938636567626203524137506e-1", + "-3.48817863192357573536083313907744269588018702862402502601699983054718835012048372083235768555953613790431700360695537918e-1", + "-9.99135337256258278958854200595331742602280601557283993231562055717063052179292021052372510863057206152466386086657442382e-1", + "-4.25474147219713305654097901385832164424798803616095278869643928816776198489330071073326518019520590535564717523756486665e-1", + "6.69409002349720857726983952566596052122726437391092096671257338244059819036586172017092390651026654050631669646310910927e-1", + "9.44240747589054266930136705015787520728797286842746645573763175559132491628984502333043316023599487896169049499868916865e-1", + "6.23417820549832676844933182722733277887833220127638406914080428946880981800946578131712749910941183940944526141109771339e-2", + "-8.95928229794837090592434136137683839101829890460754766346170956577979909285084363961363023377587044303560652568203578379e-1", + "-7.56652196635835430995109388017590459596111729342964992503572530290981857981790620732129221157071082788019187787999930361e-1", + "3.09551461133309219674309651201007026752336319933918953736299690287371505733386433918863300129026763968979930342098019300e-1", + "9.96542844308353945757715814452637400116215448012622700698887257177706625278927018059066920597035660000571997275705962011e-1", + "4.62731465522276407764000677957978862104808823938378826581864482071733508960062598574638347814740748458034065235894523010e-1", + "-6.37943500095315456672541800050589670140910744260281868746767523730582697622604545933849801882909439609368258115114388202e-1", + "-9.57113494461990955768932962010819183910065445494138937651443249061391692258872250121438832853873660881630205561168895590e-1", + "-1.03783175146302830356973378710923690121182237844646430783773333188328606275124873219756415071202025673009660963930966273e-1", + "8.76685468012988943166112725030293740012198666616661362437433807594683780986916439696374569274720383546275206733493672834e-1", + "7.83181178815072182812568575402104911406191663934571600092749188502783771503475038116599065276589122015600004250624262132e-1", + "-2.69749743842835294071354429049113807280228918034124159074991560056663623624511602063409428877143567459307323934051784210e-1", + "-9.92227004420417932443416371636723983768124774541445787394585828303853075015733744933294181104002649816119116502663362907e-1", + "-4.99188570507651271652464431008309802023236218596632956064119419694573621896525872847587264755853127438644874992889777436e-1", + "6.05374785886620830935500306718810628353011877048386199574451402773468315797082901705593423724389976967865835641164117478e-1", + "9.68331080574540181354402420018944004334504868848934676984951546671476956051983469715128604348963016773169794077158289730e-1", + "1.45045093347669933436797325432376656017480150281100519869038554695618054318368975927557872948037203212941966706926758604e-1", + "-8.55926631706799584065153976496431313099942493164544290051315786450857575707615522517293656706329757352795226750189755758e-1", + "-8.08355785820466703104647317116964786017731181599256098405978700298563758509572188640629418770593008092680980412866065299e-1", + "2.29481541445091823694157468006983283649885473964756916206813927875661041834620526229807744443043682778028709792615798955e-1", + "9.86195281084368344446227722442335005500018635181693920385626820970119467136148305491035657795704047666385553672680209923e-1", + "5.34782415974986828906369231191245075731384342252264783019973387059318216570499447505623911253042567598873910043381675873e-1", + "-5.71759181631212640256161075896307515511612057247572886814941945052483422285718810088660759708176904381865453799197101481e-1", + "-9.77874107069129472007009478090869879295520839405452365411822873037906082086100232576241983901051327761231156641104065497e-1", + "-1.86056181372276495846711248156316208757691570931906856005697361080864028851991674077024223201008430626166447144444086146e-1", + "8.33687619660983803179149188531271900120055171980951416163724579833511897001564116810390933587615557717585362295882429826e-1", + "8.32132482562487183916482822112362004641509381783438374175226355792137053285527706239574867923387554339582561002247202518e-1", + "-1.88816490768820368180947188938258919466912959009058295775702554895970560887437777994365295452696990115940651570073217522e-1", + "-9.78458105113103660973458641126689066610890753079836635611789969774219913050456840122278188955139015473252491612410972950e-1", + "-5.69451448580118869157805059117807250106203230622762838051154208713065707949727035884250775206017528612930773233017928006e-1", + "5.37154819650306918873973169624898539483418364490295996462663218848771864764982600193558748568095521886456306061269765631e-1", + "9.85726070946814004698231423834505649751779161578718404221294527194525251740198034173542003704080544827976936213857653517e-1", + "2.26745517700332138489400566746499809209783385009289423848083137846668382711005704387134606000570923556980021574851618566e-1", + "-8.10006890365888881023982873786181048364505748637138923322482323010218991062084191379116946709356002103893071903481540337e-1", + "-8.54470151393449484710948210543666267680196067632693416660536443330720708402601669617638569732848938319544250428600991723e-1", + "1.47824914922605209542648603104533928946885824995208478684499907657728115943168395067575842431291755277452367320596435067e-1", + "9.69028856602232134498324179654622883463820270279077886397861028881882684131282848087869087883519707948141915733221980948e-1", + "6.03135714281336943093251136556365407562473924416812270469171432809743173719168209727199952532489544254928975940518615351e-1", + "-5.01621542149055350065079347615664213658089623368745676779267390227688581807037821041573344917735076902116221444127518632e-1", + }}; + + boost::uintmax_t max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + static const T euler_gamma = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + T val = cos(euler_gamma * ((100 * k) - 5000)); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = cos(-euler_gamma * ((100 * k) - 5000)); + e = relative_error(val, T(data[k])); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 5000000000ULL); + + static const boost::array near_one = + {{ + "0.001103662615143147017601393734232421549156847219973314118949247990939859507971857976111288683988415478257878902917354105871236439563170045857810738102729287303674642020538722348587741395785016549139854168605590336633274890874911975139498047488076101124170425114828336211817830671418321600962996502656221412102902998671173649312277667706874059520046508702908872747388744526457997404065469953155187340837", + "0.0030157041572432190019717764776322147049224887913331212054173669461673516770769148735558540290915754514269097799280330158745508542936966046640795712691698490758472574837678659161855207596563250546269614348515005196657786359646020537231301121492728577410212550350070502426482802490452572415879214994201864402901595309726458026672888041860289772080407882673424767232857435141510615538430445535588448032261", + "0.0049277346741750694119109616231402901360500185022482787362616412856233338679208830974124749830793778323997684640684587346403570647040211088376986993615001420565608501262335822815041623056442245053684626079448221530207757672939048030945164948521320401574074802966260975904478775314730002799895049652983052125151436511589335123254582883803928373794668948878049089088843407672795237410750365571990834236348", + "0.0068397471757112108044544339281399968563253858411528016363900245610068161564091499398024110635089866212789583403491711476788985949178019078796740862827299289838108117219486357027460681238178010067475221327133396780718266880540272936860185783976937569903778160170225166328920201699827472893824363838439627437187765159770262282930293057633886299749088561182830982345936603553661004526800797082995898813903", + "0.008751734671690018552720976028788304981263251327799787402847843531098338033456389098956160956160597460869666211569183483587979772678557230743050583975270977754518475970489741156524119378847305446845331098526962579804361960647344836744631465315238254178161716870409320747176674142306881908614436607977326507761331050644035013756409444911127742401762647885817361924274132830920030936589562922803846509607", + "0.010663690172041286306192948782895990881227033104763005629047563262531418373465237876680529005058533981010793759446966868628480908709812402179047774888094761104238131843239037167212206469894485599085717216855637620318723457013401360290343196462723174177342294339229792213396006286331141933952648238459364417067676760977202812721209681621184724443514062993874571816382775241753902032787099435678672474841", + "0.012575606686811781116778815864446643746718166744927923785139233710240017201737625088406861185781739628293213436323314376708933534933748436720721568462267317026688561438144113855290140925120435317506169856461386623828941531577425811393721991195661429557079268566156800689149725770186985872449679872155877537432897653904213375816262709009448220490217917537801655330411526526290708967440087145630462068976", + "0.014487477226190798137230457835664944872810802211308342685055637400305474021552028493778559102552025380880477103065187688337931713540557562373991431880251553620947836940726544553647739994157300967262941976933375115946629204615918888689039777423610894099269527633757403818072000860056651445780074486612843419789636984117740884711882675016016919064788076097669389652323393864660933705259163296837955978748", + "0.016399294800535714798489384358524900105286836154421890562438917862501411947245037986455919696365301666112414890097246479762149456962809638588245466988584093380263545543023411087203351948681559905336010066900667101787138862856447778428938265451537422367650992162004154495705878092019403922006152498705687706013973674800621422751806347308220226407830977673540994341535381202679482907460136241543505771361", + "0.018311052420397544372537858201001145083914223029622271478159852925692124442640247100336262041440360412392318902558295108452513123454103504516607498763863728284797202978975409264141138861738184468257576157204552383675442780049333490201800526935793000727771598103735596829143729912656158790924063286176336412427525710457367751437348230246446466833498557166002214984255422115833828533909144072330080184872", + "0.020222743096546488827333191237246591760639730704704148795009602627175281013458865557238240830203973690492882935553111519759474835556686812553430134442713057622274348510526931333124437928482001301214776111358848026164688447150395879262705323533149853785508106018564787140458587165768350143018847840661371060583295055600185059031740386698369796694993301139380463919242175430688496936048982929502368583755", + "0.022134359839997490880406060727014362125793630864951833270601574861700025448109186301755833862830343973100181180995751924514611578149687732808840212399134735559355116816700346196685057916461444889179117142807858883574426062415931319905031345377305247124198345242221848293630112578508459623098934259229893301963120289071135120089672338617200639338087265986570094025605269870532431816151660553037324591448", + "0.024045895662035785157706623778569329505432699504171659064296747761761946910295074291838826981712792368282349553905175996858645967280135417577488810651594776626562252686758463813820791031580579721782251705600570838044158357396828391251385978824608388341556751951593319015721256942139947235672567093309227673005475237474351604086627391812539914665025071874865132198040631867741985556198082915821590691115", + "0.025957343574242448364285479040344211549214421772336408904791690210449825580868841229728937909141136116652894475476991471494524501035809956288247010861464302066154254736425460468024350571584780489213056428098560686376999562953811729945811217829999284678155635497607933780499844559793793320393174691097636750027421158473345884329284455326733063073401001936304522649050748641723222539485352644237494855455", + "0.027868696588519948373400137317728007608587427701668964330844960393232962659347088604492706251530487148805683505883152882204177723404307465324383408418716579280515871949790204586171885981761699066301009410176801635003961167315448162116236938093263170474354430610732127054993766008385425707409224417795873645410443727472246508894027549288331903202127478347028519320691939639175445464091747341289465807076", + "0.029779947717117692140641616959423088975059158964671307393654571763491553590582559015283533532986018614029995854278748039155177088839414450454409571267110720713374288363670804692289394770804051182510495900322915294613479146430103948686457060129295537542317247965142780968717375277053102667416124807987527429828758851341378395347636356414345553353015296944031211364374602764176767114282660874356057979248", + "0.03169108997265757234968007548831539092664261419258315028339932724609641378752993073240305448323210275610250474048387518003293691429670190316839718892647475151605557113852966925288722557261748981001717642661075734993748510506277165730472207647763678204813714194082852502621623007244214605646094787730992510318924772328958129857640953691466395972638014259980360897599169526022683004620965496473543834477", + "0.033602116368159512696233026049065446239504816931754722314316906991719894135599777826750609185018647633748023602662568553364455253741994701511752478506175671449029859193583332380924298164350627023797218098539441228986492601142199774579432202424360114528105854714450548265654769162069979862894518829365029262734944196495563243510942310738160350648115273816371164862001848102516957052031698646996790510953", + "0.035513019917067011716864665791693591701266221069066142988726516832036728613300457006403299601385922973285573124147669717618486570986860008564309641657943172757912451506572783449830586163814477502720341010870119231030511664725149033496023356743601581035789746158436049009960920433265660001864258067191594425969638702851317416487965304378219676062220223886417078628342731900948906319081697480745936074075", + "0.037423793633272685069230163289099410548201460485083250584815890545695501760634737348027106921155349564805321222282824709072582234185849564440670000847571561359324629877368620222775856068569278590582843550096096627510109210574429458414697641703261368397349100700647508781941466979105505468662952228018391181441110331804231754679360190526351574820397399161022517352576803713854137820941977691824804918229", + "0.039334430531143806170384413477273936914540782490679532559795199052084263353981243128408259086619593938946158294175465792633584421592350011455198124846778194417281005620258982615227234871780679327289232072858751285307955384102986030326321993554199425677956531006546270705693578070953933490084008156062047268010604414954653769711129551190023978078265436680151306319349753427763894284339669614362603225399", + "0.041244923625547845099780771389235760645292527949481044094490883777921290140650504322516472637184803214130714431279474404434513167088543202171922178874118967991301744186858054508473413647148744260057423931033177973119110921967581379650616945061418716237102199971097086754171168500651650526166023618723542873290120298640370217463634503988257867984189842393302366909916756244585593509804376197012137137735", + "0.043155265931878005673591620105503250213648422568500347993529171942176855000247082147052189275394127432389966427668413127665366489709229602926384588361071126297040547180622989395253518259197742053810419372452372506534313264090033740095357809571640645325965973975968081307185286025492280541542290934505383760407808393490207181258819590768103829347539943429968533891105456889889207923129412409325200337396", + "0.045065450466078760596989313842010956972889269629840996618541471076456145341576346037140737554087089598232657340541865108389258265511462307708855932308284610805209084413460614598570062354088931179587984702006847566162492414964136182928014974554852612762940578089297583097434972291633301329615187665009664697057933900728259220674217919826618275818024987757805509580781060051826778978395144370327934582031", + "0.046975470244671384601033063916347240271496301008030038885300525267985292259051299166038486168462131096926077920611254966322965395673221324506213593415263189667393727124978454125104192236004303056348320706091018781990803164595039969574510002737990997634364247271320535459089400357647302806652831431190979518269432197656547265417669309719787317687585776029758282182901563328846367691507505917911626458378", + "0.048885318284779485470814703449342779874157141188272539012461507790598796169844054420701400747288103863351008593834375336008952419161297787680355981672505884405645257094616683497040471721980241679616912483788844007649447969703512155758482444019770785766752697959554691538291379700303132353876869628124563105576278585509058450081192711918856522653293896204836307264696289474219755720645459588331890558889", + "0.050794987604154532871523976044438688478988546522275702591135165295075684834775069782087540212155311599924632216878717363279038406203747968637573994688146329296755023729170505930935028107359530042909822369245609091696704070694133386183688825674952803613566914142157159664703170379754943610785780639205752343103591085978554489192416588288410803225066825839880971435465232206429722600557780654218330146221", + "0.052704471221201384879102044313723519214541830844294339002006150295000261803629777930668202713875629368914012613840180174156598399096984605842000917709330893871365961242812860633022132663435078869433262371062200555333508565564704972551921154864927879748108180002977668648111714062992755985320189721615088748697314805428967770533095416911693326757965362169171309026356339280576158225848771071227224373815", + "0.054613762155003812122160305957618147686113745063989650607179163157398820817715079449268802189362998719256947035541552524839497119721884536865240705017403409053301625152685151644761334409897199810093505097528650897729279062117617766845257388412635800174656504897022571125534403010151970450307624961920347280823962725005822339087173498538012712497715370388872960900453285934131578336748483622553313648565", + "0.056522853425350019441850338124226420404372628229474954730316461224029279793449121148941830155705856364290655296696008865349058650396297667951745639266344993911111272076019522476315254920931469406381088740392436352997178777214659473302034620137440843681809428909274912969436139312159105442160243076856936138443854294531618433726198293972487505166088883354213979143973990964298454127970039847456893860203", + "0.058431738052758164976379864942430396555977098734986011309321413104802080798824039565461521608355122102022725461220269967251619843394860641070621951433765763369761658916816880868188275032453137184211673934079277285593935159478757148621410070196500221526968060556586710920750728824112282461003224923995158937905479480579208549847478185757177039153501786271361921802927586114942206193581554801605680183774", + "0.060340409058501876576879058406717550375449897922866349024612531373677724965692896763451690034750214807393086060232183962741893455630800282528706094634312497867863194252914455062127544671909424505367559503649890477570116767021509485710626043408265846213906257952113003324887350087083283630715857354116849013376841533857321740197047217435805280085872071354373524395263864933170034771001607559366437835689", + "0.06224885946463576546133123915706193746686049729742751789281333411875145041642253752249398319274836506892916659694331849766284472811963607782488993959669913942440995816339529777656740297867471191540909520680122909159182411803441391065468297111274482089347737322313334144161837035757661055283810143238846811496286086926075008068489724098160672664550444107807861952850135669761489736449089327971794824585", + "0.064157082294020937013292141108273585068933185681722806586173136512969086561151000586083228827704474922133659368208499428517560937267711287558275856325851735527047525549135602809953924346232393575354505341516408877034795144989051337120442048812961016500803766780090428411925756071299228254760633032932651170483895163866111455935100454818941073761804284777739005007991141161823471943803047351369535073521", + "0.066065070570350498632132342303164932774411476452581548988386145454309844170784631219900687545375669726062411278210148833761887075889382631711319762066717518842787273543143969874177059386003262516941215168234997245420735913778365997498382320917159517052861653706668051150014889560865161606396037665048820655743861710636504450723955435275019348223982732095398949832565423361714391500479155224225613768011", + "0.067972817318175064541548243754498015429928588516517183822313264446879635682093113384264993280408482780193047687370305892309106748875519486540879020142902362307237689684697063792225838111742241714789823601251998299331254097504567214769822096812914869886418586879378868131071702869283011709161582762527864014863950459121468893761825841337802563429112718615110803469902519051203360473993644451463303576859", + "0.069880315562928257463098098362562671709183706398122146969098129179472379455539984270317889382725678551314678030902515782188203802362460214070192378666311369730755912670660970378408284876465192356340335277225457776091515934608751710356445501169982098020701963512215973413220903547301855847279762573955110834619967590588317288171580291576756417265600792610005176888567344924086299458709493921684370833814", + "0.071787558330952207061531053207739391124226218288071373402959685303573894071937999096931283415397385296306228484128726125223568292760110763075739612174182840148193517540379302896938375357744754831885570482299802985278525692833941172622048860945698352794727105726197891701070706523197225463566498764869186174536278875440544967870368440256565084805804998877012238900798874720340885805165811704445925369809", + "0.07369453864952304506868897057861922170414313661538863465614770246556638808351254050794164760581857499175318127117745597595046399453737415234966090460819383278338184265518294393589316067434296307320873514873375534499000895507092920123162793722742278902956263178675873980121089525814840115300730124457959632013360479776554262210801798434607194598511786777350540581826836696200671400628870250659962729555", + "0.075601249546876396992772935963040077834759122887264324876826746597298507042570795315940378957369646666545616927930046677179646722187557860442506025110541968257406052679604681892086517951648112201767029044637142334937786145563391280677987040697732028896674786378870229133792190093646530752257521390201161387698590619925316803401938362974478273195688740273778224688121208296858072701246429755713258468481", + "0.077507684052232870319778844857360483087988665809157375994805235390695227945273826842335916971262245322463861698987988491433092759415620685754813456247989287157909601376742141647886684380473379403067343977633347655683745871434202230624968375294472571053679501320680048739346844244553807193670436672857163839591129928936603341033670518982144557944158002407590669543043048232580344768659176122645763500513", + "0.079413835195823539113919284592789131508074280056913456617148863190077260584186476150168101766032692499585019572300009477107342325731806003539645749720998260074894005503243715777788187754550286488316966320623707403846973934258796072434720381188302956748572794547906591019552569722211941807674118070825610462581312695693650893380241875873254675082431417454526920871842555422162216221640850141209989864308", + "0.081319696008915424923862092389736899811819511475112310887916890436246797704730704673729056088324784096921353721791055102563812592375189346816348952621603248827528923433998597558478366712658235656924601774921095079356565867874041683517103417362062033545480747089630436317004907748679995334911923789802669273406449877710501792905734235548100216242648355048174292232350538531258791292074224222773259366265", + "0.083225259523836973901629476483826882570495097409722948211156651871411915926347698443317606324912095013846386144848076019334983060323996364575622231284156371311209803383868297666027142776492604713451401116304951916037351315288808149328656282592946622481248077426878390562084748274992526750980236994304445617883874613002677387890383751048690275480465558930319669630406765794141303531112767626885032234711", + "0.085130518774003530041015433371012162123590338565297712899451572274044870858132401685294989726432756808251618198809497117031428754224182463768189333992610411750324249283786647605964593556580841488686189374310703328490638378071341189999989736919850819640255203388192531225871093915262442913255553964348789674386732423763999398384843950222967487918049677831350991752153610543052586794779289758903475438463", + "0.087035466793942804442393380943589773874807384137701777807755858606555806090045313793349743667697666495784828540247587627381581545620918795107877715086227932192756144780086856515641298195558204484728115519445514732755572178929839231921546119143469647706999890259163924570037168105911942268212237224359201159897493303064534985539474450028748960081579369980283792804593122976296597796047722827878891322393", + "0.088940096619320340510800454481897179643787714504988904779549430422905882044782054375828906100456879992313640144934242418129400679706865644316664458061953684856607341811667576418163339843372041295322709797007871604740491453013916791024918954258557372755707588171502529270934617054742841996068375532958173787119651672031238405892943090742861150287144368470297356054911834742041692715934237148148936307154", + "0.090844401286964974994199780075024285173534240616972938308566124002318176156233343333797652771250228033597767340846476094210813299723066344955542455246897302945908336756464582189829335315055318509171623072382573656172991307091055717376996812421994002305994837615827430425975713541786272473174908117299253875064746541808768776888139494200307162476704515967971265236163183394620211890252072718610942571965", + "0.092748373834894294768837248013614869545920040757666771889792264347367335922283987944081370356939214799510822558638935486112190359701790662792925773186897671244831971450474952036618937833706899006048469791213129922302798462311426294239282200248625552430083292818594731518350634587677158329361662244008606299358410273467156168469937529868888478684257396004386633746334360279683178784117372066095688934486", + "0.094652007302340089278624856973167138217258137565762699413364163993950641989798336903224059425798872308451866930780842878435503832366316245159154044350517727312654980455290163514021860802028251981954724580292247887851185639950862672925642859475325430465650514258094310141033116303195908372018392349011340787373492402788283020594141795669947097771918542864972570255253465754192708165241608041715996375567", + "0.09655529472977379853549858833033074225823562054271495313739665642376685099661084023094270272485976247900824483810911634635819558334630910267353320029261330296977292720266655308513559530586843550229208517388789783011887450865488554143475302590353915732321663418057567573042594801866258948380684000769091353165879953111046260532796891917772727185993569684246844052518121013717183610828519193371796413317", + }}; + + T half_pi = static_cast("1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404325664115332354692230477529111586267970406424055872514205135096926055277982231147447746519098221440548783296672306423782411689339158263560095457282428346173017430522716332410669680363012457064"); + + max_err = 0; + for(unsigned k = 0; k < near_one.size(); k++) + { + static const T euler_gamma = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + T val = cos(half_pi - (euler_gamma + k) / 523); + T e = relative_error(val, T(near_one[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = cos(-half_pi + (euler_gamma + k) / 523); + e = relative_error(val, T(near_one[k])); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 750); + + // + // Test with some exact binary values as input - this tests our code + // rather than the test data: + // + static const boost::array, 8> exact_data = + {{ + {{ 0.5, static_cast("0.877582561890372716116281582603829651991645197109744052997610868315950763274213947405794184084682258355478400593109053993") }}, + {{ 0.25, static_cast("0.968912421710644784144595449494189199804134190287442831148128124288942561184523327264655202799685025510352709626116202617") }}, + {{0.75, static_cast("0.731688868873820886311838753000084543840541276050772482507683220220750082501569499540967562610201174960122884908227300721") }}, + {{std::ldexp(1.0, -20), static_cast("0.99999999999954525264911357034690133684385823577463126432241468890539365027135494672267164697779879113636143901797362388") }}, + {{ 2, static_cast("-0.416146836547142386997568229500762189766000771075544890755149973781964936124079169074531777860169140367366791365215728559") }}, + {{ 5, static_cast("0.283662185463226264466639171513557308334422592252215944930359066586151456767382702286176981668344573238827368717546699737") }}, + {{ 10, static_cast("-0.839071529076452452258863947824064834519930165133168546835953731048792586866270768400933712760422138927451054405350243624") }}, + {{ 8.5, static_cast("-0.60201190268482361534842652295699870029606776360435523539636606145572515876770619546025351418378467287262574566665150299") }} + }}; + max_err = 0; + for(unsigned k = 0; k < exact_data.size(); k++) + { + T val = cos(exact_data[k][0]); + T e = relative_error(val, exact_data[k][1]); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = cos(-exact_data[k][0]); + e = relative_error(val, exact_data[k][1]); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); + + BOOST_TEST(cos(T(0)) == 1); + BOOST_TEST(fabs(cos(half_pi)) < std::numeric_limits::epsilon()); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_cosh.cpp b/test/test_cosh.cpp new file mode 100644 index 00000000..68b4d838 --- /dev/null +++ b/test/test_cosh.cpp @@ -0,0 +1,158 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "1.0560191127459844751259038114395241283965590525302917878166464679729562764239266483419824023679041866569431842053263976225991679105269492268050148624443706785607467750929028856273183654547152707568642275917435773104050171284580773949313906303074811586096214771879801872225500237540725592288167903987152007171391207680034517664218965133028298959753155835975555361514087618679892905973726581183754237665", + "6.0577917650974496023981039346694689204850927958941226507775366589415588030232830758139222010716099059155799853188868489737439396141346120898610181630988217093945337280471788812956307352429914669334599644412036010014302812555700905490062030666482387008384856645533100266205122930455496234252478878949675888122615795451076521244771554025667181070733415815608287241160724578541982548132473721865287585003", + "383.32956577005424506758441449272199796616394738942294350035763341369127219359132618750028176886177362785452836065735889720098699937365992620246167965376788963171659530350198190156275836547285437366012371175910490835823389352716981464503672749829183569550509561579181434088407652213421105693358960196044447948190823567291153397039759820680087749250557665869797605969680417240900163183563482342795870741", + "180470.88335034971169904627554690213669106779370247753503772451628313223853228134148123711258586005038324156900626143047383382773083164188515409766952843294484598668304799186411411329575367546332731190431166613267871177008493921416649792646568096789971466064344922873643120446759328638447781504932928745974584136039698220604099816877847080168890581112550484205291341188894903342677757367415636409890558", + "6.2781497954189513287619297175142770025826052476955600323495790530946900406209789437212923381830889846578651793922971071825731424267985994598149826652782605981764572599129753631344305259620294513472869937699509893247230674850025066547664563263958672029867981296029855675095947587305949634130736118694040608573981560192569935477462121110619100122692626135788198431038121227062383110684489973794745342204e8", + "1.613783114750852113223226710244634574082654363427931747177970610142560035434819323665197978270795707611590961019502906079030261920109649748962125930850198625621792763842224096823299250338750953491004408731082880660125641628213970297576817341593254767125933119462446651783267917469179893016103516988279473907996009458208097272806046395206212403180775656514566222835047724943633607736647735739948551096e13", + "3.0651210048650948869531196671342477415226643123350617715268971834881834615138925908518703584506447138436613632341330640449725016173384960626760387649747643297918807083363913015806893683786389067836005832038060734248371426886808175554210317756018846109627572546314172492701544345965940408777570519312837860014177872754358662463423939942202520475422342889660750666147940146262635303938752019875745307992e18", + "4.3016893602106215864771434464025735547192956887050537014696231526954713331351791376069506688795159316625154458115179050297716224800318064110052445970764898870599885508391064218065806885129697936678362276766771902589638957537168339190488273555753876162633237990462617955892238424402124353124736879474651977422350856642986446591941163073842974714357745162365700428610167249762162775568692443158879770006e24", + "4.4608685929681360001024935791890661655506049487122331222491789277138083092507844933483858468341107613657448783043064935174812965310544903547535217357996429824403225005261842368679242972243707736489629610256554995236901040773902962370130989883960298987808008001651650799892267761089302132749037069497452309074389846493140222931714618697738906019885122076310868220596765753447232222740129365498326869428e31", + "3.4181315955816806472569357441100390029536003312981931954091744304974491527743601285017456624487264929971022746516079644284683284072159616291298593217459064246713801084801182706805865477209408120733740982340972570739267039630582468876075574706187115643861449939429503730606743466086010115127464706315791765264572070452800816054590653675962889901898843712936126341807733200610910325052666512334161414655e39", + "1.935294628272790810141453021278524976364077691905248015888165919062516673344977091262644262832934899971824373171672037249361491844419302323587942915162859665992916625636813244576210109931852761921719987632855596663907494303248513195744818730879742963301327852160193919379798462926667740594397712731448572837824802330973561570848397758210619453310032286208701226098998940360395267237151018055781640126e48", + "8.0964449511890098565841496436016431651692307764702784234901741408135381374668439020986470675941110923614446905696411023621632714191313583360826598468217983223558130595633054971338824192327248896500337050246640453410159732184419096917171044075711156867804851018388576371530520943696439917673720450911725466781235347212700849702742625663288687644090935756560022610000629006347244369388824818661974220426e57", + "2.5028257092625174549175008952222569141816383637904981644379473858250736896174216539673733521627607209322019413420937570273676341726636307131078699799472622998437404149614292337267153201903296102921815263736653035269935857816159086496594269187082442244280898258397047045746728729079796167987895368614037770286371191530575814695859433478185016171380286325273493350193132538052551497175771289873181595171e68", + "5.7168370213792649967466315312864179662895170192695050789061362839510836418124645968032989149068311018994324517420345278843446068634292140996241291031113395887832891095928020095581695527354104986223411349657526888924224926675682032043363279774947976053895819671003276400297758359779703605970507328706064692923481168676751999124073697599262277247814864401196929320497117521176016017349797292609303756215e79", + "9.6487261169670031207955841899729386502708125098394777808615183927342163909284025992243201020435915122698808649711566042372911206942311277943247994427354130507790526857797833309691667380623792736661655695464087154725768656507603378053220212067894914686147301550764045337512361478831034999674296837635744344039906734109560908793921568633128400104314078575159786136202769893309913175064586488844295321363e91", + "1.2032977660238608232537005158851668311089986235965463249220377778638489972355974848209035082333822309902237165042868213438627625544096344578102199846440476859557339736747791529782018329078191477783605471526120466881600981869890379917878811691555316448842731085218988710571211956972016424649758226606500603194972966032036214213759991156778846329137084961334557845326183588274571457361004704490747798678e105", + "1.1088306081278288754492401130897590262404571813281460605683836139669281218442501421935533170636990866165181664561596333701204545493730707210930818738817252706131805203538144119244917164949716209095542194899833868499263375700313934257155601275526921302332118009966650991624878227108265079219497366770219141098050965023005919495048022616553249266192057652205987267068584616625670961423579715954410508985e119", + "7.5499880591625965663868042832675300901799245732418501707646792135512053284835138294796976048691668315442427834949618514094329533376442442492757936744857569785450769927581802961191319878260712808001736830227501518832554201816224207300614310712430470538022948957433004829725273067921443635526965673971412049693552004259820173389681647135125678701502084190660111860351299407405357314966388044340723077086e133", + "3.7985363580067976240250330165300706958269826851549371732460220923459822809007918495780412109700378352703982899561570150646963751463572075768540297484136809462018052149545042828665345287117150392150513078663739946623681053685054650372595872914400423446635806806461783139586204378680585507446218544068845246753010850565341852111017728985713047360191412931479535524815646071456825031827933342626130249175e149", + "1.4121319341572581270215359848706630542776633675711529687593487346259283960708095601494823112486631023721124235640943167173029348028743563902367757599140008654691320430919753414890689949599421028277624880392344132646738394546195638261279687543208503932172926275294218429086816560213399180179494004109164546844899632385177835442946174689070525154077366030192931540897742543089509897490703511310531249977e166", + "3.8790307719997974510664339744260233373881096199933152202662556556779783775106563986911859526413282055258612522499767709123313205863879946518297779104337686883587019222829967005608205535314284003183828513113021722123872387036435113517356676447376715595408179555267871947671679098986651665719279348025058713817796876795915844151719103197410787508530261619841035613531488383930867055908047961915279983259e183", + "7.8733605373835840397434523264038598405672829925651165847065668324385430746087633348848905637835428739401439679896923081980364912472282573695612463537585283007941057172128277340402716645674443632827653710173742423648839359547777694778576675604645880219833375227941998426325886558435214355022240854563558864080627758653439429917072753785194675103766900514602432580639079224631229479607396935864512990879e201", + "1.1808262995038900942517891457926200063018079695348469762725520377876370005771518954251015338402886097689762895044056273430051256244413916763438966705458118354189107806216991150264176024521937328179762640422127608560103802431672144866013216405157197709788484197720057702118788168789816074560208078260433548283881535909071116553897893659656781376448427981358955547508806938614921874867135186509274509121e221", + "1.3085817499987842655130548827168955655838432140245228169691892267707778790498773914833199368916114043966197329562444577848635313938483757629541576533880917215885485474416704968999200090496252044959849927443732134176975867869986011315975625868009065373046224716063168977788103866885720471095547385342868632018951910603936835789387464412366605713487321530237148912677199033012777178113821791621549557963e241", + "1.0715308148006899161903881353829644069217121138682658034413051575604561649576261428568888094218620444635013220705511245290719605273316790249367622122178650529000528086055415007045458486410501636380119413632657994999412652188430063128470336817401482172580366374079331295129200936246446347832380606353293858222758687479612927181530236387227215663399410099251455256898414199913458340065553949424990477448e262", + "6.483319651006309502237640505955012384293570932602353784849377890534620180296272226076424490097577093511886503973590409376477611667988893542117173598716788837179265384921201772013611631892729250835822804494742316330406688475091973437669111728949960922002370308207819760146543720499389938855072810566961589413895110830251224194598788696990065693705615156654866578134664648091752361824241438921952031149e283", + "2.8985391304542768293172709775230767981477721528885408305355619530690119426207269563049756824939397157221877775531212262059946098575425050827283362457005503261796116156917077778477251551070762614233325253060283603452216492681531839154649232080928787066338399915850327381614672456102374248950210248266796072457623370079195574322846594267768883120374288952014885152055438195794090975578878933873824774214e306", + "9.57524433627083921372674145950563946532138741951042299439035158875449060589509856903496678820625880407684156184675763001790613289835869844325821965070261880894138207436003366195024403902162467929095155787852409710735775347490909311196315332711680552044467458169615366116872469435840608534489425322247278926672059747911266981024366989976214521515026692183039600169984107883592297128416659318858313127e329", + "2.3372734503362369375381009524197350830316472034721759761797536237738670471009423543542251572488229045699598160834162677357730620072441755506075897500940629883044875771104686291523502165266242030847074909362622098365719455332359938746138629161304717385265309980898079489959955157644566232440805137701071311495653330606071611331941246434767948905863368638163788562679785940566685500460815077065003612487e354", + "4.2155879126937199240969909448599186868484717887298729605150033299123534992857332918168135230843738695925698383815575417820480732378749635394939513838137876524333991937836847074991505476867647762082587225838063325020413513077128321581439429001485977751765798011101092072613053687422983352140468569171564773941232256057064161142341661775359191159220450305300322654184921617310753474842253496677498824723e379", + "5.6181811613375701248970224378256740494692066242437602652469740512738297599235414593999616891945156186827736326184687322137498447792007445397397290336810468925670064733464757082986791232916898141597610692740388799796632396708149027243436859752526805112778790645096555770227809873695589969805678601106157556386974221647669590827712353133603091803570183764883405340587430017053183637835511899658145649708e405", + "5.532511069282205350923830187073466127274584467195468607886763750877294392993663821432158885753563495238131394373865428654052604326264330104646257659760161386620716716703631608643312613245804625511813964275109451513736558514977338129201153666764317441936156609643185133981728847167450887861106642311329612564652645663234240748195490808151911497393974690166034839217817023634217121406163178148652748479e432", + "4.0256666306761331240653217136731531623017017695713942917027851762705346357330788586411431378972009980532310757689380174461664677676028378924382554201434975574729861177781849023768222381429947872325368088023224591306630434887529215459580760863075907686248521168590309636468448648513752893851767315693469638980874648457114335557202115472595647478331668869318302753802858726588719006447471192697846325955e460", + "2.1644237346681663424601781769159797919834245365230735589058796985974745594485988855971413936820871935714602237643458356241187573307428309041919648027960168541647193436225977495680484218384107820095589356463058222584008532497069179993678533431131233629312850771528970443634604290143149079209513868130585713006080733488491160321145735562062411305931183571279530201672366980412430529846635995189699318073e489", + "8.5987580981195983662047247216936066485731760315371506386077056691409579856014763032619539539935299716110411688793466397984311640631361934500807639285587334983206556915704635831992012926186843826981296831658998834850783404713050829093753126189556625095994621605300047199962332098857236359801681157419606676412198783092816364336047306243999363335004760439115355072350465422891365411868472688286678516314e518", + "2.5241673163187127276134610716954724162270290228773641734420864618245211926017624829840685860130579257772126398622324109858115624706486522844752512951837805396709793171502497523431473021570806024043139443284538862368635312799539108264084028032731295487282188616820261689634926427135060887942797635147693849950058672753458576476491733064455826768562371858057444914175251596852571637211466017938478085247e549", + "5.475067911823387661325942057081957044927796274441278042805014835144678321092623034147031518807063234976073102574257079170283458172046752719724152941316842521196069804425876507927418423409523739261726681120662097159943049401039490818332686968135012747332468921142470970507219403290422458185430415836291605355383658657658638112408092789126678938878667507151950931633694006471359998448912249374833586727e580", + "8.7750549689950256776639468724574158629603320014390275681028674550826357080136422399476213432791376656222763800628593282303459051561266270006921840049305819767639184391149913915312831894296821356222752594264134130151457242713539248421883837353442181724530706933220158507240760325182068001553294949268596178418634164323874971937997072367419479635154591248667559627811893588163238012665671798461211917208e612", + "1.0392000158337773273751156576416024664653679689973856373456304843339302977923254238376497044027728158058903302390909588333829463843362779584402914847447592731182614369968957680281500946805571235013941407979569788567794900810257154433592958167545186687137810101848000107335074486050959387974516414654638879740966175786016492797845169374594168995878543584318334800124941205910589727264397237600733483158e646", + "9.0936326753636727240574546678839170665019169110943878894933093211555976995701468041449327370073681898690638466136204694745206283652338526673125958055131610409923286526192661778126811265116493171283319361595267283588121098349703951929669281966675596890266483864217591555707552765565756842701056144290075867893520379419521775913047964393758374891516340929062076304350159966063972713118995033247759001609e679", + "5.8798281636930489964162009429009257867906792508058801627042121953599912951265315933723440185825519080102988056836911095299854840387008575164090793635997912930561430335216151607097220208013034399895832350235280120270626904356196935166701773768680311063264380891331021514518757839220818506905997847228783439015252768055166165941582030353226255576433910936297965207260585437762430381969160714956727596198e714", + "2.8091881292911108404345975896815558958477835260737794579417284512413473388968057587088555041266297486841923628702282019643659456724373332519583025947015025975126598748630623031951723754960589046233996595466021913942587558326660593063197905288573353559106884645285531497626940379800500474282446929237914568534665868703742731713632349090897884403966643055728471509474896855575286123275564417626861566706e750", + "9.917129372597671132067673866739246238179742417231064062960232866725337575281938597212073697168000155027158148165861617400080837699968785505107579831803685516054837447325150388867488754170677228096524224392410232206238263933144338637103531441623303187445874039234973380151391274490746625993568552049954630793219419614845431626975962881182662815760423226111647056071831411664335144052772436215105801395e786", + "2.5869027163543111121878679987081647715187872826677398475096738640583659800068967379551376322170347537454918190603891312949716382621902484616361664158953484778255247083652726854621059785392022847887382779010079407502679229021085320675903109573769331277413372272363218896397965662581357886739691376204316908974081821980432178065394228926767529685562155837452626029223937027004015040825450642409597700449e824", + "4.9861251931207080923785686798881789193813879610842675205361210155894774686328710893906543682447029206928934967525495260314937837003448878215156341411477636831113484416124080974502217578408248150338565305116223944900839866528622960352723938548713319425798453345402992146078868053263606234074443024155243450623634720912438841022969909473424559262711669905282193529250216454066716533180418518228387188393e862", + "7.1012569014339068241101751233953234216522840280342406520909288232012799547871960723719836516359548198842749536961644100550279020276709043358260853581760590386456213180291689322352732545965831405519844109680619067101311180959399339922706596098526969148981173519865139508665631317310424178378833370605922449094745510812618563813537347841030916512147874232760564378443782164868016244561788356251308121716e901", + "7.4730215360486642135431754747074885377840195683583018254892502245011973712084221116813364423492802080799768174534590613188275471080608467087354983850284805514875889145266688973752185071777341375422809910165581997555433091939959406569831183459872344778707098094941193489061532160249775856426569696127193453339548371679229676272663084782830276508737129506676031759345288056484158647796152349867328841634e941", + "5.8109375364209112227579654658730977030869454388607076903639465992296616832002964138000947668837140543325908222688655359602408511410663722770167244801973012245657865182739637159804595049180263175014778215232564251739259624759589953677661356104554831551073263668188283861123521688445132164147762321111597028523130093864153999974376790494383016372210442340324038686843345053322425194077414241243050491297e982", + "3.33875955701899627718146291382268063073604182131575843695486667154496711979350813988644889979275310892951143249901398447859083674739840084454465850475774696325142148671937407108540250845900941142800157345665761403930889797424808979569550325271558518404559007551625637761142662107757913763221912282957681784053564387104062317729788737215450574233690655931888608424916152893688106181220341997128198692e1024", + "1.4174672877823334709610117319768830739080734407353905145632612088824955720198734996604261250019291955883620333545750761619015467840567122066622229379056280064206319780047687015558007624774062399477328822231085767309831266032616053065858739373818651687128093335640388513396191118537181280334430292439188737524362269789272308905723812818882228503013875816702686587035844437102478263525616196832018321602e1067", + "4.4466189016791091516801723880812533528438597080549410911235655611382010503145789286158745555771483577943662768773465284793798720178177605712848440200402906836390133865748188969184005230383247111166918721449908133920663776952786683837038180436264738937354101153867171804315769471050303182129269442292354388037298125177941217926845803005587166270803697433886463469168814941555804311717400657004050157245e1110", + }}; + + T eg = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + const T x = eg + k; + T val = boost::multiprecision::cosh(x * x); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = boost::multiprecision::cosh(-x * x); + e = relative_error(val, T(data[k])); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 2000); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_cpp_dec_float_conv.cpp b/test/test_cpp_dec_float_conv.cpp new file mode 100644 index 00000000..d1c73064 --- /dev/null +++ b/test/test_cpp_dec_float_conv.cpp @@ -0,0 +1,42 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#include + +int main() +{ + using namespace boost::multiprecision; + // + // Test interconversions between different precisions: + // + cpp_dec_float_50 f1(2); + cpp_dec_float_100 f2(3); + + cpp_dec_float_100 f3 = f1; // implicit conversion OK + BOOST_TEST(f3 == 2); + cpp_dec_float_50 f4(f2); // explicit conversion OK + BOOST_TEST(f4 == 3); + + f2 = f1; + BOOST_TEST(f2 == 2); + f2 = 4; + f1 = static_cast(f2); + BOOST_TEST(f1 == 4); + + + return boost::report_errors(); +} + + + diff --git a/test/test_cpp_int.cpp b/test/test_cpp_int.cpp new file mode 100644 index 00000000..4b7b74f0 --- /dev/null +++ b/test/test_cpp_int.cpp @@ -0,0 +1,381 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include "test.hpp" + +template +T generate_random(unsigned bits_wanted) +{ + static boost::random::mt19937 gen; + typedef boost::random::mt19937::result_type random_type; + + T max_val; + unsigned digits; + if(std::numeric_limits::is_bounded && (bits_wanted == std::numeric_limits::digits)) + { + max_val = (std::numeric_limits::max)(); + digits = std::numeric_limits::digits; + } + else + { + max_val = T(1) << bits_wanted; + digits = bits_wanted; + } + + unsigned bits_per_r_val = std::numeric_limits::digits - 1; + while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; + + unsigned terms_needed = digits / bits_per_r_val + 1; + + T val = 0; + for(unsigned i = 0; i < terms_needed; ++i) + { + val *= (gen.max)(); + val += gen(); + } + val %= max_val; + return val; +} + +template +struct is_checked_cpp_int : public boost::mpl::false_ {}; +template +struct is_checked_cpp_int, ET> > : public boost::mpl::true_ {}; + +template +void test() +{ + using namespace boost::multiprecision; + typedef Number test_type; + typedef typename test_type::backend_type::checked_type checked; + + unsigned last_error_count = 0; + boost::timer tim; + + BOOST_CHECK_EQUAL(Number(), 0); + + for(int i = 0; i < 10000; ++i) + { + mpz_int a = generate_random(1000); + mpz_int b = generate_random(512); + mpz_int c = generate_random(256); + mpz_int d = generate_random(32); + + int si = d.convert_to(); + unsigned ui = si; + + test_type a1 = static_cast(a.str()); + test_type b1 = static_cast(b.str()); + test_type c1 = static_cast(c.str()); + test_type d1 = static_cast(d.str()); + + BOOST_CHECK_EQUAL(a.str(), a1.str()); + BOOST_CHECK_EQUAL(b.str(), b1.str()); + BOOST_CHECK_EQUAL(c.str(), c1.str()); + BOOST_CHECK_EQUAL(d.str(), d1.str()); + BOOST_CHECK_EQUAL(mpz_int(a+b).str(), test_type(a1 + b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)+=b).str(), (test_type(a1) += b1).str()); + BOOST_CHECK_EQUAL((mpz_int(b)+=a).str(), (test_type(b1) += a1).str()); + BOOST_CHECK_EQUAL(mpz_int(a-b).str(), test_type(a1 - b1).str()); + BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)+b).str(), test_type(test_type(-a1) + b1).str()); + BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)-b).str(), test_type(test_type(-a1) - b1).str()); + BOOST_CHECK_EQUAL(mpz_int(c * d).str(), test_type(c1 * d1).str()); + BOOST_CHECK_EQUAL((mpz_int(c)*=d).str(), (test_type(c1) *= d1).str()); + BOOST_CHECK_EQUAL((mpz_int(d)*=c).str(), (test_type(d1) *= c1).str()); + BOOST_CHECK_EQUAL(mpz_int(c * -d).str(), test_type(c1 * -d1).str()); + BOOST_CHECK_EQUAL(mpz_int(-c * d).str(), test_type(-c1 * d1).str()); + BOOST_CHECK_EQUAL((mpz_int(c)*=-d).str(), (test_type(c1) *= -d1).str()); + BOOST_CHECK_EQUAL((mpz_int(-d)*=c).str(), (test_type(-d1) *= c1).str()); + BOOST_CHECK_EQUAL(mpz_int(b * c).str(), test_type(b1 * c1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / b).str(), test_type(a1 / b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)/=b).str(), (test_type(a1) /= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / -b).str(), test_type(a1 / -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a / b).str(), test_type(-a1 / b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)/=-b).str(), (test_type(a1) /= -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)/=b).str(), (test_type(-a1) /= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / d).str(), test_type(a1 / d1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % b).str(), test_type(a1 % b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=b).str(), (test_type(a1) %= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % -b).str(), test_type(a1 % -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=-b).str(), (test_type(a1) %= -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a % b).str(), test_type(-a1 % b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)%=b).str(), (test_type(-a1) %= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % d).str(), test_type(a1 % d1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=d).str(), (test_type(a1) %= d1).str()); + // bitwise ops: + BOOST_CHECK_EQUAL(mpz_int(a|b).str(), test_type(a1 | b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)|=b).str(), (test_type(a1) |= b1).str()); + if(!is_checked_cpp_int::value) + { + BOOST_CHECK_EQUAL(mpz_int(-a|b).str(), test_type(-a1 | b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)|=b).str(), (test_type(-a1) |= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a|-b).str(), test_type(a1 | -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)|=-b).str(), (test_type(a1) |= -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a|-b).str(), test_type(-a1 | -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)|=-b).str(), (test_type(-a1) |= -b1).str()); + } + BOOST_CHECK_EQUAL(mpz_int(a&b).str(), test_type(a1 & b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)&=b).str(), (test_type(a1) &= b1).str()); + if(!is_checked_cpp_int::value) + { + BOOST_CHECK_EQUAL(mpz_int(-a&b).str(), test_type(-a1 & b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)&=b).str(), (test_type(-a1) &= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a&-b).str(), test_type(a1 & -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)&=-b).str(), (test_type(a1) &= -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a&-b).str(), test_type(-a1 & -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)&=-b).str(), (test_type(-a1) &= -b1).str()); + } + BOOST_CHECK_EQUAL(mpz_int(a^b).str(), test_type(a1 ^ b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)^=b).str(), (test_type(a1) ^= b1).str()); + if(!is_checked_cpp_int::value) + { + BOOST_CHECK_EQUAL(mpz_int(-a^b).str(), test_type(-a1 ^ b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)^=b).str(), (test_type(-a1) ^= b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a^-b).str(), test_type(a1 ^ -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)^=-b).str(), (test_type(a1) ^= -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a^-b).str(), test_type(-a1 ^ -b1).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)^=-b).str(), (test_type(-a1) ^= -b1).str()); + } + // Shift ops: + for(unsigned i = 0; i < 128; ++i) + { + if(!std::numeric_limits::is_bounded) + { + BOOST_CHECK_EQUAL(mpz_int(a << i).str(), test_type(a1 << i).str()); + } + BOOST_CHECK_EQUAL(mpz_int(a >> i).str(), test_type(a1 >> i).str()); + } + // Now check operations involving signed integers: + BOOST_CHECK_EQUAL(mpz_int(a + si).str(), test_type(a1 + si).str()); + BOOST_CHECK_EQUAL(mpz_int(a + -si).str(), test_type(a1 + -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a + si).str(), test_type(-a1 + si).str()); + BOOST_CHECK_EQUAL(mpz_int(si + a).str(), test_type(si + a1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)+=si).str(), (test_type(a1) += si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)+=-si).str(), (test_type(a1) += -si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)+=si).str(), (test_type(-a1) += si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)+=-si).str(), (test_type(-a1) += -si).str()); + BOOST_CHECK_EQUAL(mpz_int(a - si).str(), test_type(a1 - si).str()); + BOOST_CHECK_EQUAL(mpz_int(a - -si).str(), test_type(a1 - -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a - si).str(), test_type(-a1 - si).str()); + BOOST_CHECK_EQUAL(mpz_int(si - a).str(), test_type(si - a1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)-=si).str(), (test_type(a1) -= si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)-=-si).str(), (test_type(a1) -= -si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)-=si).str(), (test_type(-a1) -= si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)-=-si).str(), (test_type(-a1) -= -si).str()); + BOOST_CHECK_EQUAL(mpz_int(b * si).str(), test_type(b1 * si).str()); + BOOST_CHECK_EQUAL(mpz_int(b * -si).str(), test_type(b1 * -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-b * si).str(), test_type(-b1 * si).str()); + BOOST_CHECK_EQUAL(mpz_int(si * b).str(), test_type(si * b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)*=si).str(), (test_type(a1) *= si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)*=-si).str(), (test_type(a1) *= -si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)*=si).str(), (test_type(-a1) *= si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)*=-si).str(), (test_type(-a1) *= -si).str()); + BOOST_CHECK_EQUAL(mpz_int(a / si).str(), test_type(a1 / si).str()); + BOOST_CHECK_EQUAL(mpz_int(a / -si).str(), test_type(a1 / -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a / si).str(), test_type(-a1 / si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)/=si).str(), (test_type(a1) /= si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)/=-si).str(), (test_type(a1) /= -si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)/=si).str(), (test_type(-a1) /= si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)/=-si).str(), (test_type(-a1) /= -si).str()); + BOOST_CHECK_EQUAL(mpz_int(a % si).str(), test_type(a1 % si).str()); + BOOST_CHECK_EQUAL(mpz_int(a % -si).str(), test_type(a1 % -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a % si).str(), test_type(-a1 % si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=si).str(), (test_type(a1) %= si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=-si).str(), (test_type(a1) %= -si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)%=si).str(), (test_type(-a1) %= si).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)%=-si).str(), (test_type(-a1) %= -si).str()); + if((si > 0) || !is_checked_cpp_int::value) + { + BOOST_CHECK_EQUAL(mpz_int(a|si).str(), test_type(a1 | si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)|=si).str(), (test_type(a1) |= si).str()); + BOOST_CHECK_EQUAL(mpz_int(a&si).str(), test_type(a1 & si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)&=si).str(), (test_type(a1) &= si).str()); + BOOST_CHECK_EQUAL(mpz_int(a^si).str(), test_type(a1 ^ si).str()); + BOOST_CHECK_EQUAL((mpz_int(a)^=si).str(), (test_type(a1) ^= si).str()); + BOOST_CHECK_EQUAL(mpz_int(si|a).str(), test_type(si|a1).str()); + BOOST_CHECK_EQUAL(mpz_int(si&a).str(), test_type(si&a1).str()); + BOOST_CHECK_EQUAL(mpz_int(si^a).str(), test_type(si^a1).str()); + } + BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), test_type(gcd(a1, b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), test_type(lcm(c1, d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(-a, b)).str(), test_type(gcd(-a1, b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(-c, d)).str(), test_type(lcm(-c1, d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(-a, -b)).str(), test_type(gcd(-a1, -b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(-c, -d)).str(), test_type(lcm(-c1, -d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(a, -b)).str(), test_type(gcd(a1, -b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(c, -d)).str(), test_type(lcm(c1, -d1)).str()); + // Now check operations involving unsigned integers: + BOOST_CHECK_EQUAL(mpz_int(a + ui).str(), test_type(a1 + ui).str()); + BOOST_CHECK_EQUAL(mpz_int(-a + ui).str(), test_type(-a1 + ui).str()); + BOOST_CHECK_EQUAL(mpz_int(ui + a).str(), test_type(ui + a1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)+=ui).str(), (test_type(a1) += ui).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)+=ui).str(), (test_type(-a1) += ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a - ui).str(), test_type(a1 - ui).str()); + BOOST_CHECK_EQUAL(mpz_int(-a - ui).str(), test_type(-a1 - ui).str()); + BOOST_CHECK_EQUAL(mpz_int(ui - a).str(), test_type(ui - a1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)-=ui).str(), (test_type(a1) -= ui).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)-=ui).str(), (test_type(-a1) -= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(b * ui).str(), test_type(b1 * ui).str()); + BOOST_CHECK_EQUAL(mpz_int(-b * ui).str(), test_type(-b1 * ui).str()); + BOOST_CHECK_EQUAL(mpz_int(ui * b).str(), test_type(ui * b1).str()); + BOOST_CHECK_EQUAL((mpz_int(a)*=ui).str(), (test_type(a1) *= ui).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)*=ui).str(), (test_type(-a1) *= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a / ui).str(), test_type(a1 / ui).str()); + BOOST_CHECK_EQUAL(mpz_int(-a / ui).str(), test_type(-a1 / ui).str()); + BOOST_CHECK_EQUAL((mpz_int(a)/=ui).str(), (test_type(a1) /= ui).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)/=ui).str(), (test_type(-a1) /= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a % ui).str(), test_type(a1 % ui).str()); + BOOST_CHECK_EQUAL(mpz_int(-a % ui).str(), test_type(-a1 % ui).str()); + BOOST_CHECK_EQUAL((mpz_int(a)%=ui).str(), (test_type(a1) %= ui).str()); + BOOST_CHECK_EQUAL((mpz_int(-a)%=ui).str(), (test_type(-a1) %= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a|ui).str(), test_type(a1 | ui).str()); + BOOST_CHECK_EQUAL((mpz_int(a)|=ui).str(), (test_type(a1) |= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a&ui).str(), test_type(a1 & ui).str()); + BOOST_CHECK_EQUAL((mpz_int(a)&=ui).str(), (test_type(a1) &= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(a^ui).str(), test_type(a1 ^ ui).str()); + BOOST_CHECK_EQUAL((mpz_int(a)^=ui).str(), (test_type(a1) ^= ui).str()); + BOOST_CHECK_EQUAL(mpz_int(ui|a).str(), test_type(ui|a1).str()); + BOOST_CHECK_EQUAL(mpz_int(ui&a).str(), test_type(ui&a1).str()); + BOOST_CHECK_EQUAL(mpz_int(ui^a).str(), test_type(ui^a1).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), test_type(gcd(a1, b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), test_type(lcm(c1, d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(-a, b)).str(), test_type(gcd(-a1, b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(-c, d)).str(), test_type(lcm(-c1, d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(-a, -b)).str(), test_type(gcd(-a1, -b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(-c, -d)).str(), test_type(lcm(-c1, -d1)).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(a, -b)).str(), test_type(gcd(a1, -b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(c, -d)).str(), test_type(lcm(c1, -d1)).str()); + + if(std::numeric_limits::is_modulo && checked::value) + { + static mpz_int m = mpz_int(1) << std::numeric_limits::digits; + mpz_int t(a); + test_type t1(a1); + for(unsigned i = 0; i < 10; ++i) + { + t *= a; + t %= m; + t += a; + t %= m; + t1 *= a1; + t1 += a1; + } + BOOST_CHECK_EQUAL(t.str(), t1.str()); + } + + // + // Now integer functions: + // + mpz_int z1, z2; + test_type t1, t2; + divide_qr(a, b, z1, z2); + divide_qr(a1, b1, t1, t2); + BOOST_CHECK_EQUAL(z1.str(), t1.str()); + BOOST_CHECK_EQUAL(z2.str(), t2.str()); + BOOST_CHECK_EQUAL(integer_modulus(a, si), integer_modulus(a1, si)); + BOOST_CHECK_EQUAL(lsb(a), lsb(a1)); + + for(unsigned i = 0; i < 1000; i += 13) + { + BOOST_CHECK_EQUAL(bit_test(a, i), bit_test(a1, i)); + } + if(!std::numeric_limits::is_modulo) + { + // We have to take care that our powers don't grow too large, otherwise this takes "forever", + // also don't test for modulo types, as these may give a diffferent result from arbitrary + // precision types: + BOOST_CHECK_EQUAL(mpz_int(pow(d, ui % 19)).str(), test_type(pow(d1, ui % 19)).str()); + BOOST_CHECK_EQUAL(mpz_int(powm(a, b, c)).str(), test_type(powm(a1, b1, c1)).str()); + BOOST_CHECK_EQUAL(mpz_int(powm(a, b, ui)).str(), test_type(powm(a1, b1, ui)).str()); + BOOST_CHECK_EQUAL(mpz_int(powm(a, ui, c)).str(), test_type(powm(a1, ui, c1)).str()); + } + + if(last_error_count != (unsigned)boost::detail::test_errors()) + { + last_error_count = boost::detail::test_errors(); + std::cout << std::hex << std::showbase; + + std::cout << "a = " << a << std::endl; + std::cout << "a1 = " << a1 << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "b1 = " << b1 << std::endl; + std::cout << "c = " << c << std::endl; + std::cout << "c1 = " << c1 << std::endl; + std::cout << "d = " << d << std::endl; + std::cout << "d1 = " << d1 << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a1 + b1 = " << a1+b1 << std::endl; + std::cout << std::dec; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a1 - b1 = " << a1-b1 << std::endl; + std::cout << "-a + b = " << mpz_int(-a)+b << std::endl; + std::cout << "-a1 + b1 = " << test_type(-a1)+b1 << std::endl; + std::cout << "-a - b = " << mpz_int(-a)-b << std::endl; + std::cout << "-a1 - b1 = " << test_type(-a1)-b1 << std::endl; + std::cout << "c*d = " << c*d << std::endl; + std::cout << "c1*d1 = " << c1*d1 << std::endl; + std::cout << "b*c = " << b*c << std::endl; + std::cout << "b1*c1 = " << b1*c1 << std::endl; + std::cout << "a/b = " << a/b << std::endl; + std::cout << "a1/b1 = " << a1/b1 << std::endl; + std::cout << "a/d = " << a/d << std::endl; + std::cout << "a1/d1 = " << a1/d1 << std::endl; + std::cout << "a%b = " << a%b << std::endl; + std::cout << "a1%b1 = " << a1%b1 << std::endl; + std::cout << "a%d = " << a%d << std::endl; + std::cout << "a1%d1 = " << a1%d1 << std::endl; + } + + // + // Check to see if test is taking too long. + // Tests run on the compiler farm time out after 300 seconds, + // so don't get too close to that: + // + if(tim.elapsed() > 200) + { + std::cout << "Timeout reached, aborting tests now....\n"; + break; + } + + } +} + +#if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) +#define TEST1 +#define TEST2 +#define TEST3 +#endif + +int main() +{ + using namespace boost::multiprecision; +#ifdef TEST1 + test(); +#endif +#ifdef TEST2 + test > >(); +#endif +#ifdef TEST3 + // Unchecked test verifies modulo arithmetic: + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_cpp_int_conv.cpp b/test/test_cpp_int_conv.cpp new file mode 100644 index 00000000..d5a8e2a3 --- /dev/null +++ b/test/test_cpp_int_conv.cpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#include + +int main() +{ + using namespace boost::multiprecision; + // + // Test interconversions between different precisions: + // + cpp_int i1(2); + int128_t i2(3); + int256_t i3(4); + number > i4(5); + + i1 = i3; + BOOST_TEST(i1 == 4); + i1 = i4; + BOOST_TEST(i1 == 5); + + i3 = -1234567; + i4 = -5677334; + i1 = i3; + BOOST_TEST(i1 == -1234567); + i1 = i4; + BOOST_TEST(i1 == -5677334); + + i3 = i2; + BOOST_TEST(i3 == 3); + + i3 = -1234567; + + uint128_t i5(i3); + BOOST_TEST(i5 == -1234567); + + int128_t i6(i4); + BOOST_TEST(i6 == -5677334); + + number, et_off> i7(i3); + BOOST_TEST(i7 == -1234567); + + int256_t i8(i6); + BOOST_TEST(i8 == -5677334); + + i7.assign(4.0); + BOOST_TEST(i7 == 4); + + number, et_off> i9(-5677334); + i7 = i9; + BOOST_TEST(i7 == -5677334); + i7 = number, et_off>(i9); + BOOST_TEST(i7 == -5677334); + + i9 = static_cast, et_off> >(i7); + BOOST_TEST(i9 == -5677334); + + ++i9; + i7 = i9; + BOOST_TEST(i7 == 1 - 5677334); + + return boost::report_errors(); +} + + + diff --git a/test/test_exp.cpp b/test/test_exp.cpp new file mode 100644 index 00000000..f9ca1cb1 --- /dev/null +++ b/test/test_exp.cpp @@ -0,0 +1,201 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "9.47747587596218770242116751705184563668845029215054154915126374673142219159548534317576897266130328412495991561490384353e76", + "8.98225489794452370997623936390755615068333094834545092387689795875746440121970819499035111276893290879203289092353747850e153", + "8.51291041070124257524798251795398355552294928156627848633073113916721592074889256105483993631579761345100284245144410506e230", + "8.06809030516483860484254925989129017112482132468761563276276594763374886826841745433660192438855214332469192411759402790e307", + "7.64651312322841630493169711336894888932951818957138997327518186691187347879142222644283389432604713409023263917264358401e384", + "7.24696436606255985380192585665173794455118215150711210905481870053193336336731228464367470327868286988180495111406609690e461", + "6.86829299533155197480610865771404565313986987801060270120621935139741577246731459024227828759564450034267891072352816870e538", + "6.50940811722948585242669672360741252715012399316164518226061001845519670701239429603657927628755169479689062519606799624e615", + "6.16927583978348964454665652571294215251327375137123272041877979478545511090085756858225302357977159539777447847855503405e692", + "5.84691629437043896753869572004324228849833391140408095171257918435296982661233664069534601413835876272500275725690968474e769", + "5.54140081286660645835370762406928689330724181979654545550204201113926269281603301564114980528619942840737770415885783439e846", + "5.25184925229805200184933663459660562493261505058724212670923083643709964294855282715531768162298567379648573804433968486e923", + "4.97742745928448409225535325233998957076879979440190164347796593390995994951755710667491911026476108957070504003155645761e1000", + "4.71734486697204622371883518659702954552385115723942808636490157561056417525827884479573988899517566587636669779645610803e1077", + "4.47085221753216236037602345430121605512330975424643767098987010800161616413051148037751552110081034066081309007796182114e1154", + "4.23723940366531198300986713567588008777043812458400705569721660157434941774066620870256745107265536124077734836797938268e1231", + "4.01583342289144005397455901781647949754375366066998182220342540048111140676724909947493787596336610499122085983712119281e1308", + "3.80599643873362813900306284477369187319506389058898599816705625750135796510808933786432614186155972485637939057212164098e1385", + "3.60712394320959592074309301816510372687695286650188776957291994751966018917404878612237961367128638199290387601511358836e1462", + "3.41864301533745457066062991907289263038319874930395315315257927161138360206596116102724713069518697248463965164712972907e1539", + "3.24001067063873569456703204286462007769933831045558617578289414699244767403736057931834775727420762410328297596596814910e1616", + "3.07071229688386868087623659761166306563170839771162347830514606977592027644137144160294469813988158463967740978461420862e1693", + "2.91026017157373047094077218552378456052150304677863670611408570458991015300131731261787644801415538043027268185097710615e1770", + "2.75819205688636078700279174380111581147323147951670302427494196210176478494486073721584055059489736040565979466551070179e1847", + "2.61406986804110104534167739704643351039975992759905579635058824027507742375380077276380178376470686987855503581867681046e1924", + "2.47747841124391945459619002346303925269640785743990333362087223895627681769816204236257960940497519376881830373722711456e2001", + "2.34802418757813746316913800667907927718925648696508255347624141597281474683823345136640610924639820192825966082309575303e2078", + "2.22533425939475124828943430510333464605535146852848680647615867629953075390889821397228584866395924176189346073006180260e2155", + "2.10905517593659363154553947631071808925462553114068144748077359132255993441363479041540672158497404660986163617828972963e2232", + "1.99885195510122536266653916064141606295420554580140619900425370702471778604391774578696867899999534265169574306808906810e2309", + "1.89440711840917173277691572886942144916664047407963356271198286654087884646102070148271284410118233470318337745546895603e2386", + "1.79541977639739687088375911648976940254141946934175300605485966288703931992861387257771264702798405630917098672594899744e2463", + "1.70160476180317540861346545791118106171203487587101437710693054174454895160403997508137760007058856854991413121389834429e2540", + "1.61269180804119796097157014527479883521656118500417752963675677684343588976915851637637232001139108420659882326614772004e2617", + "1.52842477060722969066998464046690349841548269556677423378408183476489015878816585045578141383463708674469365281537792914e2694", + "1.44856088916530600122626623629347336702026699647293500058111037526381692645547938577338582002157148103479049071921438452e2771", + "1.37287008819265239873777879432333192404914357037749380145412895230166352318128978403808382142784030558123748263528360645e2848", + "1.30113431416759441771790128053911040907207490879890145597562380328956450092799014856149474809345424672958343296615764490e2925", + "1.23314690739099822369963411660419632130352733806319401863570442920347696015409870236230656305563674376063778482449716744e3002", + "1.16871200663155636468514484039368694043851858077879103221831997264419096417014996945143145495038265243932745953706526253e3079", + "1.10764398487979357804590117089134596938734185016144401218934115168561552640448889215089150481162977776214124397487013110e3156", + "1.04976691458528698318220729857405616816444374000182094405930946710168752954926612218474430081526312018810817657409158490e3233", + "9.94914060836531582868347569174220216007647278536863127198023584205669825317884219144692385409156165042162234017403353704e3309", + "9.42927401023380446961314339401657458785389811652244742482194123119943160577946366372207045050095290781679375214307398844e3386", + "8.93657169598281164656322298275337750103095739790107943666668184304335665562867744740310577868880098719252549186849812451e3463", + "8.46961426624835911826517103631490619655296714141872141145089865045804196205328364155921945616925875458926717336478525196e3540", + "8.02705648870740089929294815816002943860908317454595055392168733404583122074223427054310572378841634984243492063192095337e3617", + "7.60762342267101369970765191988545810374824800500875923752736467467657167098026707905341603949108433696304383346239333297e3694", + "7.21010674617694221027190468649359000420209460539838589305387835463807416706224777302997789297329446308541513638035437482e3771", + "6.83336127500041943234365059231968669406267422759442985746460610830503287734479988530512309065240678799786759250323660701e3848", + }}; + + T pi = static_cast("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = exp(sqrt((pi * (100 * k)) * (100 * k))); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = exp(-sqrt((pi * (100 * k)) * (100 * k))); + e = relative_error(val, T(1/T(data[k]))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 5000); + + static const boost::array, 10> exact_data = + {{ + {{ std::ldexp(1.0, -50), static_cast("1.00000000000000088817841970012562676935794497867573073630970950828771105957980924149923657574337470594698012676100224953") }}, + {{ std::ldexp(1.0, -20), static_cast("1.00000095367477115374544678824955687428365188553281789775169686343569285229334215539516690752571791280462887427635269562") }}, + {{ std::ldexp(1.0, -10), static_cast("1.00097703949241653524284529261160650646585162918174419940186408264916250428896869173656853690882467186075613761065459261") }}, + {{ 0.25, static_cast("1.28402541668774148407342056806243645833628086528146308921750729687220776586723800275330641943955356890166283174967968731") }}, + {{ 0.5, static_cast("1.64872127070012814684865078781416357165377610071014801157507931164066102119421560863277652005636664300286663775630779700") }}, + {{ 0.75, static_cast("2.11700001661267466854536981983709561013449158470240342177913303081098453336401282000279156026661579821888590471901551426") }}, + {{ 10, static_cast("22026.4657948067165169579006452842443663535126185567810742354263552252028185707925751991209681645258954515555010924578367") }}, + {{ 10.5, static_cast("36315.5026742466377389120269013166179689315579671275857607480190550842856628099187749764427758174866310742771977376827512") }}, + {{ 25, static_cast("7.20048993373858725241613514661261579152235338133952787362213864472320593107782569745000325654258093194727871848859163684e10") }}, + {{ 31.25, static_cast("3.72994612957188849046766396046821396700589012875701157893019118883826370993674081486706667149871508642909416337810227575e13") }}, + }}; + + max_err = 0; + for(unsigned k = 0; k < exact_data.size(); k++) + { + T val = exp(exact_data[k][0]); + T e = relative_error(val, exact_data[k][1]); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = exp(-exact_data[k][0]); + e = relative_error(val, T(1/exact_data[k][1])); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 10); + + BOOST_TEST(exp(T(0)) == 1); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_fixed_int.cpp b/test/test_fixed_int.cpp new file mode 100644 index 00000000..87a72399 --- /dev/null +++ b/test/test_fixed_int.cpp @@ -0,0 +1,165 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include "test.hpp" + +template +T generate_random(unsigned bits_wanted) +{ + static boost::random::mt19937 gen; + typedef boost::random::mt19937::result_type random_type; + + T max_val; + unsigned digits; + if(std::numeric_limits::is_bounded && (bits_wanted == std::numeric_limits::digits)) + { + max_val = (std::numeric_limits::max)(); + digits = std::numeric_limits::digits; + } + else + { + max_val = T(1) << bits_wanted; + digits = bits_wanted; + } + + unsigned bits_per_r_val = std::numeric_limits::digits - 1; + while((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; + + unsigned terms_needed = digits / bits_per_r_val + 1; + + T val = 0; + for(unsigned i = 0; i < terms_needed; ++i) + { + val *= (gen.max)(); + val += gen(); + } + val %= max_val; + return val; +} + +int main() +{ + using namespace boost::multiprecision; + typedef number > packed_type; + unsigned last_error_count = 0; + for(int i = 0; i < 1000; ++i) + { + mpz_int a = generate_random(1000); + mpz_int b = generate_random(512); + mpz_int c = generate_random(256); + mpz_int d = generate_random(32); + + int si = d.convert_to(); + + packed_type a1 = a.str(); + packed_type b1 = b.str(); + packed_type c1 = c.str(); + packed_type d1 = d.str(); + + BOOST_CHECK_EQUAL(a.str(), a1.str()); + BOOST_CHECK_EQUAL(b.str(), b1.str()); + BOOST_CHECK_EQUAL(c.str(), c1.str()); + BOOST_CHECK_EQUAL(d.str(), d1.str()); + BOOST_CHECK_EQUAL(mpz_int(a+b).str(), packed_type(a1 + b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a-b).str(), packed_type(a1 - b1).str()); + BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)+b).str(), packed_type(packed_type(-a1) + b1).str()); + BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a)-b).str(), packed_type(packed_type(-a1) - b1).str()); + BOOST_CHECK_EQUAL(mpz_int(c * d).str(), packed_type(c1 * d1).str()); + BOOST_CHECK_EQUAL(mpz_int(c * -d).str(), packed_type(c1 * -d1).str()); + BOOST_CHECK_EQUAL(mpz_int(-c * d).str(), packed_type(-c1 * d1).str()); + BOOST_CHECK_EQUAL(mpz_int(b * c).str(), packed_type(b1 * c1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / b).str(), packed_type(a1 / b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / -b).str(), packed_type(a1 / -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a / b).str(), packed_type(-a1 / b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / d).str(), packed_type(a1 / d1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % b).str(), packed_type(a1 % b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % -b).str(), packed_type(a1 % -b1).str()); + BOOST_CHECK_EQUAL(mpz_int(-a % b).str(), packed_type(-a1 % b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a % d).str(), packed_type(a1 % d1).str()); + // bitwise ops: + BOOST_CHECK_EQUAL(mpz_int(a|b).str(), packed_type(a1 | b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a&b).str(), packed_type(a1 & b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a^b).str(), packed_type(a1 ^ b1).str()); + // Now check operations involving integers: + BOOST_CHECK_EQUAL(mpz_int(a + si).str(), packed_type(a1 + si).str()); + BOOST_CHECK_EQUAL(mpz_int(a + -si).str(), packed_type(a1 + -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a + si).str(), packed_type(-a1 + si).str()); + BOOST_CHECK_EQUAL(mpz_int(si + a).str(), packed_type(si + a1).str()); + BOOST_CHECK_EQUAL(mpz_int(a - si).str(), packed_type(a1 - si).str()); + BOOST_CHECK_EQUAL(mpz_int(a - -si).str(), packed_type(a1 - -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a - si).str(), packed_type(-a1 - si).str()); + BOOST_CHECK_EQUAL(mpz_int(si - a).str(), packed_type(si - a1).str()); + BOOST_CHECK_EQUAL(mpz_int(b * si).str(), packed_type(b1 * si).str()); + BOOST_CHECK_EQUAL(mpz_int(b * -si).str(), packed_type(b1 * -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-b * si).str(), packed_type(-b1 * si).str()); + BOOST_CHECK_EQUAL(mpz_int(si * b).str(), packed_type(si * b1).str()); + BOOST_CHECK_EQUAL(mpz_int(a / si).str(), packed_type(a1 / si).str()); + BOOST_CHECK_EQUAL(mpz_int(a / -si).str(), packed_type(a1 / -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a / si).str(), packed_type(-a1 / si).str()); + BOOST_CHECK_EQUAL(mpz_int(a % si).str(), packed_type(a1 % si).str()); + BOOST_CHECK_EQUAL(mpz_int(a % -si).str(), packed_type(a1 % -si).str()); + BOOST_CHECK_EQUAL(mpz_int(-a % si).str(), packed_type(-a1 % si).str()); + BOOST_CHECK_EQUAL(mpz_int(a|si).str(), packed_type(a1 | si).str()); + BOOST_CHECK_EQUAL(mpz_int(a&si).str(), packed_type(a1 & si).str()); + BOOST_CHECK_EQUAL(mpz_int(a^si).str(), packed_type(a1 ^ si).str()); + BOOST_CHECK_EQUAL(mpz_int(si|a).str(), packed_type(si|a1).str()); + BOOST_CHECK_EQUAL(mpz_int(si&a).str(), packed_type(si&a1).str()); + BOOST_CHECK_EQUAL(mpz_int(si^a).str(), packed_type(si^a1).str()); + BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), packed_type(gcd(a1, b1)).str()); + BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), packed_type(lcm(c1, d1)).str()); + + if(last_error_count != boost::detail::test_errors()) + { + last_error_count = boost::detail::test_errors(); + std::cout << std::hex << std::showbase; + + std::cout << "a = " << a << std::endl; + std::cout << "a1 = " << a1 << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "b1 = " << b1 << std::endl; + std::cout << "c = " << c << std::endl; + std::cout << "c1 = " << c1 << std::endl; + std::cout << "d = " << d << std::endl; + std::cout << "d1 = " << d1 << std::endl; + std::cout << "a + b = " << a+b << std::endl; + std::cout << "a1 + b1 = " << a1+b1 << std::endl; + std::cout << std::dec; + std::cout << "a - b = " << a-b << std::endl; + std::cout << "a1 - b1 = " << a1-b1 << std::endl; + std::cout << "-a + b = " << mpz_int(-a)+b << std::endl; + std::cout << "-a1 + b1 = " << packed_type(-a1)+b1 << std::endl; + std::cout << "-a - b = " << mpz_int(-a)-b << std::endl; + std::cout << "-a1 - b1 = " << packed_type(-a1)-b1 << std::endl; + std::cout << "c*d = " << c*d << std::endl; + std::cout << "c1*d1 = " << c1*d1 << std::endl; + std::cout << "b*c = " << b*c << std::endl; + std::cout << "b1*c1 = " << b1*c1 << std::endl; + std::cout << "a/b = " << a/b << std::endl; + std::cout << "a1/b1 = " << a1/b1 << std::endl; + std::cout << "a/d = " << a/d << std::endl; + std::cout << "a1/d1 = " << a1/d1 << std::endl; + std::cout << "a%b = " << a%b << std::endl; + std::cout << "a1%b1 = " << a1%b1 << std::endl; + std::cout << "a%d = " << a%d << std::endl; + std::cout << "a1%d1 = " << a1%d1 << std::endl; + } + } + return boost::report_errors(); +} + + + diff --git a/test/test_float_io.cpp b/test/test_float_io.cpp new file mode 100644 index 00000000..ad66dac3 --- /dev/null +++ b/test/test_float_io.cpp @@ -0,0 +1,310 @@ +// Copyright John Maddock 2011. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#if !defined(TEST_MPF_50) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50) +# define TEST_MPF_50 +# define TEST_CPP_DEC_FLOAT +# define TEST_MPFR_50 + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#include +#include +#include "test.hpp" +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable:4127) +#endif + +#if defined(TEST_MPF_50) +template +bool is_mpf(const boost::multiprecision::number, ET>&) +{ return true; } +#endif +template +bool is_mpf(const T&) { return false; } + +bool is_bankers_rounding_error(const std::string& s, const char* expect) +{ + // This check isn't foolproof: that would require *much* more sophisticated code!!! + std::string::size_type l = std::strlen(expect); + if(l != s.size()) + return false; + std::string::size_type len = s.find('e'); + if(len == std::string::npos) + len = l - 1; + else + --len; + if(s.compare(0, len, expect, len)) + return false; + if(s[len] != expect[len] + 1) + return false; + return true; +} + +void print_flags(std::ios_base::fmtflags f) +{ + std::cout << "Formatting flags were: "; + if(f & std::ios_base::scientific) + std::cout << "scientific "; + if(f & std::ios_base::fixed) + std::cout << "fixed "; + if(f & std::ios_base::showpoint) + std::cout << "showpoint "; + if(f & std::ios_base::showpos) + std::cout << "showpos "; + std::cout << std::endl; +} + + +template +void test() +{ + typedef T mp_t; + boost::array f = + {{ + std::ios_base::fmtflags(0), std::ios_base::showpoint, std::ios_base::showpos, std::ios_base::scientific, std::ios_base::scientific|std::ios_base::showpos, + std::ios_base::scientific|std::ios_base::showpoint, std::ios_base::fixed, std::ios_base::fixed|std::ios_base::showpoint, + std::ios_base::fixed|std::ios_base::showpos + }}; + + boost::array, 40> string_data = {{ +#include "libs/multiprecision/test/string_data.ipp" + }}; + + double num = 123456789.0; + double denom = 1; + double val = num; + for(unsigned j = 0; j < 40; ++j) + { + unsigned col = 0; + for(unsigned prec = 1; prec < 14; ++prec) + { + for(unsigned i = 0; i < f.size(); ++i, ++col) + { + std::stringstream ss; + ss.precision(prec); + ss.flags(f[i]); + ss << mp_t(val); + const char* expect = string_data[j][col]; + if(ss.str() != expect) + { + if(is_mpf(mp_t()) && is_bankers_rounding_error(ss.str(), expect)) + { + std::cout << "Ignoring bankers-rounding error with GMP mp_f.\n"; + } + else + { + std::cout << std::setprecision(20) << "Testing value " << val << std::endl; + print_flags(f[i]); + std::cout << "Precision is: " << prec << std::endl; + std::cout << "Got: " << ss.str() << std::endl; + std::cout << "Expected: " << expect << std::endl; + ++boost::detail::test_errors(); + mp_t(val).str(prec, f[i]); // for debugging + } + } + } + } + num = -num; + if(j & 1) + denom *= 8; + val = num / denom; + } + + boost::array zeros = + {{ "0", "0.", "+0", "0.0e+00", "+0.0e+00", "0.0e+00", "0.0", "0.0", "+0.0", "0", "0.0", "+0", "0.00e+00", "+0.00e+00", "0.00e+00", "0.00", "0.00", "+0.00", "0", "0.00", "+0", "0.000e+00", "+0.000e+00", "0.000e+00", "0.000", "0.000", "+0.000", "0", "0.000", "+0", "0.0000e+00", "+0.0000e+00", "0.0000e+00", "0.0000", "0.0000", "+0.0000", "0", "0.0000", "+0", "0.00000e+00", "+0.00000e+00", "0.00000e+00", "0.00000", "0.00000", "+0.00000", "0", "0.00000", "+0", "0.000000e+00", "+0.000000e+00", "0.000000e+00", "0.000000", "0.000000", "+0.000000", "0", "0.000000", "+0", "0.0000000e+00", "+0.0000000e+00", "0.0000000e+00", "0.0000000", "0.0000000", "+0.0000000", "0", "0.0000000", "+0", "0.00000000e+00", "+0.00000000e+00", "0.00000000e+00", "0.00000000", "0.00000000", "+0.00000000", "0", "0.00000000", "+0", "0.000000000e+00", "+0.000000000e+00", "0.000000000e+00", "0.000000000", "0.000000000", "+0.000000000", "0", "0.000000000", "+0", "0.0000000000e+00", "+0.0000000000e+00", "0.0000000000e+00", "0.0000000000", "0.0000000000", "+0.0000000000", "0", "0.0000000000", "+0", "0.00000000000e+00", "+0.00000000000e+00", "0.00000000000e+00", "0.00000000000", "0.00000000000", "+0.00000000000", "0", "0.00000000000", "+0", "0.000000000000e+00", "+0.000000000000e+00", "0.000000000000e+00", "0.000000000000", "0.000000000000", "+0.000000000000", "0", "0.000000000000", "+0", "0.0000000000000e+00", "+0.0000000000000e+00", "0.0000000000000e+00", "0.0000000000000", "0.0000000000000", "+0.0000000000000" }}; + + unsigned col = 0; + val = 0; + for(unsigned prec = 1; prec < 14; ++prec) + { + for(unsigned i = 0; i < f.size(); ++i, ++col) + { + std::stringstream ss; + ss.precision(prec); + ss.flags(f[i]); + ss << mp_t(val); + const char* expect = zeros[col]; + if(ss.str() != expect) + { + std::cout << std::setprecision(20) << "Testing value " << val << std::endl; + print_flags(f[i]); + std::cout << "Precision is: " << prec << std::endl; + std::cout << "Got: " << ss.str() << std::endl; + std::cout << "Expected: " << expect << std::endl; + ++boost::detail::test_errors(); + mp_t(val).str(prec, f[i]); // for debugging + } + } + } + + if(std::numeric_limits::has_infinity) + { + T val = std::numeric_limits::infinity(); + BOOST_CHECK_EQUAL(val.str(), "inf"); + BOOST_CHECK_EQUAL(val.str(0, std::ios_base::showpos), "+inf"); + val = -val; + BOOST_CHECK_EQUAL(val.str(), "-inf"); + BOOST_CHECK_EQUAL(val.str(0, std::ios_base::showpos), "-inf"); + + val = static_cast("inf"); + BOOST_CHECK_EQUAL(val, std::numeric_limits::infinity()); + val = static_cast("+inf"); + BOOST_CHECK_EQUAL(val, std::numeric_limits::infinity()); + val = static_cast("-inf"); + BOOST_CHECK_EQUAL(val, -std::numeric_limits::infinity()); + } + if(std::numeric_limits::has_quiet_NaN) + { + T val = std::numeric_limits::quiet_NaN(); + BOOST_CHECK_EQUAL(val.str(), "nan"); + val = static_cast("nan"); + BOOST_CHECK(boost::math::isnan(val)); + } +} + +template +T generate_random() +{ + typedef typename T::backend_type::exponent_type e_type; + static boost::random::mt19937 gen; + T val = gen(); + T prev_val = -1; + while(val != prev_val) + { + val *= (gen.max)(); + prev_val = val; + val += gen(); + } + e_type e; + val = frexp(val, &e); + + static boost::random::uniform_int_distribution ui(0, std::numeric_limits::max_exponent - 10); + return ldexp(val, ui(gen)); +} + +template +struct max_digits10_proxy +{ + static const unsigned value = std::numeric_limits::digits10 + 5; +}; +#ifdef TEST_CPP_DEC_FLOAT +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif +#ifdef TEST_MPF_50 +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif +#ifdef TEST_MPFR_50 +template +struct max_digits10_proxy, ET> > +{ + static const unsigned value = std::numeric_limits, ET> >::max_digits10; +}; +#endif + +template +void do_round_trip(const T& val, std::ios_base::fmtflags f) +{ + std::stringstream ss; +#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST + ss << std::setprecision(std::numeric_limits::max_digits10); +#else + ss << std::setprecision(max_digits10_proxy::value); +#endif + ss.flags(f); + ss << val; + T new_val = static_cast(ss.str()); + BOOST_CHECK_EQUAL(new_val, val); + new_val = static_cast(val.str(0, f)); + BOOST_CHECK_EQUAL(new_val, val); +} + +template +void do_round_trip(const T& val) +{ + do_round_trip(val, std::ios_base::fmtflags(0)); + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::scientific)); + if((fabs(val) > 1) && (fabs(val) < 1e100)) + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::fixed)); +} + +template +void test_round_trip() +{ + for(unsigned i = 0; i < 1000; ++i) + { + T val = generate_random(); + do_round_trip(val); + do_round_trip(T(-val)); + do_round_trip(T(1/val)); + do_round_trip(T(-1/val)); + } +} + +int main() +{ +#ifdef TEST_MPFR_50 + test(); + test(); + + test_round_trip(); + test_round_trip(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + + // cpp_dec_float has extra guard digits that messes this up: + test_round_trip(); + test_round_trip(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); + /* + // I can't get this to work with mpf_t - mpf_str appears + // not to actually print enough decimal digits: + test_round_trip(); + test_round_trip(); + */ +#endif + return boost::report_errors(); +} + diff --git a/test/test_fpclassify.cpp b/test/test_fpclassify.cpp new file mode 100644 index 00000000..4ce78ec1 --- /dev/null +++ b/test/test_fpclassify.cpp @@ -0,0 +1,321 @@ +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2007 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#ifdef TEST_MPFR_50 +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +const char* method_name(const boost::math::detail::native_tag&) +{ + return "Native"; +} + +const char* method_name(const boost::math::detail::generic_tag&) +{ + return "Generic (with numeric limits)"; +} + +const char* method_name(const boost::math::detail::generic_tag&) +{ + return "Generic (without numeric limits)"; +} + +const char* method_name(const boost::math::detail::ieee_tag&) +{ + return "IEEE std"; +} + +const char* method_name(const boost::math::detail::ieee_copy_all_bits_tag&) +{ + return "IEEE std, copy all bits"; +} + +const char* method_name(const boost::math::detail::ieee_copy_leading_bits_tag&) +{ + return "IEEE std, copy leading bits"; +} + +template +void test() +{ + typedef typename boost::math::detail::fp_traits::type traits; + typedef typename traits::method method; + + T t = 2; + T u = 2; + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + if(std::numeric_limits::is_specialized) + { + t = (std::numeric_limits::max)(); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + t = (std::numeric_limits::min)(); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + } + if(std::numeric_limits::has_denorm) + { + t = (std::numeric_limits::min)(); + t /= 2; + if(t != 0) + { + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + } + t = std::numeric_limits::denorm_min(); + if((t != 0) && (t < (std::numeric_limits::min)())) + { + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + } + } + else + { + std::cout << "Denormalised forms not tested" << std::endl; + } + t = 0; + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + t /= -u; // create minus zero if it exists + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + // infinity: + if(std::numeric_limits::has_infinity) + { + // At least one std::numeric_limits::infinity)() returns zero + // (Compaq true64 cxx), hence the check. + t = (std::numeric_limits::infinity)(); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); +#if !defined(__BORLANDC__) && !(defined(__DECCXX) && !defined(_IEEE_FP)) + // divide by zero on Borland triggers a C++ exception :-( + // divide by zero on Compaq CXX triggers a C style signal :-( + t = 2; + u = 0; + t /= u; + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); + t = -2; + t /= u; + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); +#else + std::cout << "Infinities from divide by zero not tested" << std::endl; +#endif + } + else + { + std::cout << "Infinity not tested" << std::endl; + } +#ifndef __BORLANDC__ + // NaN's: + // Note that Borland throws an exception if we even try to obtain a Nan + // by calling std::numeric_limits::quiet_NaN() !!!!!!! + if(std::numeric_limits::has_quiet_NaN) + { + t = std::numeric_limits::quiet_NaN(); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + } + else + { + std::cout << "Quiet NaN's not tested" << std::endl; + } + if(std::numeric_limits::has_signaling_NaN) + { + t = std::numeric_limits::signaling_NaN(); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); + BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); + BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); + BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); + BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); + } + else + { + std::cout << "Signaling NaN's not tested" << std::endl; + } +#endif +} + +int main() +{ + BOOST_MATH_CONTROL_FP; + // start by printing some information: +#ifdef isnan + std::cout << "Platform has isnan macro." << std::endl; +#endif +#ifdef fpclassify + std::cout << "Platform has fpclassify macro." << std::endl; +#endif +#ifdef BOOST_HAS_FPCLASSIFY + std::cout << "Platform has FP_NORMAL macro." << std::endl; +#endif + std::cout << "FP_ZERO: " << (int)FP_ZERO << std::endl; + std::cout << "FP_NORMAL: " << (int)FP_NORMAL << std::endl; + std::cout << "FP_INFINITE: " << (int)FP_INFINITE << std::endl; + std::cout << "FP_NAN: " << (int)FP_NAN << std::endl; + std::cout << "FP_SUBNORMAL: " << (int)FP_SUBNORMAL << std::endl; + +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); +#endif +#ifdef TEST_BACKEND + test >(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_generic_conv.cpp b/test/test_generic_conv.cpp new file mode 100644 index 00000000..50169d73 --- /dev/null +++ b/test/test_generic_conv.cpp @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#include +#include +#include + +#ifdef TEST_GMP +#include +#endif +#ifdef TEST_TOMMATH +#include +#endif +#ifdef TEST_MPFR +#include +#endif + +int main() +{ + using namespace boost::multiprecision; + using namespace boost::random; + + independent_bits_engine gen; + + for(unsigned i = 0; i < 100; ++i) + { + cpp_int c = gen(); + // + // Integer to integer conversions first: + // +#ifdef TEST_GMP + mpz_int z(c); + cpp_int t(z); + BOOST_CHECK_EQUAL(t, c); + z.assign(-c); + t.assign(-z); + BOOST_CHECK_EQUAL(t, c); +#endif +#ifdef TEST_TOMMATH + tom_int tom(c); + cpp_int t2(tom); + BOOST_CHECK_EQUAL(t2, c); + tom.assign(-c); + t2.assign(-tom); + BOOST_CHECK_EQUAL(t2, c); +#endif + // + // Now integer to float: + // + typedef number > dec_float_500; + dec_float_500 df(c); + dec_float_500 df2(c.str()); + BOOST_CHECK_EQUAL(df, df2); + df.assign(-c); + df2 = -df2; + BOOST_CHECK_EQUAL(df, df2); +#ifdef TEST_GMP + typedef number > mpf_type; + mpf_type mpf(c); + mpf_type mpf2(c.str()); + BOOST_CHECK_EQUAL(mpf, mpf2); + mpf.assign(-c); + mpf2 = -mpf2; + BOOST_CHECK_EQUAL(mpf, mpf2); +#endif +#ifdef TEST_MPFR + typedef number > mpfr_type; + mpfr_type mpfr(c); + mpfr_type mpfr2(c.str()); + BOOST_CHECK_EQUAL(mpfr, mpfr2); + mpfr.assign(-c); + mpfr2 = -mpfr2; + BOOST_CHECK_EQUAL(mpfr, mpfr2); +#endif + // + // Now float to float: + // + df.assign(c); + df /= dec_float_500(gen()); + dec_float_500 tol("1e-500"); +#ifdef TEST_GMP + mpf.assign(df); + mpf2 = static_cast(df.str()); + BOOST_CHECK_EQUAL(mpf, mpf2); + df.assign(mpf); + df2 = static_cast(mpf.str()); + BOOST_CHECK(fabs((df - df2) / df) < tol); +#endif +#ifdef TEST_MPFR + mpfr.assign(df); + mpfr2 = static_cast(df.str()); + BOOST_CHECK_EQUAL(mpfr, mpfr2); + df.assign(mpfr); + df2 = static_cast(mpfr.str()); + BOOST_CHECK(fabs((df - df2) / df) < tol); +#endif + // + // Rational to rational conversions: + // + cpp_rational cppr(c, gen()); +#ifdef TEST_GMP + mpq_rational mpq(cppr); + cpp_rational cppr2(mpq); + BOOST_CHECK_EQUAL(cppr, cppr2); +#endif +#ifdef TEST_TOMMATH + tom_rational tr(cppr); + cpp_rational cppr3(tr); + BOOST_CHECK_EQUAL(cppr, cppr3); +#endif + // + // Integer to rational conversions: + // +#ifdef TEST_GMP + mpq.assign(c); + mpq_rational mpq2 = static_cast(c.str()); + BOOST_CHECK_EQUAL(mpq, mpq2); +#endif +#ifdef TEST_TOMMATH + tr.assign(c); + tom_rational tr2 = static_cast(c.str()); + BOOST_CHECK_EQUAL(tr, tr2); +#endif + // + // Rational to float: + // + df.assign(cppr); + df2.assign(numerator(cppr)); + df2 /= dec_float_500(denominator(cppr)); + BOOST_CHECK(fabs(df - df2) / df2 < tol); + } + + return boost::report_errors(); +} + + + diff --git a/test/test_gmp_conversions.cpp b/test/test_gmp_conversions.cpp new file mode 100644 index 00000000..1b724d80 --- /dev/null +++ b/test/test_gmp_conversions.cpp @@ -0,0 +1,154 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#include + +int main() +{ + using namespace boost::multiprecision; + // + // Test interconversions between GMP supported backends: + // + mpf_t mpf; + mpz_t mpz; + mpq_t mpq; + mpf_init2(mpf, 100); + mpf_set_ui(mpf, 2u); + mpz_init(mpz); + mpz_set_ui(mpz, 2u); + mpq_init(mpq); + mpq_set_ui(mpq, 2u, 1u); + + BOOST_TEST(mpf_float(mpf) == 2); + BOOST_TEST(mpf_float_50(mpf) == 2); + BOOST_TEST(mpf_float(mpz) == 2); + BOOST_TEST(mpf_float_50(mpz) == 2); + BOOST_TEST(mpf_float(mpq) == 2); + BOOST_TEST(mpf_float_50(mpq) == 2); + + mpf_float f0; + mpf_float_50 f50; + f0 = mpf; + BOOST_TEST(f0 == 2); + f0 = 0; + f0 = mpz; + BOOST_TEST(f0 == 2); + f0 = 0; + f0 = mpq; + BOOST_TEST(f0 == 2); + + f50 = mpf; + BOOST_TEST(f50 == 2); + f50 = 0; + f50 = mpz; + BOOST_TEST(f50 == 2); + f50 = 0; + f50 = mpq; + BOOST_TEST(f50 == 2); + + f50 = 4; + f0 = f50; + BOOST_TEST(f0 == 4); + f0 = 3; + f50 = f0; + BOOST_TEST(f50 == 3); + f50 = 4; + BOOST_TEST(mpf_float(f50) == 4); + BOOST_TEST(mpf_float_50(f0) == 3); + + mpz_int iz(2); + mpq_rational rat(2); + f50 = iz; + BOOST_TEST(f50 == 2); + f0 = iz; + BOOST_TEST(f0 == 2); + BOOST_TEST(mpf_float(iz) == 2); + BOOST_TEST(mpf_float_50(iz) == 2); + BOOST_TEST(mpf_float(rat) == 2); + BOOST_TEST(mpf_float_50(rat) == 2); + + BOOST_TEST(mpz_int(mpf) == 2); + BOOST_TEST(mpz_int(mpz) == 2); + BOOST_TEST(mpz_int(mpq) == 2); + iz = 3; + iz = mpz_int(mpf); // explicit conversion only + BOOST_TEST(iz == 2); + iz = 3; + iz = mpz; + BOOST_TEST(iz == 2); + iz = 4; + iz = mpz_int(mpq); // explicit conversion only + BOOST_TEST(iz == 2); + f0 = 2; + f50 = 2; + + BOOST_TEST(mpz_int(f0) == 2); + BOOST_TEST(mpz_int(f50) == 2); + rat = 2; + BOOST_TEST(mpz_int(rat) == 2); + iz = 3; + iz = static_cast(f0); + BOOST_TEST(iz == 2); + iz = 3; + iz = static_cast(f50); + BOOST_TEST(iz == 2); + iz = 3; + iz = static_cast(rat); + BOOST_TEST(iz == 2); + + BOOST_TEST(mpq_rational(mpz) == 2); + BOOST_TEST(mpq_rational(mpq) == 2); + BOOST_TEST(mpq_rational(iz) == 2); + rat = 3; + rat = mpz; + BOOST_TEST(rat == 2); + rat = 3; + rat = mpq; + BOOST_TEST(rat == 2); + rat = 3; + rat = iz; + BOOST_TEST(rat == 2); + + iz = numerator(rat); + BOOST_TEST(iz == 2); + iz = denominator(rat); + BOOST_TEST(iz == 1); + + // + // Conversions involving precision only, + // note that mpf_t precisions are only approximate: + // + mpf_float::default_precision(30); + f50 = 2; + mpf_float_100 f100(3); + mpf_float f0a(4); + mpf_float f0b(f100); + BOOST_TEST(f0a.precision() >= 30); + BOOST_TEST(f0b.precision() >= 100); + f0a = f100; + BOOST_TEST(f0a == 3); + BOOST_TEST(f0a.precision() >= 100); + + f100 = f50; + BOOST_TEST(f100 == 2); + + return boost::report_errors(); +} + + + diff --git a/test/test_int_io.cpp b/test/test_int_io.cpp new file mode 100644 index 00000000..2b615fdc --- /dev/null +++ b/test/test_int_io.cpp @@ -0,0 +1,169 @@ +// Copyright John Maddock 2011. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +# define TEST_TOMMATH +# define TEST_MPZ +# define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPZ) +#include +#endif +#if defined(TEST_TOMMATH) +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif + +#include +#include +#include +#include "test.hpp" +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable:4127) +#endif + +template +struct unchecked_type{ typedef T type; }; + +#ifdef TEST_CPP_INT +template +struct unchecked_type, ExpressionTemplates> > +{ + typedef boost::multiprecision::number, ExpressionTemplates> type; +}; +#endif + +template +T generate_random() +{ + typedef typename unchecked_type::type unchecked_T; + + static const unsigned limbs = std::numeric_limits::is_specialized && std::numeric_limits::is_bounded ? std::numeric_limits::digits / std::numeric_limits::digits + 3 : 20; + + static boost::random::uniform_int_distribution ui(0, limbs); + static boost::random::mt19937 gen; + unchecked_T val = gen(); + unsigned lim = ui(gen); + for(unsigned i = 0; i < lim; ++i) + { + val *= (gen.max)(); + val += gen(); + } + return val; +} + +template +void do_round_trip(const T& val, std::ios_base::fmtflags f) +{ + std::stringstream ss; +#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST + ss << std::setprecision(std::numeric_limits::max_digits10); +#else + ss << std::setprecision(std::numeric_limits::digits10 + 5); +#endif + ss.flags(f); + ss << val; + T new_val = static_cast(ss.str()); + BOOST_CHECK_EQUAL(new_val, val); + new_val = static_cast(val.str(0, f)); + BOOST_CHECK_EQUAL(new_val, val); +} + +template +void do_round_trip(const T& val) +{ + do_round_trip(val, std::ios_base::fmtflags(0)); + if(val >= 0) + { + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::hex)); + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::oct)); + } +} + +template +void negative_round_trip(T val, const boost::mpl::true_&) +{ + do_round_trip(T(-val)); +} +template +void negative_round_trip(T, const boost::mpl::false_&) +{ +} + +template +void negative_spots(const boost::mpl::true_&) +{ + BOOST_CHECK_EQUAL(T(-1002).str(), "-1002"); + if(!std::numeric_limits::is_modulo) + { + BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error); + BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error); + } +} +template +void negative_spots(const boost::mpl::false_&) +{ +} + +template +void test_round_trip() +{ + for(unsigned i = 0; i < 1000; ++i) + { + T val = generate_random(); + do_round_trip(val); + negative_round_trip(val, boost::mpl::bool_::is_signed>()); + } + + BOOST_CHECK_EQUAL(T(1002).str(), "1002"); + BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::showpos), "+1002"); + BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct), "1752"); + BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct|std::ios_base::showbase), "01752"); + BOOST_CHECK_EQUAL(boost::to_lower_copy(T(1002).str(0, std::ios_base::hex)), "3ea"); + BOOST_CHECK_EQUAL(boost::to_lower_copy(T(1002).str(0, std::ios_base::hex|std::ios_base::showbase)), "0x3ea"); + BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec), "1002"); + BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec|std::ios_base::showbase), "1002"); + + negative_spots(boost::mpl::bool_::is_signed>()); +} + +int main() +{ +#ifdef TEST_MPZ + test_round_trip(); +#endif +#ifdef TEST_TOMMATH + test_round_trip(); +#endif +#ifdef TEST_CPP_INT + test_round_trip(); + test_round_trip(); + test_round_trip(); + test_round_trip > >(); + test_round_trip > >(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_log.cpp b/test/test_log.cpp new file mode 100644 index 00000000..12961093 --- /dev/null +++ b/test/test_log.cpp @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#ifdef TEST_MPFR_50 +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "-2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806", + "10.355073440919378699690477472036470469315794905372650461119520557405966250191554948388847794306923706128373152780234988638443954821327953543032075228882306893901540038156503265416950932549208174713640840670002321534598356631953006304821201484830902632165858733357596733427094375150860310219829690440417223992885533566388118595248523193740778052893647271700612136670114224280374211626787106078693643289", + "11.741365414719872359995630593475834957852130639032528348910839621576752378207582766840832626901446337859064321328454096088656817987112409176281442608184950888327275070356290649885618053367245169005379545357345645235094776018156840041023694466493107510640907700621694994008944652785168884717808235919056023540605910031676977750466679901495978099025342154131430098841939052890393197699093697421676686108", + "12.552295188839391064403078983058501313786961042419051509346988474726615643710688192053158471717695991904853941837387256340073310064341282022830248452137946273986542713154937759697687656073485311102053666502633006429446632794099471395918827441203897096147814416727830805903830888831170139661499031930347916453836121200110772307492771615813954882033814741470466415076136175748560866462690250372712624427", + "13.12765917900902322346243585913156826327069465639834188399662474212182724479008698347907678965083909936781641397385483495362268256360763444317213586059490467781653518008717313901614800566992248144716374322429987750723867821114358979404591879648104388637035609754399283274014767545593886580941165664957384975221949645055255781874944374229417864853289321901220692566918330756199433299461690335766708584", + "13.573946210017730027239177097297058651455670148127333215055495986565964988037166389618503523561570994165268599045375753512400565200059790703280760252213714757212213525833556727462647729566258301490115414864748436290794191111843775262434063842232241185107471214859854864335150887423144285468856056851239653315249148749701603523173627966758652109489308872414194066451074827802642589890222384815709071028", + "13.938589284701101831675037903832444894846690407420628610481163937380536465305805316181768586604603341197033655576371082304146219991693253987043452241307224478718013872459287813264283001906622959681872321576087143975972033651747378310838673897181549722528073649569290162541997276292708638316653324605571398691171391912961431088832002969546541039753774950645926800096854799942237644831671997679785482847", + "14.246890620897408672445451566098178524763429935510610216690355229695078778430708804421870639655370744549370273426124295240527401708361100923871708589722651960428863955835558634640426846383161118062310502176054546468600516588908689567134867002953229862887953032595529925511011383644740837050282379317993152702704798000312156694502691021267028423979454580574052732764336948692001989411724963233511159783", + "14.51395339092117324610526432755496036199337959182144260442491096061930765841595850793460014941610881052330595683873016973224744403781498772061971443926277312865243350174522677227134957935047605429941424114476598970997223505479765426888886686275495180653025817201214478249415383537946915840293549927935267010481189550187682053892807264533011114305883442850485847010726074555176479027986850883182954118", + "14.749519451795537716462643672888549370666057639128212044001868590062813335472483708120056955187220713486931180221186191741860718823347399129280491176499608998857949407351247432513825095161942372289203657231256344909997480732110798704027258108845584594081552703009126596026870753341888414903979390651641367952487019992866762344920748102417282166652161104367292712971759633790964534907923779335451109079", + "14.960240475644662390024535772058360495972689995692264619118050620984863397335883147741001175137837088856196207660064061839685086120444324885420172384357780225067863432546453923434326358834374021700709153791633034800554630092122384413882780201869241166113270104158152592921242256738530713688528178980864650875690860545577283508963373084295388766350046816560200649161822618828666606722223620871032632611", + "15.150860829728925816270269964092673433542841210964830162793225770535551518840933315190406262273098573795238063523955485390896001670839635976377071048140363687808579387495186737492639543519534774851635101169579614712607935494886581440494071142193798729857001548284675533558490478467589884332536443679208006567281631805562767928329937083844501800478013385969649342207304490375728237042482944784544838254", + "15.324883579506436493570233597448883519693351814374549397498489035148221882270042436654099306811313261346823941672888447313628931256927773946985727814886420570056552118783468127543676769633344136209500636666830026098080195180498059221494203817961212365532443050015541947762494604799890429565189588245725920948145579035449699519788465993549043152027361890729572024195346130030456992216388648768722394836", + "15.484968991583560712862164152602532972505596882865402498065644250737301955125596006515274461619204302558285733320299957799185995441209009451408808376560872924206710117585718578727591708553957297729203457443101522435265312291388453827953066056871634785359329503731609907767433693085428240202927311226115616775436485821324503901092891486358733365244513748729928672060637178808283856096451123227237766837", + "15.633184933296400322886411216914351313442169047575854720677392808712745585778888867637029115450088924031428350724038141381219620588274493330817678181565157141965018413952386880843987389414299029950277357119925470077396582940505069596480801954154029286187951921181728705116872415271634077604874063371227144842898712603028462623610688275714711124501733417572553751110494225479183571648948845731888607993", + "15.771170674177108994750017157264759379388540187789301748807798065200414118407271774235601089093934343495795521812477515931432709195503245641975701807702026215615357450518151317247119115864533992757135781852491298348627270712291588580073932563653614422839620206266586292520948221873093053975823776289996754936187304352159896156876771015468496811587576227636095095473566772184717633945339405330371627545", + "15.900247714739125237305645451417508966665591345786220672552302840334525160137723176098165167253830541655084109190400464710649206788771240950251243759258268060695212680017248831015574286848979270728739089100870231114250075432989803029255029492399141798408644860336753530942734586654467728627658977642688053752033223720047083446705808444218983029996407752310091763448795485193086044050699179075227514085", + "16.021496956952197922992283502641894579962626483154818954043789565712934054541190510263229676242727892630672492409948339732534439120465067507199758379167701667321617794907607307728874859663168072318224068053703928672394393376652024298292046951118253912008558176064907492479298408285769067404165601995001682495873893492451380569168665052480684672167775365328449822100602627386235888117607629689989295358", + "16.135813783442291449575041100809653925479234724736343542177079039059170241908162244448865517513646317913575323823536275208044355623776985732503939829900060864487127004364547143183319169525031486430688761890355067541570726092642869160866842639424318480923069734468346837396224375681293323049896437786794370196393419740684520457519876260717581058279975484300455393801884203407282602155622048760192869731", + "16.243948224975912162101874242338089698927747514172297963501304802721456885123447742525917146000081948350317670558217990170315910524955950657647628011646020228669505156094231753926456488583104510177838897523717492728937537629972877557426292386450904986250829454391823373783104867874948543639133365724217397301073161382317429508046689262594057712721480553629716238053162259132557499326959178271755311819", + "16.346534812891312020017737390565972522861639520956794183631801030677318559517349930264816297286373068267542772472219372292428845683416042271115312027071601889325060155482892443418582095080544516697369324049179348198348320350032057951783059238791085449471373733253488008998200818236407442435705194113745206455080467406424910471012832247972967952311217374959559350158619575075500673005632848486334892081", + "16.444115140490340128500589643685615592593325439192231430163649023292793816677629077048173396104592590442505550803932707806677495894373323443853064668488945973357469342360809555842080876327526869093152265593359032627507962690981132695345232937664935403696772586286371082469152648334224734697834132478315542287352614722743239776066558016553826776123247656549922477370984130115175375533899599151832866777", + "16.537155171118865136534989063582757364253199496897225305411818162632163606557745471767961160436879104964882723479325928591604518246962419687548390063992529356693298596378658322800277364077966826234091623459656551097008920549618056923279473982070326894236928331513682937597704431571923632859325944958271156630648510192786810276479282782233678225160061893949554276261365074478039201200141096034185340788", + "16.626058695701082390621404187251773798561764113151150041596109882112467488919141098521165822165293765039118029510544981683905860141438867442019067534265891760023149100317968826679154566584457042877767867250357368225093921585968539417839705388349710086788853906351301543791493808667435475597486845630653110450254081800953162013336880338884388603160347478448669890791767227275369657780841518987171046251", + "16.711177924047687436041681081297469757517395732698719962499711839818824068470368594816509809165130772248099176990649818696451892735033114399817499272685517472929769530848678764490613732856699010061350335113220658748043901782349324603111802594973838523650919828685995473213566914734286172266839140529583990377667556754261878256224596588519392559788652514828861263680954096492024398529162625680677258884", + "16.792821912654942574589969785414406627855177803111176492774370259331640542125643510644899208865670120639893723574191986313708664152776559897034386961403215067476041927571306948209653637016541256814370701598681758297129259567548154765775910932763810160923332344469835976310776610418278334876476195529920021337399751846302536974621623453741347064741080510495703994896565552519309503521053051550623483165", + "16.871263338577273117049933407315211807184894736082799946337588399915643695388836578819581481279897851015095335198849942961931601540668917787952832251688896660707943869197097893837964754891796695592066084995854170120209827918603483811654385230282025426754327077293929504883381435192439219366582495078959939830875435944938000044089717015334115741229281828493468876793032191535756728196375330663180727281", + "16.946743994200631806033476403925371852051109645526740171061759524387799979304956484613870531865187139791227191840781754383935422487885452369507952721547705027535773654885832127821314459521240798742974634464887793874048016231828535132695506414037947185201173465247385982934992490469404967587724592554548395276895353595409898385619478502390678687463962622836411208115179925881515699871702165077675857036", + "17.019479282236065828727803356580529388797042464710975507911282243104151862598751845439937481303609237769338953879291798328663979939210753132559510492288100384177867237190989151135211416672909332732482371326996189543048703303285313799031214641216166381411885795576234361808712082618702464622338883787915216150436372783047860816587095332458688921705641277515576461385290501276378977328383137813013202605", + "17.089661921583428533920885090473894674921519340994685086552627218992626938319872359613748323826158856027837200411438668460410538403836237956276065714403575420148736981655027235218177614075251822388622713232585428029969533906061654341819894513492491624632974192525592636008127939368987600981961744622054023981036109865947530952316809705151315101400446930619393266624895135955182323721805890693892489067", + "17.157465024686670167940702199808038440453826682770881229464136716214305217066325160993039686330328188786987064692354236198505670650108871009195717920051441546822338399371747349503874711833721760676087218038457960626001087951737722106836691584985009357268276351001658789309901363541541142239028890280836555429745898638761562947010206765922958485242984359891337645169887782296197402533921841201821435322", + "17.223044670108153088406971612680579462250390145455205711423224535559905829397735171751863831903325186673310251936245608147861310604382786127429364616442074955520795624793164764110780962566943990430036624945190166480864873260501647262851147587875798742974124100786387378932173276365815649310057053480347330487890156980245097594505867694166591312545929965230291418670445516669557156689966248314016354044", + "17.286542066533530981819924644041556546839394128235306235416269038138274222049809140847092268150839206354707638710275634022335650694777681817694798501418812448888688173373947001904190184008892957674606496333161081431327984331509197841574297574788702287443502123119313877415278877304866456565176360773848651195816021879148876985173267277031263646152871873014441183590471141901167533828621963866651938359", + "17.348085383681499172852340212837946913681349503319833895379599364916346996678774115472356552172467728498192423708290186696353892633802275272186862935888864564436104200250553583802585096479988444811879111645109656880728153108808638274341978968354895482288870990505393394330150686285205409461910256828313237800771316014620729111128197408712519655232673726993167731090657784157432284844410962540306871812", + "17.407791309811451413991402934776587727274692304168979758129844486195147501475844430031581045491342304862802756719012802717759227086944920237646742600183730387935914237410099970497154963215669635477250725760034883360834134873909027143784365748082991457136260982918509631214089379283854791699127985575276751950639814381413022404340898037317031344649130788109442934133748721229332612763230675387867060167", + "17.465766383402858316731575043043871754932551869660069657366289253587674381952187793692876332186097637634087898052217367730831337525450143144735163993701984235559102178727289467801811444923511321849112339058962832869205150513708620081533545907748750224381419445198858131583714181742840318906599828122743306582674187117835956409356596804579817623463035229848008072471150460106195548408352347746742847561", + "17.522108137193897711249955720342223562404817078270264273905715197834637314555104238731504974899534359198079882854402652102198388084110484760619705504323190957788898675675472299192322756141627162323541713415099172067523105704142354142286507565791349450889277448545966302507723270185283899864397011417078910276215036241179611950839739662625626455044878609357243901835302874736030320059872773022839076998", + "17.576906085439158795399613853863097303860835367703382634217979275105020336999327656009595436350031662565840865227976662242781789960872250051998481804897622287887086985238091438506085053631982050247194140738539987379268409303934286420729479452837709138518786355198810012076646196653084861659638299340083440855659993917810136693887499673110592919880225890667600561450738971059427382635508450091570097859", + "17.630242579482716539323837128846626753956194314343736063283695118187974605321998609676585457221722093540967455603842712855190915316171267768551204188316976169082878976713161041600921069589708836776259260899700342542761959107817464710887483018031112156977258240064220687983570300417350906046032596793701224117336432612122346984445322343505811317200044404325245524587348610225714892960184376194438742903", + "17.682193552177642930469311075041540632454794315173833851548924954045201903733019976720709429894183669091622069055829864963447674638381460850277690319942206492046322144914184638283615681017449686491773099947404077379395563267125512703092895031616346899622091168324459335139948282486097513426616067084251033517363717148785943762510534333490466778398817865864252996839848563898275763467374270388303474531", + "17.732829168042892302590066897013224260526349617442757064898532827287653373154374250085440081248759495538523122114463120786358068331952209807684385821625688206899889794184992102701935895298679767555036775735985597715341448247873700759325978422207409167388561946150223833135803435044691082980471455256218231653367433009869225710546713847446382266908465706428817510556416763430212167661925983678317689559", + "17.782214393127773091907390576928321922818609345162469668288248606737448584265787291899115365824350981071781548351963523796289812496283393676088371363622146243894946956855177324929267339605228930435844698103907214217720043808120931206339233299438914243909015437719067832873971853535761149326746352476616918607787268605165583917095714007024394600276277913067861955743579281638075879563801550521361400101", + "17.830409496196797333256263738087407756305793204876426547866274663003566432384680240879632999625725708300091127739268764655234592101254713785942646078437589939733647676861210608435791914827456291767449764007558390614584486670558546409061408823289149666666818024559557140308187730981247373784664587280435856629009596287509432264978977660915985852234235063815941899607957940727152099219426925372856581083", + "17.877470490934232288852811743259662703350866532641876235327240424382634438025700311951299570329496669487738366928514133455422447732866797861412283887178678146519925852345567722230587799483201967913067391020608007825990349366451164476805546339769760220805534987675878347990806759564468339408725207557557011408435539499579334714364702076041798486860978860009676392441269681660376828431489832998763783258", + "17.923449527306267869903426070004616586122783729793624019886904269965872168854615384174781325332961537402467089754136043237824345234828497017675462013908498436584882632257634259557543282397560432131425953734774375224901224027834174376390115551172850840545446370919691863863162138436779349056977625063368614038926314141157758995633570593909444840439875814859101692914284555504462737973961801589348562421", + "17.968395238938123096275003449517382823058653367901994410453731720353712579214128295617333869516953666517153266184450063833611730223713367177888956257642697863674682557764474491249664869634869467450632518845976225157445436929203774807794710993549169067538180609230496568688211520386012533845072853251411123534511690847284034061828924979836346301147669327210040586682352268581578885354613616677879192008", + "18.012353052308072938755867264876761138384940766536728123219303502872235608220456049765985905816906980541771912193578395286636524639567005562096644259687421270993689984646487799760867557580378976263785987858028882916593402367582926712749625025395229096162602944095765767003293442756802839571379406129666952518296572179431801499117577022831811590456125422748646995266409456422225586206021840322692382857", + "18.055365462686668331727160748231009519565746647193730385530909331597852334952578425145279427250887034166658709337134491235522678908221793937220809954557808901763389178392831492051282059480629151432246720826269576988663211852119754955967569929315382922357289706041278636253185833298598511399638105081736687620508948263244525471222947804257016135464845038301780535378180021273347494295813215232102999649", + "18.097472281022918092839876166164329437973263728374666387409900363304423095913608188979786368122872685324785740303523457754035383735336598870745063200445496969465305638435393742921093080855121166597064087151732410717510776813994536867846471600876935467557239720329955864393503091522335217308468551898804050931884864074974187930869095426636541733964836470414482229854405996155347764481217202728996408614", + "18.138710855372574931023279730094645378686287349356676919424498204049762635832652703081045863264164065707461503608812437952726945167389204858679677978907656542126675434222486013764292798698974541262372833651362936600851261171024940667498778746253799866490414715539561648775214507198558445051277115507846030240001071535504590488750762226492938922487331198045407471864288427126708589240674067562104543957", + "18.179116269955114571377487963612019905652085216126618591531831326851631273535837433851652060806307371522002942828348086254592323263632131183438294055667010855067061587674644272103122258118876651912890486407250279668447142712674562099014392095571206458285314302909409592642841502932705416119595372330139185232535836986175505626716905102551635720868328845059106716603941432470493828723765413424721976223", + "18.218721524498032554193215680552580137491683034589488437319060302272592206508827557611431375182704552154497537575444766904464774327453349109721410510507102426285778233008253433639863695380913463970388673098705619991229471182831382051550803100625573309055088036785775202381313835883262855970305798706681563291905495590616431781211404743717763365778127660253455212146746026811363929209719531660648504082", + "18.25755769616561915104320634671335949819923250838247367135480870103002754055972575277617781066800125225275977232426410882766773084485826986957597205108505829168630501177398318211279559799848433615486396320080576991739828304477785924273653352846964138446264644904849824507615174857436913763769835408524950658917536946876135419383532210821743200063786350760207420579200676223678007228393958258720083932", + "18.295654086063005239961930900603578763176327716162022442528659338478895027684612801134718048445578078864512023650622689532231640803798279071247213212940626166721703242773412064293396910008891332614727995930235839898502680907757808722725076622433926254807390507349193089487065273859422711581690536923283818694448490391002663699373577479984089586448960986922914070154319198856799480586814831572660049059", + "18.333038352045729366070360053860247416881993539906325936417001019639836810235521744851872438194534698737793818113182566661284551265375926400252096198917463166081789346386579278436021220544269108158036360716265068681920333271695665204550361645092770414267870574761534021576748772414710332296686656677922105572480136623006540318287771752403257225484193416375374630295739694584359181669584822144217946089", + "18.369736629342788833545154829965612197972030184654204521583836723612431388284128470120361520079152081604731214550025504583810749093225662462708297813392905679444268263153178673045591535099590243771860299493196201337328463166245762316637806913270164277457975112426005180292583426915918675383435395598215385153247994877265654873384456838948090969392401887506081626510459117637684719849016393221041720966", + "18.405773640310900146133080088261946202976690317466294344672811637024889157611521518848738302063682147953709444704912322724498748005402509152494514057803322060491136048741666988817114427555111210963923209356023892097003244960804568051496345885676927757469123572277620624446804627512970828422692616021227425852662243212443997074981005547833762050079432581680067106949297497692327125068990077901522226957", + "18.441172794474399698182030074721740031645602552534420544604120821167467838337449892992771747357276011553142091110875268371883702350672621604391781630952792517951394285585851496086739721764180588422789463043949353454011941863375479066641639870318143091000764755109263681792932398864353035859720611512874738125344871434992639512151401272538083058455878170262156351968871089395179837425273523581266914745", + "18.47595627986464597709414934346663732189241252367556916529377819718435871713823800089497791390570676646849082185155969226893554048129639509679051447135722658187695404706235925157146425104283059827944524324932672824661552843990966903508121362067629390223781365207266998003720499319458536728358620338853555386727837290179454339519141841532839938596761951045619471589862830891354308681626977577420483375", + "18.510145146551442627414905806735913567003712650812295077443330836708330498077617580007887630002806998527489958357928811323358164284670780912045286972377274734553167811143903532773133805470585887337986897779623231393980154689146471547983633489101760043708991315746940120025902341173853793429617026275691215584867628750464940410772709161351434979639911956946479201132978330304672548030931942250342827294", + "18.54375938315397840777373858913955248239941847920328667581513228848814216209238117867823746808674105485439472281080229047484288277191323337476914908731578203036561093352990739771860442165984753982600021729206737097284114048195126812337180690412756158211962923840645830361425158816448002373708570542607328640280411811505735178290827333249222248570577590327817428193141575383830773736064963674654660788", + "18.576817987027647186937851258336640937668818840595786321214115700990580993937301728456982569596955182509352640277092493549853424411966677818012248002654715239100874590037738307469713048325570874520232570867464224788639656453937494219294174471955373301736672685268384577575584576576899158917424074434177408506824723823546414342198182263466224674661649356568188397290822447447185825387180657594093708751", + "18.609339028743835443520046961477709286939310853034399826433866146117641838882532805452792636721283076369348347017617290496488517658040508081002292362699460963188796636919359563770588812590411785597112719721757265655201721601867128800954165396591923271771796713301912904158675092529178443570927414653982088273331584295588174225100793199329706639345162173054259175639620324704962515101988919574683797276", + "18.641339711410638424722499047013449967887089663871032284600678326435618587023360889502435665997102476809993062067289899429492640057255987173558009597289702007868879986681400023832856533473923548707096670227832737339287908558274044368146372966754230837592655179154123960009424338853507410779228164259856997555111697864450713171508666161000757176178710802248263025585993364498172063037657704404452535503", + "18.672836425322050368486113163967894536152542145032787472779137579977190277914128508177973702344749215422866489255932015284354044054928123475206880037062819389112504714106095639732288437854189846017324055713142277768438434138800721340366655917386856186887417022606078557020556496094324427190459240576788558291551699271849591355480496655647717244614207638067307680084952591605729876523430439516165337322", + "18.703844798370253311556748128890196309240890383998201893987314003630502067675284072677315790931434159739316058047067634433988116165753705089479010402482501330164866808933095532965233351834719435836698735379881853925522288987702030512098787246242665060494288818182785084700362957305908534097737840396555283267034806128689898134337131513408714563437722088348519474128730338455257510535561818243515295123", + "18.734379742609172948695846511449581634565683544125106511957075355113091757584835040550323433523983103087395353257534872811737536865777209110758107808331702363999663358869296693765232701087487872606287651215678117982769333263424530048349886338191672000649776344735688777038908317935895545479771750928675097454702913124841960320021274672197296187088995346243239131294305233657221950357770047779041168948", + "18.764455497316603659697964676682244441947566581055018250974850982088974686459881812049067093753928158863642280317022246479491132048354932411165733919156970301233277913734990931824860100667882748928084034147822613522025142522120240087012670818451468498896073922908905983528384054249374818979283244638542138214163225714979901542761366770616662189716515808719831023436094002277345660650710470976214503432", + "18.794085668866182740204823781307373749785233327862921970091261536522099678420128101122831261188800902247301052497120590553831148856384993334702795779266689462427228385943774192181671843132138022659399715350825905060669445319905454600530058604054055511420322690455781203696250448217551628254838303648547201462249630753150471851402187751539728462449395082445265630322991793425964521071134426892761087686", + "18.82328326768867946516209716586995768024335839807194833176766112965627616145648993732694510000805245875257813926012495009414082293067923695618654400188454857448056930551075037023425200611189368317293241290052197494133870263300149851324237139757643613913686228545143709137199633423670636305032456696459165988858650794045361585281861601603030153235699981659298052458840307661288883784791255308752353561", + "18.852060742573912900871064645288864648159675216435305629278797553184221367993840166607573470069267053513735624040087819326415506386854437946403720812228284865900153407303755694944652909440890918000505344963394853809579466102995490946923404655914747241389209313457700354163158136320973199396402856713949800424774426208733366034958384913000571799639761622099679737940788622933241370717844146251711932128", + "18.880430012539655701065719740012642650514689061888847292472446317260576484360479108374318422256748212928421929786176000015552730066213309405093412502424231235041703778572229968621812094224953783751727048234887878221529796434400738059144871066371011576734445290684672478932371976691435646196856591582073749970279840730554499319160664075936135140351358832332481792115613668240634181554442075595951874232", + "18.908402496471717232311467781165733233171140941896760455553034330908971709296619686804159498334964006649119069488646486948675866965781697617293443993292894960273992948681816600748607581132058645469709895004815813032481899164996133398853203604094641445335770040577643758444125343960451089873183667195183097301272165939070294009329717796749663916249651314647264543061678516229808974080105230884519025421", + "18.935989140719681524355183827184271883117018713616424044375161718824065979531438908152091359516789236304421957752893530968312896089478807820652680723918795442056690234785900341761515097938048245785367391810983836804772037480360220145546699221066508593371664219887047644628393373836620900288539062774663891696384999640649150431067240627749142322666676970274474792135970231868616050929898319819448939034", + "18.963200444815204167404888798469665227431788358892299847438551435971105813566329353339851076750530262901184430318825907802984559086828099838800823075902608236275943927671387049630228757166718632225359114181378374769186216486342164672374303171089906235756037703334480067642792992542669516647312965086899057259968955796081732571906843773036664256360263051447703790357359429377002031207739864979999279347", + "18.990046485464088033353325238570094871523592746407402454864447659438418650897352188003827603659585905257296788261872980663015351591030286798753545075312871886708540373690732957230479307213846083134185408782477823043603415914158563765104431367119681516469558190435321626296408405773925785846797696565762444462069369032104851518168840362055319574446706630124442642806832354006488607879109906061011225994", + "19.016536938949335590921908878972071081608578803308502271146163132935001206102423418117835863551157682291011036313549071538079474102791095379250735204641651869626255407971202952320707788423726057706822543117840676308428340234652209177652929619836857962138281947043694787969753375808877555756525156889419987622193160096718082756877689454214937644538436622120458515758071395625444960838247998451767464267", + "19.042681102069820040323211057777714109150558076228575985448688497208727928412122242888431932498284067180966108960090928128416538326586163291672353531766027111567123306015724614143020205136706498507055346813817986209642505418179828757157587146552894936306186818734849750397304488535715134906592464324381660408650130874094490704788761416060096501351661608424222204094369103147551037672603814369634649173", + "19.068487911727958175697030382906549671323284692477975980792892280404995909757933182996822232452584791269433004172376138676679805214029937405307084300414313959313789831600985178255638111559270519906326622715617717964168412002699242926437873012736620082535900009120622005729068876661407020205549742970102634687260159098231611555026386636952356914915597529253373429394903680674472796958663494038067669179", + "19.093965963269656159901801532857652686731313095114787279282350143184060615248880952958892345276101741792959203039945279273255821413683057071718873479055914318955623580559627285483449590741119271240498698177664589148961791164562328382134513604070535948997556425774535241433839196056647337630745324677877037589790564832932809741759428622931327986353687891898499439791429917840804474313864245639140963876", + "19.119123527670705331793258647026174473061813878914781070641605073424527485626683566355878191198143709838509389044950724156590593262994411423265514055870555330957166471517671117689943118929441254707396532385048466111853801352620946858612646592880180562600210076019427990165200479741063391057955342589569972650353707736819649707138135073772494722116787681314798945037658461538374603477221825614061123586", + "19.143968567655614969812922707872905228504499895574401195919290684664632292543319151929670686365568982588326143748358606442800755409560708661213139514248609009613770051771501624762852458893105259920477327438788243371302722213272226600736522283567127277667156871770413468147870394343816746792945999572244176333552811712447483231232773171106511438260175071145300046115843401710072061507331123043607901766", + "19.168508752827482780609154136923082745746771414212427034681109262302000645968087085215520638009496537393752178754873475983837687377025695010556483691979309217953419255985001727184619660158435191823702770674175581797631578786818852604111682506864006199186805540809913091091561814668081471402749434233431033452441548505582706019452955567976154397574205270457372773342241946969622998755580434262211071558", + "19.192751473880834042563713562225153433521577940186973776803866639536641104273721851582869330116346851241224039623128541122821371810756925681002641212419779923811384320279466454221232217629041792882431116499214977303106306157966687858071257893713340199820635963233697984370035461108601863346164084264967404520613456100656965925875472210769471793070984755357524002396981276686789870757739219539841324669", + "19.216703855963329593992083348877341510356872855419154524286060224198192164950344042194924570763041352943159776496534086655621090662648765929073480563926604513272233491262353914647091955902924297702861031248271549558718609763974479507490837350364617085882753391176792131259310397149374028556893735115741447201974608383790314541221313482249282941830681505989160209022143487123591182161037084387107577471", + "19.240372771246783136336288622974117018573581443774444767997147210768023102387819846722491865244820295698055584478151667485670300985795814036287612086238394489310685917822308982062485897587424683040075624404469719368214374255580054164790522993745386564072906888203344350441788631572056395846260169628655731587443716443908470481602481327796867951175756539602824534024677208143458306390998693538144276002", + "19.263764850762979509196317705761686108092922892356892210254799469999751475179529646750512177469718303426094538082717842694993912366018532429385996195100165328675330327321101942399890523238950583083919577089467043577581159099371618262297126999910295820866611740582812686480215151994304295620401944519281853807987442610790122820927006439539980791908595120476521299636624843377591628005484740938263373595", + "19.286886495555294522450851525927489255646333848651043717882790718796769943763203547772413744395083720600670009266257171342692898145198064660758379840502214228374875168690401725272168814130387964227940171355345107459707413634435078254467165459318134413588306046635342334572072865760417877208230914828250259039270224031775041480686581149991980042698893384296012208438178584526032640636530664689171174514", + "19.309743887193036513569909003754932688390195189494409126081957694707453295769725463252527373922995550848707616892717734716346726926003376949988744940329952938435722400261306789658518736487435455592323288866363564460056999876237001095092480820045715217327131479089102764865100373961878408215166685028270522348153253852064527393390794401890890932406298166622224431486187051653736399833197687524233000392", + "19.332342997691718269365647851051829244300572144237799985690236148794296859647334840581772744190077146167636205171422529047782401411481872480699008041273574144705390909628455554205882856537701103044535844002047328262877230706418721410147702147287802942241134713881576962004492246225067150128745210304021219616585555420191917418786300056829952680702638022710700076784220324428140020802898115083347702904", + "19.354689598879088211883278917315015191222443867565368209411861608347893184500809153071123456883339348988675265028178228103174790923741638364554293709103213239495123865898742141584076941660965692453426480770865774436380303703020587851939728834028918714275983773159730132531253761589283704592841895713231304417993106469276962707965968679020792759185611101812841427933459395519877074670185732532077876915", + "19.376789271243668798743209719830951710660724013826759987563467708214368337563307069810449676142525612003499201086112645501159094078378318648014400550345870757023544381773094826620272453238529286555419097429861755219673554476395943490245768513403194721941361801918811127988057063915654267554707302094460700078255016831241731287084620030531370389406858605301314913503432729894455360413554796057743624785", + "19.398647412299738536733101983020344760416543000933452586938357216391679714568872063480206587627849607725892049860100424409512218327903976557192129920072602449053963631370720893361294311430877864798057636106390383386608343478253049758287190639090148001663846660919016228401517981946486814580501445191763231914170223651871543954569563229752867364010807484149328122287932691728836607206296504503654291916", + "19.420269244500125639443026886412358511499173347101740173789245348545649777799992933455717128782979425999232096035698012165274922488616903998818326535687811364645463339885951676665882203155018792792505473796600843314336576346118972683035247786115152970665197263535031125663311669153219106967873840911780618890220192918885584791820817380351857621444438732170662912318105800373867459654881916254806601924", + "19.441659822725832764853886827062860938003360575287073851586808019473777348197590834815623551815029267586554639358825375063360984210103069003729612683914916394217674289812465439813541316938870999354861402160375582810342455043995730819816948505547453029096197833928688735935982538915244747599958654970407704104602569366784225221531104839626781845870092648147888203880688567605208831444945817857785153427", + "19.462824041379362514202453738329145059871795167945778128620896576209292571177865023083134487492542931078517939464890630420523665550799939651548618906955780515811541533057671943504991862669514142328738958049297858093270685582461594213632344682911288013670395835728596839923778216755784200501989248577166652556656745561631320914185098036550279972269808563352717494278133064808018424486494613581670904697", + "19.483766641106643718481178395114340475919752681994355643610181441860832131581914604665304968112958314746911243491535376957183544987386808635080341126118126364286470448001964590403332961518317007864293940732767763315935539659300785943459751426720740528037173390794501709108627539732588206226415399674048608843262175783293190807110169521287571898125826758063922707869247389042070537305271065057452360137", + "19.504492215170652185153425611551614568097792837031617515988255748353971463776213613651972980845739009653411602074763823583486335276886222365741099356087975815479321535979397651959714956358141934399110351847826398926624666313434326948757230737160647513320407575743953348133831681915668076630219831345596329489041495050445409516995558844346940248424949708046529076568535423815692145534030368195098701895", + "19.52500521549816144973266072401605164852396136071234571245810367391072812166019661923143396972741343266046339927362413412251126099193801965681827360699083448218860273549526903661234475357554150017778848244185893299525191263899191588797634058235164494448438674653809951435022502560679429105527325418829543863756825670476364629140951247734867887985343458291386040322597855003211338820555010939867273248", + "19.545309958419535630089123088329455125777373731767323301911891787605488456921558805681207304272616222501167615837357366396904683096528060072684210523189673108467018417135186800678628444987751206147451054525963839562634340820804697604369657105969423354842149829173951943549166420900709500398322624130365195674097282456714104812933002700523506427441210494461469512180706693823193924457440917371176532034", + "19.565410630120075532420489068555321524954362381908007338302983473268528473151341321768804731192210840056455228388636731122203200610869021021871133154865620432257415783302175345843898977949742849569372169004904667621738405749986270376895267386643049526766451459390277406632576412790748533372863644721976845168460840162066672290292749672668879524315410824251032084115058493720402881895485689493165441193", + }}; + + T pi = static_cast("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609"); + T tenth = 1; + tenth /= 10; + T logten = log(T(10)); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = boost::multiprecision::log(tenth + pi * (100 * k) * (100 * k)); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + + val = boost::multiprecision::log(1 / (tenth + pi * (100 * k) * (100 * k))); + e = relative_error(val, T(-T(data[k]))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + + val = boost::multiprecision::log10(tenth + pi * (100 * k) * (100 * k)); + e = relative_error(val, T(T(data[k]) / logten)); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + + val = boost::multiprecision::log10(1 / (tenth + pi * (100 * k) * (100 * k))); + e = relative_error(val, T(-T(data[k]) / logten)); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 10); + BOOST_TEST(log(T(1)) == 0); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_miller_rabin.cpp b/test/test_miller_rabin.cpp new file mode 100644 index 00000000..ec12ab8b --- /dev/null +++ b/test/test_miller_rabin.cpp @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include "test.hpp" + + +template +void test() +{ + // + // Very simple test program to verify that the GMP's Miller-Rabin + // implementation and this one agree on whether some random numbers + // are prime or not. Of course these are probabilistic tests so there's + // no reason why they should actually agree - except the probability of + // disagreement for 25 trials is almost infinitely small. + // + using namespace boost::random; + using namespace boost::multiprecision; + + typedef I test_type; + + static const unsigned test_bits = + std::numeric_limits::digits && (std::numeric_limits::digits <= 256) + ? std::numeric_limits::digits + : 128; + + independent_bits_engine gen; + // + // We must use a different generator for the tests and number generation, otherwise + // we get false positives. Further we use the same random number engine for the + // Miller Rabin test as GMP uses internally: + // + mt19937 gen2; + + // + // Begin by testing the primes in our table as all these should return true: + // + for(unsigned i = 1; i < boost::math::max_prime; ++i) + { + BOOST_TEST(miller_rabin_test(test_type(boost::math::prime(i)), 25, gen)); + BOOST_TEST(mpz_probab_prime_p(mpz_int(boost::math::prime(i)).backend().data(), 25)); + } + // + // Now test some random values and compare GMP's native routine with ours. + // + for(unsigned i = 0; i < 10000; ++i) + { + test_type n = gen(); + bool is_prime_boost = miller_rabin_test(n, 25, gen2); + bool is_gmp_prime = mpz_probab_prime_p(mpz_int(n).backend().data(), 25) ? true : false; + if(is_prime_boost && is_gmp_prime) + { + std::cout << "We have a prime: " << std::hex << std::showbase << n << std::endl; + } + if(is_prime_boost != is_gmp_prime) + std::cout << std::hex << std::showbase << "n = " << n << std::endl; + BOOST_CHECK_EQUAL(is_prime_boost, is_gmp_prime); + } +} + +int main() +{ + using namespace boost::multiprecision; + + test(); + test >(); + test(); + test(); + + test(); + test, et_off> >(); + test(); + test(); + + return boost::report_errors(); +} + + diff --git a/test/test_mixed_cpp_int.cpp b/test/test_mixed_cpp_int.cpp new file mode 100644 index 00000000..7d12eba9 --- /dev/null +++ b/test/test_mixed_cpp_int.cpp @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include "test.hpp" + +template +void test() +{ + using namespace boost::multiprecision; + typedef Number test_type; + + test_type h = (std::numeric_limits::max)(); + test_type l = (std::numeric_limits::max)(); + BigNumber r; + + add(r, h, h); + BOOST_CHECK_EQUAL(r, cpp_int(h) + cpp_int(h)); + + multiply(r, h, h); + BOOST_CHECK_EQUAL(r, cpp_int(h) * cpp_int(h)); + + if(std::numeric_limits::is_signed) + { + subtract(r, l, h); + BOOST_CHECK_EQUAL(r, cpp_int(l) - cpp_int(h)); + subtract(r, h, l); + BOOST_CHECK_EQUAL(r, cpp_int(h) - cpp_int(l)); + multiply(r, l, l); + BOOST_CHECK_EQUAL(r, cpp_int(l) * cpp_int(l)); + } + + // + // Try again with integer types as the source: + // + static const unsigned max_digits = std::numeric_limits::is_signed ? std::numeric_limits::digits : std::numeric_limits::digits; + static const unsigned require_digits = std::numeric_limits::digits <= 2 * max_digits ? std::numeric_limits::digits / 2 : max_digits; + typedef typename boost::mpl::if_c::is_signed, typename boost::int_t::least, typename boost::uint_t::least>::type i_type; + + i_type ih = (std::numeric_limits::max)(); + i_type il = (std::numeric_limits::max)(); + + add(r, ih, ih); + BOOST_CHECK_EQUAL(r, cpp_int(ih) + cpp_int(ih)); + + multiply(r, ih, ih); + BOOST_CHECK_EQUAL(r, cpp_int(ih) * cpp_int(ih)); + + if(std::numeric_limits::is_signed) + { + subtract(r, il, ih); + BOOST_CHECK_EQUAL(r, cpp_int(il) - cpp_int(ih)); + subtract(r, ih, il); + BOOST_CHECK_EQUAL(r, cpp_int(ih) - cpp_int(il)); + multiply(r, il, il); + BOOST_CHECK_EQUAL(r, cpp_int(il) * cpp_int(il)); + } +} + +int main() +{ + using namespace boost::multiprecision; + + test(); + test(); + test, et_off>, checked_int128_t>(); + test(); + + test(); + test(); + test, et_off>, checked_uint128_t>(); + test(); + + return boost::report_errors(); +} + + + diff --git a/test/test_mixed_float.cpp b/test/test_mixed_float.cpp new file mode 100644 index 00000000..2b5aa6ff --- /dev/null +++ b/test/test_mixed_float.cpp @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#ifdef TEST_GMP +#include +#endif +#ifdef TEST_MPFR +#include +#endif +#include +#include "test.hpp" + +template +void test() +{ + using namespace boost::multiprecision; + typedef Number test_type; + + test_type a = 1; + a /= 3; + test_type b = -a; + + BigNumber r; + BOOST_CHECK_EQUAL(add(r, a, a), BigNumber(a) + BigNumber(a)); + BOOST_CHECK_EQUAL(subtract(r, a, b), BigNumber(a) - BigNumber(b)); + BOOST_CHECK_EQUAL(subtract(r, b, a), BigNumber(b) - BigNumber(a)); + BOOST_CHECK_EQUAL(multiply(r, a, a), BigNumber(a) * BigNumber(a)); +} + +int main() +{ + using namespace boost::multiprecision; + + test(); + +#ifdef TEST_GMP + test(); +#endif +#ifdef TEST_MPFR + test(); +#endif + + return boost::report_errors(); +} + + + diff --git a/test/test_move.cpp b/test/test_move.cpp new file mode 100644 index 00000000..1ce4a4cf --- /dev/null +++ b/test/test_move.cpp @@ -0,0 +1,291 @@ +// Copyright John Maddock 2012. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include + +#ifndef BOOST_NO_RVALUE_REFERENCES + +#if !defined(TEST_GMP) && !defined(TEST_MPFR) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +# define TEST_GMP +# define TEST_MPFR +# define TEST_TOMMATH +# define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_GMP) +#include +#endif +#if defined(TEST_MPFR) +#include +#endif +#ifdef TEST_TOMMATH +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif + +#include "test.hpp" + +unsigned allocation_count = 0; + +void *(*alloc_func_ptr) (size_t); +void *(*realloc_func_ptr) (void *, size_t, size_t); +void (*free_func_ptr) (void *, size_t); + +void *alloc_func(size_t n) +{ + ++allocation_count; + return (*alloc_func_ptr)(n); +} + +void free_func(void * p, size_t n) +{ + (*free_func_ptr)(p, n); +} + +void * realloc_func(void * p, size_t old, size_t n) +{ + ++allocation_count; + return (*realloc_func_ptr)(p, old, n); +} + +template +void do_something(const T&) +{ +} + +template +void test_std_lib() +{ + std::vector v; + for(unsigned i = 0; i < 100; ++i) + v.insert(v.begin(), i); + + T a(2), b(3); + std::swap(a, b); + BOOST_TEST(a == 3); + BOOST_TEST(b == 2); +} + + +int main() +{ +#if defined(TEST_MPFR) || defined(TEST_GMP) + mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); + mp_set_memory_functions(&alloc_func, &realloc_func, &free_func); +#endif + + using namespace boost::multiprecision; + +#ifdef TEST_MPFR + { + test_std_lib(); + mpfr_float_50 a = 2; + BOOST_TEST(allocation_count); // sanity check that we are tracking allocations + allocation_count = 0; + mpfr_float_50 b = std::move(a); + BOOST_TEST(allocation_count == 0); + // + // Move assign - we rely on knowledge of the internals to make this test work!! + // + mpfr_float_50 c(3); + do_something(b); + do_something(c); + const void* p = b.backend().data()[0]._mpfr_d; + BOOST_TEST(c.backend().data()[0]._mpfr_d != p); + c = std::move(b); + BOOST_TEST(c.backend().data()[0]._mpfr_d == p); + BOOST_TEST(b.backend().data()[0]._mpfr_d != p); + // + // Again with variable precision, this we can test more easily: + // + mpfr_float d, e; + d.precision(100); + e.precision(1000); + d = 2; + e = 3; + allocation_count = 0; + BOOST_TEST(d == 2); + d = std::move(e); + BOOST_TEST(allocation_count == 0); + BOOST_TEST(d == 3); + e = 2; + BOOST_TEST(e == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } +#endif +#ifdef TEST_GMP + { + test_std_lib(); + mpf_float_50 a = 2; + BOOST_TEST(allocation_count); // sanity check that we are tracking allocations + allocation_count = 0; + mpf_float_50 b = std::move(a); + BOOST_TEST(allocation_count == 0); + // + // Move assign: this requires knowledge of the internals to test!! + // + mpf_float_50 c(3); + do_something(b); + do_something(c); + const void* p = b.backend().data()[0]._mp_d; + BOOST_TEST(c.backend().data()[0]._mp_d != p); + c = std::move(b); + BOOST_TEST(c.backend().data()[0]._mp_d == p); + BOOST_TEST(b.backend().data()[0]._mp_d != p); + // + // Again with variable precision, this we can test more easily: + // + mpf_float d, e; + d.precision(100); + e.precision(1000); + d = 2; + e = 3; + allocation_count = 0; + BOOST_TEST(d == 2); + d = std::move(e); + BOOST_TEST(allocation_count == 0); + BOOST_TEST(d == 3); + e = 2; + BOOST_TEST(e == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } + { + test_std_lib(); + mpz_int a = 2; + BOOST_TEST(allocation_count); // sanity check that we are tracking allocations + allocation_count = 0; + mpz_int b = std::move(a); + BOOST_TEST(allocation_count == 0); + + // + // Move assign: + // + mpz_int d, e; + d = 2; + d <<= 1000; + e = 3; + allocation_count = 0; + e = std::move(d); + BOOST_TEST(allocation_count == 0); + e = 2; + BOOST_TEST(e == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } + { + test_std_lib(); + mpq_rational a = 2; + BOOST_TEST(allocation_count); // sanity check that we are tracking allocations + allocation_count = 0; + mpq_rational b = std::move(a); + BOOST_TEST(allocation_count == 0); + + // + // Move assign: + // + mpq_rational d, e; + d = mpz_int(2) << 1000; + e = 3; + allocation_count = 0; + e = std::move(d); + BOOST_TEST(allocation_count == 0); + d = 2; + BOOST_TEST(d == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } +#endif +#ifdef TEST_TOMMATH + { + test_std_lib(); + tom_int a = 2; + void const* p = a.backend().data().dp; + tom_int b = std::move(a); + BOOST_TEST(b.backend().data().dp == p); + // We can't test this, as it will assert inside data(): + //BOOST_TEST(a.backend().data().dp == 0); + + // + // Move assign: + // + tom_int d, e; + d = 2; + d <<= 1000; + e = 3; + p = d.backend().data().dp; + BOOST_TEST(p != e.backend().data().dp); + e = std::move(d); + BOOST_TEST(e.backend().data().dp == p); + d = 2; + BOOST_TEST(d == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } +#endif +#ifdef TEST_CPP_INT + { + test_std_lib(); + cpp_int a = 2; + a <<= 1000; // Force dynamic allocation. + void const* p = a.backend().limbs(); + cpp_int b = std::move(a); + BOOST_TEST(b.backend().limbs() == p); + + // + // Move assign: + // + cpp_int d, e; + d = 2; + d <<= 1000; + e = 3; + e <<= 1000; + p = d.backend().limbs(); + BOOST_TEST(p != e.backend().limbs()); + e = std::move(d); + BOOST_TEST(e.backend().limbs() == p); + d = 2; + BOOST_TEST(d == 2); + d = std::move(e); + e = d; + BOOST_TEST(e == d); + } +#endif + return boost::report_errors(); +} + +#else +// +// No rvalue refs, nothing to test: +// +int main() +{ + return 0; +} + +#endif + diff --git a/test/test_mpfr_conversions.cpp b/test/test_mpfr_conversions.cpp new file mode 100644 index 00000000..1bc78f03 --- /dev/null +++ b/test/test_mpfr_conversions.cpp @@ -0,0 +1,126 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#include +#include + +int main() +{ + using namespace boost::multiprecision; + // + // Test interconversions between GMP supported backends: + // + mpf_t mpf; + mpz_t mpz; + mpq_t mpq; + mpfr_t mpfr; + mpf_init2(mpf, 100); + mpf_set_ui(mpf, 2u); + mpz_init(mpz); + mpz_set_ui(mpz, 2u); + mpq_init(mpq); + mpq_set_ui(mpq, 2u, 1u); + mpfr_init(mpfr); + mpfr_set_ui(mpfr, 2u, GMP_RNDN); + + BOOST_TEST(mpfr_float(mpf) == 2); + BOOST_TEST(mpfr_float_50(mpf) == 2); + BOOST_TEST(mpfr_float(mpz) == 2); + BOOST_TEST(mpfr_float_50(mpz) == 2); + BOOST_TEST(mpfr_float(mpq) == 2); + BOOST_TEST(mpfr_float_50(mpq) == 2); + BOOST_TEST(mpfr_float(mpfr) == 2); + BOOST_TEST(mpfr_float_50(mpfr) == 2); + + mpfr_float f0; + mpfr_float_50 f50; + f0 = mpf; + BOOST_TEST(f0 == 2); + f0 = 0; + f0 = mpz; + BOOST_TEST(f0 == 2); + f0 = 0; + f0 = mpq; + BOOST_TEST(f0 == 2); + f0 = mpfr; + BOOST_TEST(f0 == 2); + + f50 = mpf; + BOOST_TEST(f50 == 2); + f50 = 0; + f50 = mpz; + BOOST_TEST(f50 == 2); + f50 = 0; + f50 = mpq; + BOOST_TEST(f50 == 2); + f50 = mpfr; + BOOST_TEST(f50 == 2); + + f50 = 4; + f0 = f50; + BOOST_TEST(f0 == 4); + f0 = 3; + f50 = f0; + BOOST_TEST(f50 == 3); + f50 = 4; + BOOST_TEST(mpfr_float(f50) == 4); + BOOST_TEST(mpfr_float_50(f0) == 3); + + mpz_int iz(2); + mpq_rational rat(2); + mpf_float gf(2); + f50 = 3; + f50 = iz; + BOOST_TEST(f50 == 2); + f50 = 3; + f0 = iz; + BOOST_TEST(f0 == 2); + f50 = 3; + f0 = gf; + BOOST_TEST(f0 == 2); + BOOST_TEST(mpfr_float(iz) == 2); + BOOST_TEST(mpfr_float_50(iz) == 2); + BOOST_TEST(mpfr_float(rat) == 2); + BOOST_TEST(mpfr_float_50(rat) == 2); + BOOST_TEST(mpfr_float(gf) == 2); + BOOST_TEST(mpfr_float_50(gf) == 2); + + // + // Conversions involving precision only: + // + mpfr_float::default_precision(30); + f50 = 2; + mpfr_float_100 f100(3); + mpfr_float f0a(4); + mpfr_float f0b(f100); + BOOST_TEST(f0a.precision() == 30); + BOOST_TEST(f0b.precision() == 100); + f0a = f100; + BOOST_TEST(f0a == 3); + BOOST_TEST(f0a.precision() == 100); + + f100 = f50; + BOOST_TEST(f100 == 2); + + f50 = static_cast(f100); + + return boost::report_errors(); +} + + + diff --git a/test/test_native_integer.cpp b/test/test_native_integer.cpp new file mode 100644 index 00000000..0e55822a --- /dev/null +++ b/test/test_native_integer.cpp @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +// +// Compare arithmetic results using fixed_int to GMP results. +// + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include "test.hpp" + +#ifdef BOOST_MSVC +#pragma warning(disable:4146) +#endif + +template +void test() +{ + using namespace boost::multiprecision; + + I i(0); + + BOOST_CHECK_THROW(lsb(i), std::range_error); + BOOST_CHECK(bit_test(bit_set(i, 0), 0)); + BOOST_CHECK_EQUAL(bit_set(i, 0), 1); + BOOST_CHECK_EQUAL(bit_unset(i, 0), 0); + BOOST_CHECK_EQUAL(bit_flip(bit_set(i, 0), 0), 0); + + unsigned max_index = (std::numeric_limits::digits) - 1; + BOOST_CHECK(bit_test(bit_set(i, max_index), max_index)); + BOOST_CHECK_EQUAL(bit_unset(i, max_index), 0); + BOOST_CHECK_EQUAL(bit_flip(bit_set(i, max_index), max_index), 0); + + if(std::numeric_limits::is_signed) + { + i = static_cast(-1); + BOOST_CHECK_THROW(lsb(i), std::range_error); + } + + H mx = (std::numeric_limits::max)(); + + BOOST_CHECK_EQUAL(multiply(i, mx, mx), static_cast(mx) * static_cast(mx)); + BOOST_CHECK_EQUAL(add(i, mx, mx), static_cast(mx) + static_cast(mx)); + if(std::numeric_limits::is_signed) + { + BOOST_CHECK_EQUAL(subtract(i, mx, static_cast(-mx)), static_cast(mx) - static_cast(-mx)); + BOOST_CHECK_EQUAL(add(i, static_cast(-mx), static_cast(-mx)), static_cast(-mx) + static_cast(-mx)); + } + + i = (std::numeric_limits::max)(); + I j = 12345; + I r, q; + divide_qr(i, j, q, r); + BOOST_CHECK_EQUAL(q, i / j); + BOOST_CHECK_EQUAL(r, i % j); + BOOST_CHECK_EQUAL(integer_modulus(i, j), i % j); + I p = 456; + BOOST_CHECK_EQUAL(powm(i, p, j), pow(cpp_int(i), static_cast(p)) % j); +} + +int main() +{ + using namespace boost::multiprecision; + + test(); + test(); + test(); + test(); + + return boost::report_errors(); +} + + + diff --git a/test/test_numeric_limits.cpp b/test/test_numeric_limits.cpp new file mode 100644 index 00000000..8b32f8a7 --- /dev/null +++ b/test/test_numeric_limits.cpp @@ -0,0 +1,251 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && \ + !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) && \ + !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +# define TEST_MPF_50 +# define TEST_MPF +# define TEST_BACKEND +# define TEST_MPZ +# define TEST_MPFR +# define TEST_MPFR_50 +# define TEST_CPP_DEC_FLOAT +# define TEST_MPQ +# define TEST_TOMMATH +# define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) || defined(TEST_MPF) || defined(TEST_MPZ) || defined(TEST_MPQ) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif +#if defined(TEST_MPFR) || defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_TOMMATH +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif + +#ifdef BOOST_MSVC +#pragma warning(disable:4127) +#endif + +#define PRINT(x)\ + std::cout << BOOST_STRINGIZE(x) << " = " << std::numeric_limits::x << std::endl; + +template +void test_specific(const boost::mpl::int_&) +{ + Number minv, maxv; + minv = (std::numeric_limits::min)(); + maxv = (std::numeric_limits::max)(); + BOOST_CHECK(boost::math::isnormal(minv)); + BOOST_CHECK(boost::math::isnormal(maxv)); + BOOST_CHECK(boost::math::isnormal(log(minv))); + BOOST_CHECK(boost::math::isnormal(log(maxv))); + BOOST_CHECK(boost::math::isnormal(sqrt(minv))); + BOOST_CHECK(boost::math::isnormal(sqrt(maxv))); + + if(std::numeric_limits::is_specialized) + { + if(std::numeric_limits::has_quiet_NaN) + { + BOOST_TEST((boost::math::isnan)(std::numeric_limits::quiet_NaN())); + BOOST_TEST(FP_NAN == (boost::math::fpclassify)(std::numeric_limits::quiet_NaN())); + BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits::quiet_NaN())); + BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits::quiet_NaN())); + BOOST_TEST(!(boost::math::isinf)(std::numeric_limits::quiet_NaN())); + } + if(std::numeric_limits::has_signaling_NaN) + { + BOOST_TEST((boost::math::isnan)(std::numeric_limits::signaling_NaN())); + BOOST_TEST(FP_NAN == (boost::math::fpclassify)(std::numeric_limits::signaling_NaN())); + BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits::signaling_NaN())); + BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits::signaling_NaN())); + BOOST_TEST(!(boost::math::isinf)(std::numeric_limits::signaling_NaN())); + } + if(std::numeric_limits::has_infinity) + { + BOOST_TEST((boost::math::isinf)(std::numeric_limits::infinity())); + BOOST_TEST(FP_INFINITE == (boost::math::fpclassify)(std::numeric_limits::infinity())); + BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits::infinity())); + BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits::infinity())); + BOOST_TEST(!(boost::math::isnan)(std::numeric_limits::infinity())); + } + if(std::numeric_limits::has_denorm) + { + BOOST_TEST(FP_SUBNORMAL == (boost::math::fpclassify)(std::numeric_limits::denorm_min())); + BOOST_TEST((boost::math::isfinite)(std::numeric_limits::denorm_min())); + BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits::denorm_min())); + BOOST_TEST(!(boost::math::isinf)(std::numeric_limits::denorm_min())); + BOOST_TEST(!(boost::math::isnan)(std::numeric_limits::denorm_min())); + } + } + Number n = 0; + BOOST_TEST((boost::math::fpclassify)(n) == FP_ZERO); + BOOST_TEST((boost::math::isfinite)(n)); + BOOST_TEST(!(boost::math::isnormal)(n)); + BOOST_TEST(!(boost::math::isinf)(n)); + BOOST_TEST(!(boost::math::isnan)(n)); + n = 2; + BOOST_TEST((boost::math::fpclassify)(n) == FP_NORMAL); + BOOST_TEST((boost::math::isfinite)(n)); + BOOST_TEST((boost::math::isnormal)(n)); + BOOST_TEST(!(boost::math::isinf)(n)); + BOOST_TEST(!(boost::math::isnan)(n)); +} + +template +void test_specific(const boost::mpl::int_&) +{ + if(std::numeric_limits::is_modulo) + { + if(!std::numeric_limits::is_signed) + { + BOOST_TEST(1 + (std::numeric_limits::max)() == 0); + BOOST_TEST(--Number(0) == (std::numeric_limits::max)()); + } + } +} + +template +void test_specific(const T&) +{ +} + +template +void test() +{ + // + // Note really a test just yet, but we can at least print out all the values: + // + std::cout << "numeric_limits values for type " << typeid(Number).name() << std::endl; + + PRINT(is_specialized); + if(std::numeric_limits::is_integer) + { + std::cout << std::hex << std::showbase; + } + PRINT(max()); + if(std::numeric_limits::is_integer) + { + std::cout << std::dec; + } + PRINT(max()); + PRINT(min()); +#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST + PRINT(lowest()); +#endif + PRINT(digits); + PRINT(digits10); +#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST + PRINT(max_digits10); +#endif + PRINT(is_signed); + PRINT(is_integer); + PRINT(is_exact); + PRINT(radix); + PRINT(epsilon()); + PRINT(round_error()); + PRINT(min_exponent); + PRINT(min_exponent10); + PRINT(max_exponent); + PRINT(max_exponent10); + PRINT(has_infinity); + PRINT(has_quiet_NaN); + PRINT(has_signaling_NaN); + PRINT(has_denorm); + PRINT(has_denorm_loss); + PRINT(infinity()); + PRINT(quiet_NaN()); + PRINT(signaling_NaN()); + PRINT(denorm_min()); + PRINT(is_iec559); + PRINT(is_bounded); + PRINT(is_modulo); + PRINT(traps); + PRINT(tinyness_before); + PRINT(round_style); + + typedef typename boost::mpl::if_c< + std::numeric_limits::is_specialized, + typename boost::multiprecision::number_category::type, + boost::mpl::int_<500> // not a number type + >::type fp_test_type; + + test_specific(fp_test_type()); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); +#endif +#ifdef TEST_MPF + boost::multiprecision::mpf_float::default_precision(1000); + /* + boost::multiprecision::mpf_float r; + r.precision(50); + BOOST_TEST(r.precision() >= 50); + */ + BOOST_TEST(boost::multiprecision::mpf_float::default_precision() == 1000); + test(); +#endif +#ifdef TEST_MPZ + test(); +#endif +#ifdef TEST_MPQ + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); +#endif +#ifdef TEST_MPFR + test(); +#endif +#ifdef TEST_MPFR_50 + test(); +#endif +#ifdef TEST_TOMMATH + test(); +#endif +#ifdef TEST_CPP_INT + test(); + test(); + test(); + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_pow.cpp b/test/test_pow.cpp new file mode 100644 index 00000000..07c770c5 --- /dev/null +++ b/test/test_pow.cpp @@ -0,0 +1,604 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT +# define TEST_MPFR_50 + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array, 500> data = + {{ + {{ "9.85291419463953934609889984130859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "8.41670862661703722551465034484863281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.66781019918879108354226292713799369912745098619466567318041467361236175866573114777000418440761829061824953361563557580935951901405814080757565313129904800947783606850513184296612628910656615168927761935861462770335134108408073175949783551491164949747086136599355880600420490275164555515512645668845e4202" }}, + {{ "1.65291435510970359246130101382732391357421875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.93652894786225093781695250072516500949859619140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.14852190138491736562279120519668390081141778746743826681517181158751264571350304943298501284647564489716027476004029804110782430201351750715968215799574772058637701195873519618784612525011353325208230847515250406858209757415407239793739704829281917272032288615255140733409015874140869835291148547238" }}, + {{ "2.95673953882856110908505797851830720901489257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.30915509717990971694234758615493774414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "9.16137091634529046709182958669115589757019722367818747705232600776240821857227718551873067599347313641575272826830417174591636547915061517391300131065931465784194067711359196329143298499263726513131614582697830908424187934868152998838921216586737465291051289708299364409624364999366486746226077050764e249" }}, + {{ "6.08581487679821513288314083212071636808104813098907470703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "7.65778516457987279864028096199035644531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.27056224622668410282266686919173718609676411389459024877282902746284033954589536288634973757568176464096389580016576960309487231057438455595655805167665817497028295657665023126747065443986739792258870082022889306909488139458069146748438042701949551909468708242176394539901613782225328586614222105675e-3229" }}, + {{ "2.72264614486854572561469467473216354846954345703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.86954434555903360043460637029966164845973253250122070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99366682241962146368589809577120011723198308450433185299366732500677873637460155970547267099719914327909694930518383012498797681761846242526638144261306834523078708261122471803832490341687603813336927181436827534082878781252668704774445437548691251936499670077735883150461534069270846997649139259014e-1" }}, + {{ "1.15866069758449596882599053060403093695640563964843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.91253262757665787319183436920866370201110839843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.46868982488456565751167443881314840659743514173491612010770748877346398177489343237604160804413931931718223750314831998907846386274396179552445359933868165880372381338724806279781831953896898649659594755834925976964179275873971118494605322798850925802574178528777014182338769959249415096934378557388e-1" }}, + {{ "4.72825938314130529761314392089843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.22893132739781236750786774791777133941650390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.47245157077269889091085696140795527282280334677569169487973419233796250189843816560261965111196061138868370890204338231535198008079068304184762140493830719955323588998399173073261634891767823614143691840392792367527470000847416054709559319143615840412839768396194451923527439592939735228732869467965e69" }}, + {{ "1.29556572255334176588803529739379882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.81521083299418428680382930906489491462707519531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.91729899451736210436889587963352494969987265352294254442114149825297350300933403119961677078224257818567229354512108221647637427508041941647518586565006416113534560289731038664091154857692367872604020422463457596747145816854139701847749519264660326361171185139298113322096978245544144264234481020815e7" }}, + {{ "1.74305909145137593441177159547805786132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.55727459709495003048473904527781996876001358032226562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.12324923143821767715038683964417533829057341785931080679952341815408539775130405061465897612861320390765996927155081774925717154208894105154455487856335006846587865128269477586014136390788140643457017602926503892493119037260205017744346004538379559837051387829449807650507431889923695496342461088404" }}, + {{ "5.94723096329786358182900585234165191650390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.47960584914021491681479503199625469278544187545776367187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00101355895664265703253905800820834352012946978175213925289823900262226487475877307647753894219794796436589570196875943062842928843129407133278574235943906905626144071246066853301987332156463703818534415183682692042219695734377740067313312425523058170350486981674302932951851973390826740834796342180" }}, + {{ "1.68908811949766600121487086783034214931831229478120803833007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "7.31583500510190560817136429250240325927734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.06485337562137503941405427253471002412719863672407294570575625371322654317127374055512455786988091092329605000808871766177184698431732837248355728401235010135527651826220232715652024742668291949645619992685612328535253252695622896976648954823150769316159100729259724133493553742448044299816541989455e-423" }}, + {{ "4.72470471679805708838453814912838879536138847470283508300781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.93150097545414496380544733256101608276367187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.36613880262643802742756290736395850668317512466586871167321608424137867570108690626258507320043808302565319397131444616166042735793688809613906106252620462557968555895414582976985576875374557668514391264049547180886976991031038592004458693177738810104222966751846844587127740341157319952915743398285e-103" }}, + {{ "5.42042332941097132481544917936844285577535629272460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.51174849138805500459170616522897034883499145507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.77171703127754502681310204125715941650801721154976863870699221072355335125966565182666925044598746890911836338141033359039531496488403405876863230608143768785806156629534985369811294999635059473513624761915818310578096052710097713441725036078711101258417410421951107958524860020565804089659046743943e-1" }}, + {{ "1.03814929656497190180175493878778070211410522460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.02775539432865528274851918411059159552678465843200683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99908769642175788386137778958539300137602918424410284952085874015336769726750047569734816766197409755257562872230833189101650544474710424482558254479079319860825174137124403380959665595507587367668848404286717760343524270837960434045414179621713212480893218438355518348995643697164109731552178914851e-1" }}, + {{ "3.82635641630229656584560871124267578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.04696645144304778529686927868169732391834259033203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02545504718938094372102791727911930176506035001600018053644429991055918696319033730794852043021666923875675436795843500904336366408589219201909169612259476814126333181168932741070039124737361896932592045285182764869916877379718622220890978571031406624988992549594836404906978120992311725853941493659" }}, + {{ "1.33672486906479148771609288814943283796310424804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.20701621203230615719803608953952789306640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.82608741435940656086722594561546646099634760918110959565977761208896418216166536561903222226214939613599640463597249764023513875896636280664458251642404729724932181291845871312202787897768372355186920789243514016890287945724482698867187289280837997988218972650355222505584789955736058952829050123955e-11" }}, + {{ "7.88803854908014727698173373937606811523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.46278561425722486433187441434711217880249023437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.72840141730863663391876877521764355960382145920572562742914162972208384723706307292705275033115082012368548682595775882643927894139786449383322664316773126131611883398659050539189893838100041408464889082404113404032943316931275847874983317572290683797208861989532362102600980996636385789799495020849e4" }}, + {{ "6.02908445011699427595885936170816421508789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.73159824509963122807221225230023264884948730468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.06403097260563050081855800637166449495962164712719263330810086375883439970326530663445685346228862337912240907582664457942174627433334293660419014781254710335542481599007896808711916825623070383641755045318205803207383228319360990374222920104547227487223738392731388028498147565624523546346417715655" }}, + {{ "5.21882079270016063787807070184499025344848632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.00797343550563134328967862529680132865905761718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "9.36552325485277806964373331313098838333278330423455390715861973295876349888773267892681165876113176797510574847645252615081953879524429911159719101193921387688552351634752458416166446355778230365755243829643708299147847893065939954861919388676503519612640610354931769525373202729617723199328630093636e-1" }}, + {{ "6.21172003041995424155174987390637397766113281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8.60919435020819194006019142717534009534574579447507858276367187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000157241706535645559625081132898066253320364132991765749046567536915342813631920409642832019004224458248512335711478395060579077427182783938451114029622700384959716532968625901664719629811957905865676402174328291417935322613778738659214041802729741480722967793087943757739011593472415850478420639" }}, + {{ "8.93348943116835901567807098899720585905015468597412109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.15322293979125788609962910413742065429687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.91021563983953636397848520840523223624643742835964326188016961937573012460753870407293657436708430593126320103796954182972032017026192445957161066771807675200884423939605981304732630092257312925408813941089831976477439943114677798839623996214029155361569909503935179401196449493080818512569086682097e-1267" }}, + {{ "5.55105519395504379644989967346191406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "2.20561294990389011871911861817352473735809326171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.11282177288045201072507504088709286277978249266318510332909847928909226338145185595245293917086320817076726850666066198249106037631163063795831697507293260413136608221812252367908447186422344164553977681855896096040438700902356349275031836676568495994537852124264298684105398360497193752327260914137e1" }}, + {{ "2.64139377644600310476863391784263512818142771720886230468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "7.78537344498752810831310178230069141136482357978820800781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99179632299559171314926709030763809736309139005374052895886931807671532458904052556141342139885810036321222015645710865315806166952058325774560966552187527103940189373824279065702873017246336399071137612269219545181070886990906061668084063703411460250321467244169857420435253409159030432098292621067e-1" }}, + {{ "1.04207364225271594477817416191101074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "9.49096324860676521240065994788892567157745361328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00881927761618177965011845644574187803759898330801723609976606642566910129111150781463974721119043760111173993259232795682413324213317011846206782754096089290427628991647487342082014619699610677423897602146820644840945077548746946762791624180147374361784328110343084702444523109612274014821745626982" }}, + {{ "3.31519320566263809429985442989163857419043779373168945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "5.69130350190431280252290058285780105507001280784606933593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99544126695324189746630737456946723361046661345027805407888971023026631339988056392642825478722792254481831582440796961181158845762815786131168245934078509438401554967954057934563178474479427510608187860234090448388699710858468168174057416883471915845617321874136073232354461932587707630236256378020e-1" }}, + {{ "1.88337177923367888807137937590141518739983439445495605468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.32540268863411711208755150437355041503906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.75229630554212330195665922771148699451829771147200356624805857657236782065140481467338634818457146889580617522654929450001033313425457042558128784684181381335537144806647956114444609625124141647264003246426211941949785732284342909061255617831919446477154897012961652269654460432165747451828975060062e-1612" }}, + {{ "3.95459290525709050712066527921706438064575195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.67791671378427392183514677004296800078009255230426788330078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99997515679857005761440503886095927815406391244413835291624899797364615653895949902813000744851723242602512239539568754651988070279277456656779917196036522934849059282355864096704432345340316634144618927930200708582994637711792811242475638942101629267185320507818308058050356385241284795438747530570e-1" }}, + {{ "4.18765706320910169324633898213505744934082031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.16291806714740175721090054139494895935058593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.21448401185251170746394861880464242649255630391558005989017991140563422704674077045117022763467561974222030061746655113958910240758539727055748249625892285904547489203480154655618632992990390332430221914382681227157928848406067945057161854616129785541408035327136685741399621377579757754012545382969e1" }}, + {{ "1.28834086985551640736069600734481355175375938415527343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.50705923255961032891647732867568265646696090698242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.76932835372685523370171735287063726416767225734834615849134547109660778793799398169080725972094573408844765674179657286895933198717192952354877012591779343412877647689917686841315165602494901218010719779271020694334581849406783713948998204010537229621398578990055098138781426451663477493080600789821e-1" }}, + {{ "2.09720612044679288743509459891356527805328369140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.58040082173553630973117378744063898921012878417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.37769288971832154015429547694831033608424622845142547611771987181607855769209591840464089347717993026475816138178319620101164703046235086673631394869476080594839931563796671833715053698127488579638544943331524253087769152813629459325853986427109398088052746438762088357925061124187186100435982047033e-1" }}, + {{ "2.86348409095251425380765364359092473023338243365287780761718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.66147340815298694138846258283592760562896728515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.19957610695947876947018322120150143406142221469373757924519795345150006977773403730313023369079301615734601162566867121616810596830759956044509310651071485457850172811241087990683705383118703983140409701647142571470333867908682196499347683237058377349085352136214854181401946343510795949868835711429e-1" }}, + {{ "1.43297873345568077638745307922363281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.41681240009364082165985165850941029930254444479942321777343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00016822776212044529668140515271000711944889104836686684000447554242511520504646895662976301872271981369559245931879055379226726537073846553544561947637792091890791964244339592472180091648456672557297620691698497967178088487062658421331764320606009571740080394934111049676474128724114098218934644280" }}, + {{ "3.60098653144944158555063040694221854209899902343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.03376339210932499668160744477063417434692382812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.25275538744154336055615419863736730746930928726962752118772852620054361808569416481449220736645770958820155429279907622983889720952174836443567087662689941130263300184594808723215176724531461369529244321399979413684112346655770810116945662086924599874483949305102682382993398648882273436739947930631e-1" }}, + {{ "5.29540201171499924810703863187200113316066563129425048828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "4.56136148696097143417915731333778239786624908447265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.56082033932816309081231125453071826327896674917466727856568147854623107132514590973229074834141556000908164346345063684708226886531162257152516511661460364047957606893852284251293056880030888612998267350454535860387161852393199580592248818623376237183284153405740445167284591706260229351268548628924e-1" }}, + {{ "1.44301800298425852986383688403293490409851074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.14308392953894662376346236243307430413551628589630126953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000261963485792416853927136569198682383793838454319729684734973539039182323306199235318171814360855994012568229358281529883676852371448365509202038288834881570383584403906835594533516647281713968932211752518665238323196577224701747937440185305151190908616249351775361542696295892178890063882257116" }}, + {{ "6.22803809629584627372000937839402467943727970123291015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "3.25094187232484732597015408828156068921089172363281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.86658469541403998034943500870243069476823132486007751990824694615782893644279173776512596334159142603325455113617967643461939139102971978114976150505918018758878971981207590718138194009315889095960072548673588879789986017926322494375432269097377546556386620403909103214427884440798206932883636297352e-1" }}, + {{ "9.85553619558515492826700210571289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.19375835372379413001908687874674797058105468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.69327012293708811121144971175263370083910101169553278058859848877086709080419562447585355719348842415619132355236627485649548952876411849102018675375354238273102815474095986357261970461229247085634624604985094330242448976955585994530902647027597520370418448678147789523361182103563378206595110636366e6" }}, + {{ "3.58793922164308502070761974778179137501865625381469726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "6.91828844531360287462007363501470535993576049804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.77635990889125108309690852819112724262223736693646969131631611067612444282401471024845889526676870050656945639578159737127915466435929600368572355785708484463627825178182883323088006398240693308602881027224033181200011330121428663774743869527395379215026638702157803494202819893449358544841576526785e-1" }}, + {{ "4.96146848614257760345935821533203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "5.36919182658175953015700088144512847065925598144531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.57915370211935194723362359441601671775858730114448762856923579370262681814508708674839371719677055754578289843591415190008400693094242195743768201495967775525358591358166609121796030602701836084062498854380733868656008519376928763241674707747769169741392588580100945268376807756367217092609019332523" }}, + {{ "4.24495621335822494657116776828331694559892639517784118652343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "2.41273133041338017079624478355981409549713134765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.05650148888948869811331120941963319541414375806822687983830138205938420862200064078576598469877831249406211581526927963122105281131255004573845222711684347603254852806653766035434125383812586900316395999300527269121533046942253679078218107723668449508163238533047093749711627477323541829484653131292e-2" }}, + {{ "4.48640427032238338142633438110351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.57545512531989570200255390552968037809478119015693664550781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00002050314697607659431018359659361183713303212753613120902527904331498111603138394334757418054814218670389608976827498549914166555768752494414195237102560486571709642923543196007200071132086884670852209514113439317507321835737223329599950365222037362534859303381396326717532288233329927808913598785" }}, + {{ "6.49749570902381674386560916900634765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.67233186866778105184039304731413722038269042968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.37780724079840208711014533649991541109470796504084314835156759344214993302863952807171583660778803863957191115559320339273255056520571556246744533838811694006166732957726755945662570959533321672076547914911635593118101608294069731654269467619949055336628326621660012876406202543146880009002104821553e6" }}, + {{ "6.09674367112420512171411246526986360549926757812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.57044841435982965565515412365016345574986189603805541992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99995606813099499267634389464438683850041060806908350269346321155672893761130577244819124593817984249660934044363638948086248241297434338993626965911693249278796597285537898160766381999495115463474497883772569241592760426493272254012575287314033420480717621539078495596903806489817283498263020744184e-1" }}, + {{ "7.57503455130639213876975190942175686359405517578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.25659927896368083096931278497265793703263625502586364746093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99967576340235983529748322865757677186118554170023614050204881657758768441183672920424294568610952334609747551908015545068832481235294176033402023954402315837530793201944548984799957607361928025651266738940647431602585783131780321746876553060340085541214977820888348264644079307051095179685852079945e-1" }}, + {{ "7.23094922542264449683013793901409371756017208099365234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.59957635240683257102367598179171181982383131980895996093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98843860017333489092110505899347130551976013147438321970353479326257793437223848104429707854561661175450570835038515201752789245106905767296900600611401551754756721658819816241278926439311942572630487380703760937536160330693843537976099522621025621041857521661138411993182809798954282325807746896512e-1" }}, + {{ "2.22347866336470469832420349121093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "2.67574314969844628819828358246013522148132324218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.45597650920700334896440864288586774552136744768533970151074149218272851829624764505239431335468131476208480181217427109189696065749387968903474055278714181692867425657254225967806378137696550459591101296481511902742572646395696145586249150843548288850238158312747067673295059110101209836587291678717e1" }}, + {{ "1.61969754204121987178899289006039907690137624740600585937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "4.98433649539913870007978857756825163960456848144531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.77061455335439039778043359172467746025200146785630273407892949860314031306268447375871357416922980298986141833641561954857127992214135487677696097641048847861017455164355255934271546462888696419881919311556223441720520985938735112636787538160901409982382930452852563601752376961873325250302513132303e-1" }}, + {{ "1.10785802837759378425275258450710680335760116577148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.18652221207551884308087353225857896177330985665321350097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99946575396258084502018839446238846584110705812867877643924485585779113197512036317728340100285410504878437697437320927763146715271389949541429089452281046460116468251613835907291530307473134875676645637754443536935426771393775580503285493873005924313301673550096584687732186248324962291699197441007e-1" }}, + {{ "4.00900856150933880290426758463695477985311299562454223632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.51532437768501453796091832382231245901493821293115615844726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99981169291887424157759932262067246066753044936086128253970315838989839817149914187581608688565806547274970455207936904774502513857569845689591879527047150474914557088218340646463900082270385606124499095033110795779754466447281328092278318076549095302554108789079991538595665731579745334006426859960e-1" }}, + {{ "1.19021350263737038868705475636033952469006180763244628906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.68290288542928294646117137745022773742675781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "9.04852417540620009944566041453719467211390230149498516011819535440728246929538100576552383464173953438153608848998091884909329517100819960017904887302473398843345408874822800579053111675353115760245493436345787702548498655314405766561270926511701674435330529881522800583133171192665005622617374333010e-67" }}, + {{ "3.24276265467208501549166432820214822640991769731044769287109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "4.45408954542178808083674468321078165899962186813354492187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.94386254687686946963322383552185492075977337531973213930838015838274376322044860137122810561067818353529641305366066211688682157075369267213623551618566522232634253178245524174116891287095569137130501326353904791232655125453161983083517758472031555434930112729665552915867163490039363051308443099856e-1" }}, + {{ "6.15810616566200508259498747065663337707519531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.16615056291079111083774932922096922993659973144531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.84767212442093730437806115126470445228033445461780019945996712538430276008229376762120777978183512697217805509135802054380845495119030204478634136438561790634012659775242132306345870420149133737299397362388964674004273429551607587049902912378874846355087545159480302396357641147726629312485985544367e-1" }}, + {{ "4.98639800075090606696903705596923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.77610720170316863455745731714685575752810109406709671020507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001921243238237193183827489311170506446717993399056537282384027062526108337893488664380391849139457202726524784919352515463921911589077429652463880766791641171380378763553978844617450998857121720620679684506344842701809891676387117033562056914974016308650056416678855410514380179891286420315463385" }}, + {{ "1.39829478131476389535237103700637817382812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.43499530583138337064275091847775911446660757064819335937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00024882796344591385461239880845260384691776851307067376321212831043330119768926261152601978474535337925904198175128520020096443925386965960197623129024285407478015708065567539370247164906581380771634920314388644089046167410745320267558557473972499677590220735439622489041126850128421653983634543138" }}, + {{ "5.53823542724402595460730935883475467562675476074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.89513503025480504506072865211763200932182371616363525390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99887300842861835164017418113429559930804468019069798605482088141983665217815479503166341320807290829070352700865762573462007338287440579346738382811838185553843038382146930720875234411175792603385681200743384496310942148612050283753172718455515566946341846284557394785250850393323918755270713010620e-1" }}, + {{ "1.41121361373833846300840377807617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "9.98754187978802221437035768758505582809448242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.39052029796505087174799036572060834290339669936231503015871931355721722463161747207749930806516332386763841930651054884331973674982367750538370231486178766251016302345689298357523496706436693633349722362506875465430935461687316908940273568043577086452494403668755303085058972545116855832701160169233e5" }}, + {{ "2.89668134268413328424353336831842398169101215898990631103515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.15865345460021584855780929501634091138839721679687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.28205556117411408113652874564375329933423424935399606070975188165013549346043442272013469493594176280229509402715241333520310808546934629428072668916547032154136142048364995378685732366063433675907163954131129548865718748066808278449447269502355535592014434886553141414017802588692926998785625006881e-1" }}, + {{ "6.80370452266789652639999985694885253906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.55585667546695538554502036276971921324729919433593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02281231404359612151527353897929180348478744328820333025332541070807332704656155540376559985312945856024293947964716753864592850899748540597581561259020876390111605898100116321942106603048757052249826147692127068934907088939143183343054183800841834132202006495897859489577613318023621649632711626369" }}, + {{ "4.62504113144313121035178237860918670776300132274627685546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.52163427846739888679716834474220377160236239433288574218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98482342652643471998471847918276729621115291527655407478347392440646810723671728307137559792389469491363165496772939188998042052370839020230988405367662374022902953797332354477989367493245470167443057076807839721016298819277997067517609396627866901281229526562169916899579412733467953808761281274902e-1" }}, + {{ "4.50822932159575771038362290710210800170898437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.06839470475542444583005874392256373539566993713378906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00407725957483558818239220892424948692876561612077691060007144800995480352451729509031292920021843587131856132257906499443064130817064638818765366250131236399994854411601609832821870319397908684888708832193783247348840517389795509100198832759307607589651546707827898198086014636944156848700425178047" }}, + {{ "2.97403319008989266980513832550059305503964424133300781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.86474774881857552344399664434604346752166748046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.05563040619657475424023632617553458144221260647471757349470769600263284068856263065983919485584722356671096360406091314847188039821446085937501687228128412834520625095444394738723676139779119999762553228944695777339743845083698817002881418226410778165865331625883646946752393289471811888730325566680e-1" }}, + {{ "2.38325080784211650097859092056751251220703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.66302465811868707690202029425563523545861244201660156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00914434741735633383477956146627482536171366958054332840551181784200344603582400731522959980543848217816660950109678863255860871237640121402147335369863635255623422637578873942180607947824451388135749116333642343887949089848641558138185462358132315292011403950110303162349396320495083970574820485984" }}, + {{ "1.71423190201370800878066802397370338439941406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.22776453453089651191021403064951300621032714843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.41715373496456388539324810858409600194977863833255435782643057881295200486872481370727134110261522844531904021514609023835218872201273620577170073750362820523072032985530745444647038907617563505404059737966630343043214665700476103118304785807103469358517871674775523305518419709923690374745267779192" }}, + {{ "2.24202183750390773639082908630371093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.88606137138923326407313751928995770867913961410522460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00356204426464651318381353366766656275190463831503522239513652128295092897680949875433153708401966246976000272332294389517143726474038495934684353460128449357504408039179941027444904612222505017810534008770086553370099204575810832664720970035523251219105643922854038752127247330051903230606763080754" }}, + {{ "6.68254924276967532392745852121151983737945556640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.37453434835288135218434035778045654296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.23884289615444976971058885660437787480627352137562427420631247881049437291942148842029267007686370097695430731343288589752635360722257432905786816202418979845289181427172830309982121527477449228884669859681103900842455539708329644639171581286590973017189366587396069226010533102477610964537380565038e-6" }}, + {{ "7.08735989603501259637141629355028271675109863281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.93170577274373727050260640680789947509765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.22994581178880428430588361219833883540463488675474104323353907511764504539625188516288826354093370529125373667749527512470360034116957923611728143647053700596011110669882224710437210488847861184277118067955181730553186100384807049379684590737156995709498402541295775367296456895644229479101255193586e-8" }}, + {{ "2.32014942323958166525699198246002197265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "4.44810310131192876426098337105941027402877807617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.41156739924941071144222113991630683194620198146427652318978812945951687592217439817665385168004660248141475796965481088709894832854582569992290051260681221672250427616673943995167609515610097891251991676291118804434690243303234426750763059520585143335380969303297852505455054177640936866538646738978" }}, + {{ "5.53282998141260031843557953834533691406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.84121602625912601070012897253036499023437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.58373770974866315239700400474362989477383658235694014601763955308120813900734144800418886820772189374330395186134971653113939250757648994415649668842051891937875262317539557069792723676293862948593761228728392700591159530165592758768030540795599964339740660316188438257430600649159884119157424191581e1437" }}, + {{ "1.85718777739859418943524360656738281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "5.22760764621501818278162532216413183050462976098060607910156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000634214788464577855189457084479231510812185767194037441581727975561469887723538341241488476848396809344125019310357146729535769441778199276860378224675705997700022744347653159656289098028240954603207536444605258988369343538458427994444681579339406242882282677673848923548267602318784029338545299" }}, + {{ "2.26509465497761368624196620658040046691894531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.03762510179397637877229954028734937310218811035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.03290580019042823129797947218377400320349309579887379648069219653044521496312022139633395975447973076157177628011296170468228189168841156259900536323684747126636993787966799478738521263932697630770091216225209592893137197359045523997671979624680066252774430678393930591603773849047796785558663064178" }}, + {{ "3.00476295219746433740048985328030539676547050476074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "8.02409308153823985776398330926895141601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.14136997855533491337740509094908136487500777275671775674006769752964040924959289897651192452522290539206601428332553008348132654735739834724305690164751538343877568881013821199733121651153278576916744941958595422652696891642421407236449964345890318648778746090208231400439749942969896805715062234843e-203" }}, + {{ "9.70798896667321969289332628250122070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "4.44245980458260469880826804001117125153541564941406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.04162803810086699019811359451605453492327199203637588333443087016790236547076001612983024940969264195708947484110311219661303765376669460085704437741732903824466154100734799424439147057676949660911617676769474501254927589549167841876728171722481679869607753266592648983928705022178056753619502736504" }}, + {{ "4.66389224589813756668976729713449458358809351921081542968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "8.41598683219974930125317769125103950500488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.53382042139791789590459891074340066702060120383660058981707324170432197791546635984529280576877432127625617337120709804544743161881268886942872653531280982977576133511801284796672543413476367564502976743587063883733930418435751755822485352709171649159924126024328941448624940766411726855902924670549e-37" }}, + {{ "3.59808415633625783280891141657775733619928359985351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.89106070923696201191432919586077332496643066406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.11957324795765157901703029938063916662894000731995996196921601505519523032651152137148283098242267387419838627536448762986353433569901640648734154364900058234967711292575255307936095926242393050569604396410567616604312846123878721000606629431359673384574670669906697802557686478096291498804903738631e-1" }}, + {{ "8.29546112810515936034083672723227209644392132759094238281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.58324466499312066503080131951719522476196289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.86659658288740565122000959721270284304946720479579271651550103638161205367495371607443353257219806398111103943515458202894485596325631197266478165244814107159447017816960534609382148164169335790367935277372018345236031109996214855557877416239874683021494253068006756484498147004540748744410389570461e-11" }}, + {{ "8.63334593891555979183749514049850404262542724609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.53080323158965114771490334533154964447021484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.35233729973545869852697007160756749812975339497681040282999017995032382608550729201580422775220111291799102420635253476809267746237352183450521514570985348430714476644398637263228584608977432119909919809882847191196859131282077491115028311403034792745466352775458252803189617423439193439791933123479e-2" }}, + {{ "4.96802530016260956990947761369170621037483215332031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.02519683572433439877613636781461536884307861328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.79130174131074712614824707606461473196424333567411409743609116414751816130489331857231684597817414740294362613028844768413127008896909984819847802879905875872491406317289520166024819440680050252863090346899246519659384416734528764367429297819383807550500609868490474715994290375146313368129823880737e-1" }}, + {{ "1.24702033554851823282660916447639465332031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.71070595755497723185201142115374750574119389057159423828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00004316789477874277620263489613820769653924396429221925198065527832144152145855155330213971456389989525794479500052652310504867952437063466242776820964127214900733034755428153463014611408545155223418498794841462940237893200540509678171081868776875097700422657888013910264387140255547155547751726595" }}, + {{ "8.14130989781463318757936953318221640074625611305236816406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "5.47674360353472167162180994637310504913330078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.63199095965818056903859668356569903606584619352293451010588563431807635376986054905897873784109387681218165026966672415089273447045333707684197569751029547891913778442699838628510300753325723159251992398807517774034918042863197611983714480066975243968618918488213538490759809651966026386013669113012e-3" }}, + {{ "9.48316047562641761814461460744496434926986694335937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.87318705342295180847622670938790179206989705562591552734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99986164907695049446699147999970503354260553000953839878275159076458261755428730763560216631851642537174133195419034054495238529976374508256949441111167727864128507860277033299044051865971449902820004978297018651282279654117307535005136847959876138249613275046667240315151303933181873427450473536424e-1" }}, + {{ "6.72439622398628665533859560810014954768121242523193359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "7.25371945127648842799317208118736743927001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.74287216286274945633266572714083322962101975717027023442493643122162512912802620909159732325958549010615659395950026917825109006470507725724883444926417334797999132724229966674370457592343778072797597317430071335665732334697884217471229705559230148495486170835726019893708870900510074940623722192258e-24" }}, + {{ "2.30442309265876887366175651550292968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "5.10077615004599603520940576117936871014535427093505859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00006298512189780533426621327292231284630240394286315128868176668180396156679505765231684868863847590833570938788465357619602169740491681317033999860409913654411707265663879954547321897801703570651803262843624273611588702980486012373865440788314427239276089286730821085936329475836740228791493079509" }}, + {{ "5.67608898683707252530439291149377822875976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.07683021912563162914011627435684204101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.67068196412266823466861212116241893055807436102731155140415238019317223182255528301301262470626159261154640191153443230288813541880287940859066915763205210708548641176944414442344483827370453800486623574896474317715521007693847769491979549043149389934860292588058888100428936865217794693086764880012e458" }}, + {{ "2.81337246606456581503152847290039062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "6.76344844070871521052312758115476754028350114822387695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00084899099059737772913859365556118027581054407285954758329055990529529377511066455820790791091871502993434775634942750452313898053395589443975739777882392931281046995883876066279980856281434476038018812014179817821871586805042023183706725376177160577170143175806815414662475357051404586743878413781" }}, + {{ "3.34983523837648674431610729129715764429420232772827148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "3.20852082105692326674528658259077928960323333740234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.74653990782509243550836183201075823369159155519692846798314436930630346572690178245424014813711682670551067058906680367646181984756645025448347553573937829174199564122446362713993201587207768412845129431576839987405545810458778769778400165994012026984577717831659943902405397254874487260228557294263e-1" }}, + {{ "1.17365003664101777758332900702953338623046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.78053489600925995972602322581224143505096435546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.05893503437891990856263354837986270829833882333366791751057714437977103925035624856886729661425365010268503431934637684230477655839134293793513971115798026793973457123299079643692631311303731259185411381265912635677151301389868547814580071368806352687212447229499485791883769033890017890187866384697" }}, + {{ "6.35473191480731591582298278808593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "8.15332646258649447190691716969013214111328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.39785593586175436998336047723152633390674636830187065022507274459265394076960202352145842758484227495355755965560336623550772098175134115092702375767668586879200691996181864401350579269221993542974245130770033239773182375358583651870979382999043883377805409110023459275245515025837447884289450716490e473" }}, + {{ "1.20953010742292040959000587463378906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.81528620999166889760090271010994911193847656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.36836082188852137389175804388074236213762814888145199618983165421342520318145120542719392963440700570926350816427711317556249274733873103430368341047528787950522843632555485443202700694068291761260828423023146529348899979040923182831897371799138328552240635790031739904574931369069808189107688786563" }}, + {{ "5.02826864423656406943852203994538285769522190093994140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.49148497614115050149963259684682270744815468788146972656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99886724184991506266822294352662914256716265702852450641368490227402118731911016182228523518485801671330942930187800995820804252420406598640376923122551567922827288661396415930336442260706727249870079649992447995120206397679683465259479974096061438201134430443691684817587750638183840953282722156209e-1" }}, + {{ "1.77623605706485581789272343300467582594137638807296752929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "7.16881559843790408872998831668610364431515336036682128906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99216151571584206550599285631558723279674057106881165894202136106399680298454020164284514110193651012658901118782805914666290560642145072003861919887611842296547047036059520963486973019219177746829500434614825844519776793639037139709040279058532565912742721673028532604681375807832044191447365386410e-1" }}, + {{ "5.44470752993507289829722139984369277954101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "7.89424994358623844748022030382017533156613353639841079711914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000315551756552929413349733123431754994533967419962917545562731445729245526256276165331606875912022797791137395975129631042701829381104269734643785979371368397149024305719491289967486350643357572991392648348784068298353851347894101762457227438358667841811859357203913787202416700523836489423208926" }}, + {{ "3.47952865539182312204502522945404052734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.70647055379554400678099312926860875450074672698974609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01003641035516199003729871729172100472722683758579980406598003587323081240911466133797745466321375213116846128724578817241014105529656120259049841543565831847323023771528373536119517374544673647922841984354734790648175557634969225996223997613913923117328699599574593399806697328078695200917124733876" }}, + {{ "4.89683247131728754952817439516365993767976760864257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.96528625490362656162875165666292787136626429855823516845703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99989546369402488423594127072150976413227845609208465040224219805251052465526350038203035493184013561718362361567469358800995276604754108514280603768744650567983276404672018483263585666869718723877857972643772304671740644914409892158811218430582592069739462405196179208350796857344173822141379782399e-1" }}, + {{ "1.46846575134083542901741736841358942911028861999511718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.13961295777929194628086406737565994262695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.25155431004176641664360564432608271749851863826540763464893400702786658931519008803678187122457752047812131114041410952546777155616546380522319343918668230249104290662019435519965989945104554644065424460926764956490748710036580200886547368376656130754697653950693222962392418484839778727280176131769e-7" }}, + {{ "4.92258328635518438431972754187881946563720703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.16701285749932963387021089829431730322539806365966796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99846424401823072211356827414998110501335375349159811161820098061831954942111055007312660415928636319873898347702590642507419097876493991759663677610295879480797600223758201686500279349159643821096880668703139199785910150322740521690695804135686666464835791331742866153491003010427701847514162106732e-1" }}, + {{ "2.08891842024441984904115088284015655517578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.37451123552204679256760755379218608140945434570312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.51853459491101499462028153198307960464036529321862426769066486207166171296494170498179583135034855145454026518293079000045567402865046530341818676848400774327944796661350087157800975247279219703171839848135584471839442165788564723636737356977396947188532339857132058951624239309379955278406455872013" }}, + {{ "6.59693951898326247373915975913405418395996093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8.58390504285117244415159731829589873086661100387573242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00016195756688330761491474273615136423552556614577036197755742996689336001512360595235890000441982158893267294826116899101351409093661584157256387065246323209052057870928088601548025462625595893993027794606583868972654751596093207938303600634384394989635869479864226583469214082919105133232859648980" }}, + {{ "4.72190302282203920185565948486328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.36872614795644276242114756314549595117568969726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.36273289377674003549552956596428296006868194528902491172931330043916572933784595495824585583342079403134944318241053700848989680616524963231553615168899405338957973320487490472555612135391925458093520067531657179731576065041675903036737870428047782297012296101361469066116145701281560378942697624754" }}, + {{ "4.82034977757478931038870317848932245397008955478668212890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.20114163951150231847420091213507475913502275943756103515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98806768192609411674337267672424056960083232464271360229113542018960233572696008296128150338304172594110837781004501757127999427554595909914289685513812993265024374119615672800606621652602006481141937435665444874495693840170640030665928027259502446424921700891997624978473239252852217099622859393453e-1" }}, + {{ "9.54197957425642506734675407642498612403869628906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.34304142023469919031697372702183201909065246582031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99984326565139803772938990236401058117431661922045573846220380640349699832779123098058540753008622857674232899802697126593866411818203678224123515319186907350469596960547397261912465753250671926347546302198056587430826863955515669743258039245240360599418185587449465990312391796474083173534248199413e-1" }}, + {{ "6.40960699263738433728576637804508209228515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.00816732049831557560537476092576980590820312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.44157504422123306075307680246115279780269010737951173392922320903011026254261224810748434749033392788723902179648854339741924679540874536758451693815806813776859218948113244848659597589114467756894234559650445795659560796369660440795499707193716216403592941616722628011042403021580672267269382135734e182" }}, + {{ "1.22311589009840382402671821182593703269958496093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.10469349157712311976231589483177231159061193466186523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00004238976442526402787977257335501538186147626008780569692886964327726967250839556988250363044075945205489441982444641281650300897861533023502296756146804366735904879346020295258735438264424281840920414740589412010520817925020516062766522452589181209496869654998063536725728358771467633669371863258" }}, + {{ "6.39291118430208007339388132095336914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.28391975830675164615968242287635803222656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.69505481296349945509651870173004703548467117826619443587513918127052944692060859604078331125022112009253571107992368448403956917792261351644585277417570509975725723863004283151424512684410008159602519982839123505049564570077423370661622862250195728714873045142974264003278199036815752137105673556433e4" }}, + {{ "9.83190653233646116859745234251022338867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.16849063361153184814611449837684631347656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.25770980590636267172342833096299211879468172398651157530921609762966193936659345808702337762714296668889853763786019297633422123145533613492472992798929637639386760407400078511978818609469799050619387136981965857651597610392961103496543359101531210986834447630570812748220097342632073167798940478519e830" }}, + {{ "5.47317500559057634745840914547443389892578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.25569401906009264768826483305019792169332504272460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.05154283217149739996322394073132732110285973177101672144476243536792403202554641841303821681674178605013975392578098758039213562899690576014988268448654777051869934823936115258309781471880324840875908371004233345043851515355481534420805940488435409518654838065662552503310797307929345306698760361427" }}, + {{ "6.49123836382549113110940197657328099012374877929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.85020261717664669109950636993744410574436187744140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.50660946670306311914365279482095005173354041210571854577128244379583503141132158648667793122314902465794942399303782457347308120094047863238127874892080844189140303644281120192942849585627941033052970332875969503978268193734299765207776684899260119431935484734340685682552324678913617232469193989216e-1" }}, + {{ "2.24692705476482810621891017532902878883760422468185424804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.52982695718321792810456827282905578613281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.90763013958916250310703922628537395346144248614383500040096138375431039104002049367585390738671354254176978486242291556216285278163895739264649656370403930009408842065500683071987767757954595210907449882232438368368764844630512751091553559176805208777768953085505825846870225770460080538105432353809e-17" }}, + {{ "1.03776311938838771311566233634948730468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.67758461032731062689826728728803573176264762878417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.03459301282359622046275858130909175858605738103500377882461906122638713902728757596922241637837677972497613038491667511030599129584893938038824302224512570610802632172627579650514542361582967805126424931338365938119495726516045340017819117717607391845493489250022446019685368890472485823905828290701" }}, + {{ "5.44463531752032992017120704986155033111572265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.08467925444702359527582302689552307128906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.09056011709343327076534816446309237286970058275834540830372719698670511928227959632093780315386474610345825780828956917908117330975173563693122316666283875774232598613235043753932040992980072681882395580571647274880789017536786697004043527146342091119566202577901703268215449281872604307112909919335e-264" }}, + {{ "4.32141091390930114357615821063518524169921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.79962553627032728620349644188536331057548522949218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.07012654071632775332556853428357456635166481137753650401618414453228087751942869456669180112375507267782856652222749904765639096915852769878278766680206962666525967341796532563009425557062229126958039051450556007688280632610398536337196273409572525834486954342631282999563123455233960154445776600968" }}, + {{ "8.85195395209329438657164246251340955495834350585937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.32014972604017088997352402657270431518554687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.71305713463862717236321613646893663926389070764619904563621824742856237889605485601780242185666715109642520925666586793175066523791156636682971412268154170045092095602942426637119803498838588967096817482914325839210531169438704998222940708453881877588305201012231120626503012557840854056737490425114e-25" }}, + {{ "5.11800358239917845513955452219079234055243432521820068359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.53194625802088957300384208792820572853088378906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.78675898815841251401603750577856756795950441245444722873452268896478608982683458941926503132911522781757532432483294128491039729829837206496101278313685758061174666050134299787052246310316361371623036791254936884792176693736621135978412809784428098496835040268753660201880757384305210529998116341854e-1" }}, + {{ "2.32741466149031985682915646407309395726770162582397460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "5.38640739832896395418437851532189597492106258869171142578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99549497162550438458304414161333920701781715268855145062033883882900750111819551249273252859663946257284929221986573479403421187776431235203160677411657816941834327558315579342010850796902138914924928940560282841455433144115320935123004884062392612303227832917659972351800421646517607120651251528968e-1" }}, + {{ "2.88820917341887019574642181396484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "3.72679079374876875974109680100809782743453979492187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.04797427152199505899776613380207153019163891696040089708565511495563600355422445163531206665239877024907641710076156338867860992891601417074486301976244681251883409289427117509266966735400170413169626794460003914944960446253186507533452481416547111722260834345331494363350198444447590272333886931493" }}, + {{ "9.11769074488846854364965111017227172851562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.34287283617854882322717458009719848632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.61412399451200792430940441597911814328017657658519351363425803166936981320098511499093754150499459010245435176020174953699548406222107608392288974835149178057255386825625780361600243592099112823611022187187648569904297395013151014275208089987059198137284635106672418842688183845527005332642735224166e1877" }}, + {{ "2.99902079785064756833889987319707870483398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.68497592645624978853480246954177346196956932544708251953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001063692844088210456002419855074011148005470079145471634788112628295771788190807123424233524759763995207569368229563514564551401717941193555837507092120724642714186373549513618453183103215293207086254916107790393722326161402579919794484826396299503609272588338890824693538523484869461094064640920" }}, + {{ "7.72854459904651157557964324951171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "4.48978348521208037863461370875484135467559099197387695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00610574384563796400321310101756992783528974702739913146260646865660943239706104030906315422031586966995536370399679280585793557349882649609015460449277306668457058524687099432479479161198093426061867258598346229732606275929747805949435342506588647203249401335413541148238532118555631296171613732580" }}, + {{ "9.29770372877305817382875829935073852539062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.35261872461758123759034688760038989130407571792602539062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00037864179461996490975401602514900577512361928909810135170262283211442500106334885446423595314421485481346967556782507370070595069946883492382064486384013379235733594798086474310298773717536986583185147038897974675666723220012717870637206407697176312759927758943687773764377471241445265488722941855" }}, + {{ "1.08593927041971596736402716487646102905273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.54205328509148672372353061632566095795482397079467773437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00119232709184950657347355900529943667776581936561333029642844322931651851922987396688070423513516427393233449332830940932893802869470044377136541346608056612546712420915411514501773616973022311857494372432610405714927103499401270099666054931681878021711299630772502630342850129330691538468637467235" }}, + {{ "6.08955210127030499279499053955078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "3.93997641600216752522101160138845443725585937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.18201219777662049133348544929685038145294798461233898669466368271726917449741209374562376908881805268589020897308399041338055306698995074087125055703556791502100679603522120055594862139867723186128435543540272128120797808148788656196331354569711892744404054200303870971480027638854018077003767037387e22" }}, + {{ "4.17002058199641822966441395692527294158935546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.27638775324770278722132099691322082435362972319126129150390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000325050709508111108865304342178215954684414490544574201155545551225580135488259163273316494247157849444894518301320733204512003009459708444645141220074915996395890189435364804366091830247042355490183040883445209891891864651638351487974364904897430627412415757188029347485931227191708441175016047" }}, + {{ "7.67550081598081896869234519442670716671273112297058105468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.09358860541564251178670019726268947124481201171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.33361058888703312937877266409714100834748582910004102998779521040115944440359724219966898465717158230452195981198500825979353396690326287544928081118745655488492150353523103453131904616559184005975246310430624687681784477200062656846973772093687820868635241069192671298954998139357716654945366635020e-2" }}, + {{ "9.11928851435624994337558746337890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "7.77150273145831363419411275117454351857304573059082031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.01072215443565297495212875757828431150173416786594077990011283253611684077171961857977658555772993227256701225998130851047810587496804030395055038866276482446366864045774522304245866613460132889356389785400787106849829332460233953000396006079677394660376277801825929937944079178448460996666434091599" }}, + {{ "5.41420122645918127091135829687118530273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.89522592882503256809384462044931751734111458063125610351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00007565289778675652984140979321399062757791371437603651125252179594586538728496280877795475718254343845999376499222253067347916841829323365254311918387151598991472092918535912843066893311920458448486904240767256448921472261918689220109607027673999114234655407258002618927723100761498362332050377153" }}, + {{ "8.00879921885989665142346893844660371541976928710937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.65125145484174709054059349000453948974609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.51542106881981491731489464208722559455080283729538316329978070693260585378415308395373558536702307332302792317627310748549719761801156867236663991267318247059438589418271824484275577584765219427298744283723772247523591169183694405713456066811755471408195734266771535080425449850856084868376311119689e-106" }}, + {{ "1.09156997362350409730424871668219566345214843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.10878062686337663933500152779743075370788574218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01957066747628902940966302510092960488528925253540221172663471275503400990771789589916604068584334436432589666410671717466013196522730609847023637947764642131621149159485396625786863911618319465245064605684158683676154002669412578226202367577007287146331656090836085181386754790207143710478024828107" }}, + {{ "5.27981737437816178726279758848249912261962890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.41970852096179633861083857482299208641052246093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.43686253241293502543031164235680564280493113934425702290586259672655229919415634458697404687915141160074152506872313697917935113169212018685900336128740210227144508079482606408290248099236632255964024354639101204012497824568760884660053718968331056137812934970479251589590682389747704367113989950745" }}, + {{ "2.97632424685030514410755131393671035766601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "9.12458361916200374253094196319580078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.69742603562041824153926447786929280716116286355510132564473072728789802885515779796188477871744149730979853211785348379587523589298115735526488355106077778856284664084128422453984824424076757383964141778964343798745285559893404942252682634909106936299245602255752362338032501973165524906979409622054e1344" }}, + {{ "8.12277007629636675119400024414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "4.92673741168140821855558897368609905242919921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.30484996489149406381687564563779425178418692009670007244171321324888859123491778857160269626310259110411696125879945417306210294026918965107428093516365217530286177050990880067424193779915234192484015646474192080157981645949288654940510168136275269591421630149209078542082633232345605476593203338075e29" }}, + {{ "6.75063843580995381898901541717350482940673828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.02748489106749621435632491284195566549897193908691406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00196404947416174365030420006016203648060565955934806957206111637856432455172895201651727892958586584412299635092294986305134023877029915464080887124975616815060819276759381700802994334432976763795102196206567937500407359464356440088544622676160266170981561234435498384331071158546292310523236254753" }}, + {{ "3.50174444164054002612829208374023437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "7.80282755451220007281154522615906898863613605499267578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00819798888901128629632317940565742032581044787310510298394051237610722547925779466083057852335930819436022531750188258730486171674268778076637531078630844955462136795806889121317307097195981029957098770479755079052235805500969330960373439119072852284817639069793570751583988153638659438922106591664" }}, + {{ "1.26564950853483537684951443225145339965820312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.55352677703511933278261725188684749809908680617809295654296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000394312365539989563625486331626137964273811834798695005780013495760538177217100805072673596190622159320905648378255454000218262505715454699578920413495174693604468418384665870032433868756106543653906692751058614669494849726609491390952522788637204327400613561970408136313418894648226391505731573" }}, + {{ "2.15745882397261681817646206127392360940575599670410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.37905683348865193416088459343882277607917785644531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.64117851649613850769514625497977880278916078343037571542452910699608639199334716242087257033679813405503457913766626678856765747940796988239184619492044398845847330875248279377691256718144764352787323595310916665202454075432835782224634142882556904024349917556799442289975480861859420905292552431968e-1" }}, + {{ "1.04145372167880889691105039673857390880584716796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.37802182325172850596572970971465110778808593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.88526852493738132239113873166539203263138672058127955706951262195153797473038707601101237196070886256644090185553908945280688151557324839521372121066434881841798255953853902832020964805296391060444306684398308798244411237112095640393380398474592654522034844007881900667824504043884214270458892007901e-9" }}, + {{ "3.07012551115110277066833077697083353996276855468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.68879194147396471947786267264746129512786865234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.27959056811329343392664000245431816256252125501370190635108304735068414726869009253945094404747463601079257760616120868020903017002340732110943618640264478113302579667971697324950504699622151612181100300886867598913337113652973737056690812163582367071363756081204514554722838161602803979904270771466e-1" }}, + {{ "3.87855552747419096704106777906417846679687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.68123953003118842275398492347449064254760742187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.14414942990692656452341784125767590353064260907248467847740571016135049928321189261126610028098851785915087403250818786340815261171401002033061136458109120291157079359913768807250954139969052510045722307049663169894534742927788300920701107994896596920105547258658675585904959114220585301112702429345" }}, + {{ "7.26004581866997872330315999533922877162694931030273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.06413410745037140259228181093931198120117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.21086963011262781557962916039162488992600789192717542131434452153601149170623279185807445011140592247466432290015786700658875253434281122713288249913633617033214856219833669907164464033302015146556043425711342744639683355773156696931162767677537366527811567871143970446954952970890842842464186617910e-1" }}, + {{ "4.11288422352877880427968193544074892997741699218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.51736412939929010690320865251123905181884765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.24565288563751822331299972603179488550349468370067144446751898852644002616709216207408151506565589257442807820798232055968358812640290558093447292295273379034573533601586226697268290915360691120466719143962043078879323957769794563236709847407432551615445562560818926972156677354022231138620495943375e-4" }}, + {{ "3.83413786726422607898712158203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "5.00384576840691153165607829578220844268798828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8.70586881100241909365086281828106615321437784717557599878404325717613404517722842063862151116432421295729131945352592123500947115034261116251456345076603582494211858526398683989440066160175940760838173788310914276938532934671434380694237696835717084352874743706871899256563045584501545107582617433574e27" }}, + {{ "1.45287638810286156079709662947152537526562809944152832031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.12685751933480298196330049442792642366839572787284851074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99976308406201382296511195677454028213966050559386949061001176100458674306535766658075727649858861936143578824990999294178518894376297296437371242014351633015801209221765213206140971726863151455918302666401442029878834264175629251102478211077868646609228275473662440136138981614575523961652841689231e-1" }}, + {{ "1.06060778784217379921983592794276773929595947265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.66538555043448722320365007476539176423102617263793945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99991775850777769594805464682102392095766388724998006545282885743063065509840288039071353911521871815954556155694843177720505424196812072094678443706799908575637539974472545844157811962504294140635183658965312242832638263593804028788156476482121148602286677141129409544764834011834242854688050032534e-1" }}, + {{ "5.88086377090030459208191970787993341218680143356323242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.28950414823927278495929726886970456689596176147460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.97772228399557115917897595553123200059617745525398631036747902716221825268917059130877148214691312502174434355597848183024102187672671321353149180399633699090375168044589993636218162674313714376215322688591337150653523844732601246528148296899452660176207080310884559549441104143585753370139662688312e-1" }}, + {{ "1.82088437442942030486392468446865677833557128906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.18170819309718790101129681779923430440248921513557434082031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000130754723378331003328108523077660890480086159377400421770916129060299296337133805493313328717117334983973342138421022906982702012383037259191961910456959250943670084798790257349266900179703918444391347033677458675178576414635996649806132816647233201959427396166295868642002149628537093670669003" }}, + {{ "1.81790864213692415773948596324771642684936523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4.11112317505943991591266239993274211883544921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.16716616089260899158634927691311476940264689424270830038830803482761816779192664467113169986590716888439242048069862364270415910055880132349242712046577768880635878273030333655678293456983297487516817843334720432032181949191565525929129951842591644277698817197191950932369312197425519306770280944742e1" }}, + {{ "3.11682213641562033444643020629882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.94098588905476396315741283160605235025286674499511718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.03790338780611240821364394096187689009151442337723127625883997000112224823851501188946812750320424873330954741819494803462494193607811995436113951374495986635400485180461374008937550605117989616259238001766980179462154007176099462553721961527948038831707776585902099492828100272597482214965326918683" }}, + {{ "1.39087864126595343872150323250025394372642040252685546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.30102723808126441440435883123427629470825195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.14022877396721831842223346046335424470246823884137406233750859143164782910052273120452909159294424816461360814736670369100321052363875210113861850087708357854957657313512898387152990311841659387594066789695419982631901574195401313785030478101180804642923588217360853722001240454059693137169086797197e-1" }}, + {{ "2.70245297975474845853308125676051076879957690834999084472656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "2.27192418381639527069637551903724670410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.66297652134236153231549630311782646457435806521553869102045806271290140313907532572617601088189845177879703715370369231877915346831429034626669722739550299919960838955152823532091259662956246982857242736145549200749997723311019597549168518852317671248226020048798842889139150504890040937192852486477e-1266" }}, + {{ "1.24917144681230411151773296296596527099609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.15140916555233019380466430447995662689208984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.38260599513773427745927397841453042338248242456988517458147773019568704658853879515960004076402277283883489795069346406439823839016514254977654510204974986928186171239215823810556312920621087546486393810430469767985081698483192169492133075210737954383435371131440185644678524564816434215238704654516e24" }}, + {{ "3.11836231019214392290450632572174072265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.07745884054014173791813391289906576275825500488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.18191130436089764539875276066824383600066278177797976268794231640866698789531115667856789828761726794355968881132857750694814866048339710833375629295256557712732385065863487440162509225900966765667937759713986800012768351783498265785505802770202831716066805035224331887004845557896771449008224340669" }}, + {{ "1.49079206164313831095569184981286525726318359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "9.42373605503094040614087134599685668945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.27012834121533023666785182346229437241289754499051958039863912420351581912036946871768101343922573098899177777951053704877386501476998681242293961635818871027535060307630949907397555951449420495765047830618356183657814571149049220337636474144629773918060565875711712572574729922979876342390263324772e1105" }}, + {{ "6.66620618596326164947279968586713039258029311895370483398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.21273515382789454086776004260173067450523376464843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "8.77204862888219369744788573660770287170392769001738688402155865708513288003188496251740638940642992963657767448328425353472870578497253649660611575851476001092271122636729433601460150801906619434951209083981408041494135365768470816162930615684520542260356335965614720676272646217323394466315267451500e-1" }}, + {{ "1.38078986432311534571226729894988238811492919921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.93562727297856326913461089134216308593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.09060418138444387424424059062331178711979043905828333720448765913252697584689444873629369083510366476460104106313375773568706388071930121668811178870306890980290075045537520987441428335324653171796426529164093528427568372203611999068229147036397950044150945977202609787933363721956655499688121770967e-511" }}, + {{ "2.16771050432941410690546035766601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.11416271213217389808580737309284813818521797657012939453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00085620226622470905732844417905757963463091991631468675045664887604696934739150514381777470211904644648980514762573227291787791600677422794047913591269830095072415283470532919592193733010388187339828883232881043401853930198928232094973120867346831075681954343729371567448461485192448773328157967492" }}, + {{ "8.66129276411148731409928025470890133874490857124328613281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.63230476162026535980054120500426506623625755310058593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.75677926316087201992937434104172212635183402081845367050961907386982900528845357336855433020027701890844425355924313158894887243517734179729721860852203216211626732274220956786288208809210677612308603888585509873354794360927290410971415768734554863757722931375046183502833124862440220040682623894401e-1" }}, + {{ "3.35057580340428966085564166377253059181384742259979248046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.16747650803829827736990409903228282928466796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.69762726818915994102636669640248641695258916516178220951615332541358403169898089796085534108216181605452622185779736827460245748311614902401628390881069582094010945399117381574868399439034359201699565625835678615787458358138834274021214751543009200113868243044350923559610553355961511493945076046223e-15" }}, + {{ "6.53381930771882064867828177057162974961102008819580078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.88128239916411388321648701094090938568115234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.44239576906295172295161064728901353975092629051590219076800377900713837403284136783431262977433666893756151770251819781412876948522321366628456614260642901179077056688683539196520237460889892611407142177331136348438247424975172992629120895139251739138531630904163246094893508737465346231066931419052e-25" }}, + {{ "9.58824111169796669855713844299316406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "4.76775888223340871263644658029079437255859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.29079715270199960942963556473318847100392035825806894633874834481890517355918139252275167622132083673533042352315135079499274198112245747602316235108479674713674202663546893395644195003527204518806401402778881498713093151993690595544754136969841959488665417573929913679381495568123074940059218587082e237" }}, + {{ "9.80462544807249748030075764404500660020858049392700195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.92380061818621106439763934758957475423812866210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.69367957215417366534795032414092044927898150798664469523819577887485052498975506353682229088031835479896261249192998498541269057857290594440231095317424708287026045610877468508170913712129807960043309223866462243177903185979844369471346406937023243553333556543631914530281862882346915332974736594434e-1" }}, + {{ "4.22715824828159014714401564560830593109130859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.73237473383745509636355563998222351074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.85142181625610748727512967615608623642319089823180852116567338775155480625397140714648406228861247464456116191851444571000366236244452154069748412545940070600491678946250810802096421175871317523376451483012224450957973158915531091130907648484702974041033736125577265886371493322366154555363836169078e108" }}, + {{ "6.96647127037580693453833191597368568181991577148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.57526947921747250802582129836082458496093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.21776552625627356590336877317582904052748969026951170943346144361121751863809186842688158978930311760773848599440472082708351294025960471667864592532594991999006914698692274398613842119283225752843571850040859177332114176284555447226936581391382855150937157990431287391269415649433263516860035782138e-414" }}, + {{ "8.87031657211726951572927646338939666748046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.34070958469201997331765596754848957061767578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.30679204065692425620221532321916410120280977665891018935099692677903142836365793713310074103183167526509810778546217793360039724544105606790669360053805611269103519872268834740224972933178750433774433912507891375768945267742879488012985036171398185645729556921004734943776799979369402749984084043452e26" }}, + {{ "1.38894800193875870772397540520159964216873049736022949218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "8.28834370250225660470277944114059209823608398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.35222056499059860815119534190744388049132560559707635179974362835024292102863415735162094842301916959003527949486946878329851243593307281685479130665725517616797588026104563060365221513904192277451172225341242860418605162130720263571624685346061029050164764398879401328940031001593736913742594656342e-4" }}, + {{ "1.09816947397275884975090254336294037784682586789131164550781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.58183945899629990446480509724835883389459922909736633300781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99936261439304212269593793274631621066678586897953594510473482514688267255174393243589871913940083113695300948318689338051222055912287552167309726448706279958229666015743107592418824002439360290161725288760084420735569321637244499982204153705684126108823317986930400592132185032791247608619277879575e-1" }}, + {{ "2.31096996516865660353801104065496474504470825195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.05549814372709782617221208056434988975524902343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.07259003265165794231974650932471010325197411080114721904301457157547097334313567798534807882346741414784333355642286915364891740931795753032224983168581398136163731017251242792429565442336378918505638415347606482959367519064678452374991852143987534832456623394400259546622175052847902597251732867983e-1" }}, + {{ "8.49670416441904163828979790196171961724758148193359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "5.06998079666728116224327926886417117202654480934143066406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99758288631873273226282145885741739757443924805027385096536700548341955223394388330738555808413815209906793614975662061712919602993250011794563507497959691981853673962928960543216580974445772540799559436678586781978389593065105455927885069982188267742598791601651598840088278986439446428992363728811e-1" }}, + {{ "1.57311385387133050244301557540893554687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.28071775496995989116096048565651699391310103237628936767578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00003170338187821543987107336746662729109295981087069294808638827112958850528655867141095917778641007871411889107729782401763128246612168904257048743190385169980528080025389670873111442583914650963121405799362630066123464254273948242629742051351814124726982856264616340030151043214382406894418159834" }}, + {{ "2.39202138047558889866195386275649070739746093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.49118181918548543762881308794021606445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.27339014094927962826314328575939814304054781018385168289190485168514741352754753149678911930165646861374735328175462043586928267957865268734389479790773849220996848074070389175534751472812216991107745875007249116250242613067032470443930894251972922681126465003519414999032823440924453088711434009253e757" }}, + {{ "1.64634850170019781216979026794433593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.58052312996124176558421225990969105623662471771240234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01546348252503362826107105198333600916123885616351929759095090370675683807853397698537671019348523544289454424258903395372242729481623263158900841743559291226322042608326721672299094222138476822715326186152957264351608036142453170432188932360709929281850323115131827188070509946087921486355921396837" }}, + {{ "1.29984771123733180422585298252613483782624825835227966308593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.48673306853607149757845462545446935109794139862060546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99382895797564405052408771210317692764125583490813721738650031785719409851796983570805688722349822979681595897622086712994137349075757656980372150545265412692073900115244181782170626388308672797472118433651575906690160786295103594530704832482562910548180219532761382129979082146445301288761331520852e-1" }}, + {{ "3.34499410762214122172508723451755940914154052734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.70362841707174993644002825021743774414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.40485852822901975442109716898610918193900542520961776863305069906497895793489542547982159745108266280524490077140951661552295048439266934614559790866489193897427949324691009938697269495988925070011169411841665487299534902136008055662912091113639828368592572760704050198717640286295766255031666140310e-272" }}, + {{ "4.58769266685160914676089305430650711059570312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.94008884841098259987912655333275324665009975433349609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00265878013514519296809865295705868217393246867225559245606227172893223522667583594724300322356488286875380629025637162385262938162022625886814529504008804417980773476428819488610083450291142913844379562656183905757559036430981251862699509205398028210683848825112302095809741897956564300820095580866" }}, + {{ "1.83659034529005538161072763614356517791748046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4.28717719818835121259326115250587463378906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.53726930767980134628351414040002163694004937538301878071492381306637265403593248974390687238745936146996356402451151949754817939176416474547668969917407094657482938942615901000965138448816198787619804034435155352704149778316444976717855180409986287616695020212770570197624985971189801426264668362739e113" }}, + {{ "8.69656197110674742973418505087579433165956288576126098632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.53470532471532833396210548926319461315870285034179687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.36245700894899388555856775460955394048641742342223378203581109445790321544636857502869379407622931929904915591813410010543421311751441003345169506628319334514393326009523930245673734273160199057057608984977895920935149203153332718973184503752228376603699406900321208889195409621350940486281346111426e-1" }}, + {{ "4.77866412699338716230101908877259120345115661621093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.16847487332184418740155251725809648633003234863281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.00939095440309291336847802488312895385004430053772751642212203497067924870860269568166321148643247526572505972984054880543549485653717067216843154655077419087852705718322510631592242331848706588637404925586365121042986696317386544833327481602868949385627978856713298735650783856235081147982296346628e-1" }}, + {{ "1.54963799196492800547275692224502563476562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.11204960957075971172969275357900187373161315917968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.16782897318171377990330689886402903355059628193684114132825684051875757607797689933491076299185969963004000061078683006351157287011440524301691431503915118755080894616168235485089522630543579349054155603272650786560006738889360398191602249883148592535791585897969899944427735543027279681332101510149" }}, + {{ "2.47000679471161216497421264648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.52499082730789443929086957041363348253071308135986328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01911645804528060285295007365522901933244353571254108413776362642912835636609229733378877024828901273387523484327765744744502840827542422973162779826478327376782490303695679704814420712110588844007646988152318154340574171527693080085147287526207828218450010980129801914952299876654249129807403026665" }}, + {{ "3.03723549186705435616595583070420616422779858112335205078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "4.51110323265247643576003611087799072265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.62158625261315621796784260963880908165199570383258880752909601743905724906716730454255511124675934144867399204404978430279501754463613692043192608111413253272638040513583589571469911855611383025946828382761211165356334768347578605666178294674917101334371471550226399719868797818976469869780054171828e-204" }}, + {{ "1.79856395286417303225334762828424572944641113281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.32059115576763366967701779364219305534788873046636581420898437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000077517217823836935248077849892691299847903424265238524662417641027601052147271170002075034613200815926835872160958521395863660559755851166354980024967551112970300127247095245969854003499125350435566412954660499861774431261483707515396163088724936940160199016889915664585852452649068941190636190" }}, + {{ "4.41355937354146021789347287267446517944335937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.42641018144159374969603959470987319946289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.74548555036519520791276201322845305843766995125882533366758793048355043544777974793130718057932582612619627280143295972890756755586060864163343519807569602024123450673829021330095007485505005460893008699595178496760510808546265795771516348135206769564722897763853591915237047669941031110007831969575e-13" }}, + {{ "5.69171991829923172190319746732711791992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.98043102542145899036540868110023438930511474609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.35629700595091638395832213480888201727086153567756638562745744247364577078732772888391063571800696941049290536498639573875131887930844892410621248852158649248884548273739508794634953342193256645662324249539648039244590505104994015484168576899587920875428234320711411322714373060714140422162212909132e1" }}, + {{ "5.76954356011381364402468285845770878950133919715881347656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.25111872914564514758239965885877609252929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.94463304445870155806025859667737584217029774659090091223865132706141204011793568374081383686497430278169952431756767677964164234313821914580067310902314296078439102264644178954457549643252195734243656729528702645014237867821529512634908260975861471735012585206572278726071364924835281322609605715766e-3" }}, + {{ "1.05123768089208714283672857492391017331101465970277786254882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.80326412933219444312271662056446075439453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "9.01096635654174895730364890004274506998670967372315294988820585742497849923309225303695080415166238118944235696360277258545630995713146996451284285658251097270549397299546887024456736142173128664145649440632706184379221313274424739352233838868194748496986549948050292922466160812395403732938083994855e-1079" }}, + {{ "1.28163238607435392424349629436619579792022705078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.16524102155253899582021404057741165161132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.07879719574926016494490747415323778012199705593394831943581938296777477488312425323506097154699459156568032482136467971947677672762383992541647262353219851774496336332221673599562229050781431336707003943210680119687255794953033119424826346843688505841414943672869216307940977860809662475253945553141e-104" }}, + {{ "7.87202251453049029805697500705718994140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.39760572205021471603458849131129682064056396484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.53207555977032989055018208938771579303277505887799197079806149426805566503858217166434829573392590992745607709024458374528640995879305116834709101892580164791296787623750765678369128997876794757719509455355831607218534572758406336319858307548393197701741434159035106328532033366541994641153056109739" }}, + {{ "1.85413190872573295564507134258747100830078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.69406846692120716113549860892817378044128417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.95656735368615067592522859512955039643574891198504549379998394284320814651945584264960315505975008311532240586619468218955713277820799989277348072854744621874725681637220043518336051308494199906438625737004480910828551371454866506648373987268921256736551339157313351536645840751017335445520822528269e1" }}, + {{ "3.99959450842199415454558675264706835150718688964843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.86709578350118121647938096430152654647827148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.05340685717906270754605609530501932449443307474519553599524954021671059012176997891604734383935653924096296837478833892286774229478680952581431502458132810484806788952807655375243507984165689501659897282979828575230799553474262829100370309746639962529485962944150334131789310986002849666502428526895e-1" }}, + {{ "1.84674139572777286713578526189394324319437146186828613281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "2.25571659299317051061706251857685856521129608154296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.23722070622293990830799081708429380180065314114356604329745073190591014971022286949735867992102290979570786194665670044964971913376468986554402193499702945966888241927569660743521069322430532256408138686743620372490125687831732257527068587575688326301178711197108267406944507908002982504230542257301e-1" }}, + {{ "3.58473911190903163515031337738037109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "7.60245302222975851691444404423236846923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.78031144785764416938612223102409855040299356306284612439958299013225825622202999580381834230141933121841779061836895061770649393695477680433223418771879979265527918578121214616513115300315506936777567650603403724811526574832706041635294702581230395655527148395841553708668562384577527922279281988840e346" }}, + {{ "3.71269374692093090395417220861418172717094421386718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.32704198530596029974130967143963744092616252601146697998046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.99998245586875139489901271639028340713779059130027015276766418411283294006537627833255021572845938748168207820412482122290518617722205438714506223415635135045747382101925106285222804464701875561904552995223695133038388901912278020591663993121292169965721308487953050363811103359158918910384771899011e-1" }}, + {{ "1.70108553436059684038639261416392400860786437988281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.16607504683781455865482223899221025931183248758316040039062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99978954129792622644650032269094574319631975777438486754903659150962464082118122945419410503323172656817200054190506282421527117453082829189458035945776425795407971906137471812197621061779135748565507246203908206485915975691199432826508885650310574999400116127525787480206412253878273855862615753183e-1" }}, + {{ "2.09225836667166789993643760681152343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "6.85669374483343502246768252916808705776929855346679687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00843563284699754528712961596450017035453860350588570410059871012011253379813933654529429045301434484839481489237559065322374683637748571974104032389976926103159187339564349254244671809494052575105796625285810628759847430784136996879048594191371809811836063684074535025913318716848524590469577859424" }}, + {{ "1.21714727542868383913798879802925512194633483886718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.04024274981674075615800667549137870082631707191467285156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99851738180285989619013743122680620229360476738383672375457223596142024538032582334141363701685216531955627726353087504478019029760906182307020379318817894422274668875967247480704625723584657033632048027924110460864147683431850155444025526123837240535234902995892523890236573378473187948012001689440e-1" }}, + {{ "5.07736820771065972511537633948819348006509244441986083984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.97089812664133678943301219987915828824043273925781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.61496103531524292145269969904333508188364139708137329208759077302004651060803860997069231846146525416244529356233531058823752839075298907756560474430217361656059248345442657322781131236619023757967452575027788503647455091630937116588678330308533380860226144011143233073363114955647590755520397783133e-1" }}, + {{ "1.05107095024027863416904438054189085960388183593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.03411347779367872590228216722607612609863281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.75435618440696236423847758785039217191601787351549036022831398969378880644344551767328463505949691251600586393797511528994909897140379260738080763330267660481025359227717949542759648019166102411005065795694130304853332521480946507674204615568889856249883941530835820527992056685661760535222848429821" }}, + {{ "6.04991801259759207250177315273731437628157436847686767578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "8.18837713372669895761646330356597900390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.65759593884760895858132938458504295554865358684199156580525629386190771627069601339728387260476959873950047671147626130674714736942807728977752816985626622779230687686049014608462755984076183185977629942323400832151270339085974963175219245006492664764899739861651980200882059489983917901390447959952e-3455" }}, + {{ "6.51744748140962656179908663034439086914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.07710216336688000492681493991398156140348874032497406005859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000328979143507415685697811442096253363291297955720636385496027164054688294193762566482130745852122932064218776073663482596744861678935376393042841878114830402198126626873661961854660156517253426476105318520395463096676472118157780746408448524800033381676594338617857965937768629354079942055143731" }}, + {{ "4.63884491638627549647821979306172579526901245117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.58892435788971937427049851976335048675537109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.33715260820791317269987064747412391800309849955602033217225409481400578667858265909262657939940738177907804353137088637745857746470695800199690029742037073210058760217313184489359114691758908649867287570270285365266943814797806817843515342646282514312200010453327035336204860831498248439822619093280e-38" }}, + {{ "1.49058285795790606154814783579354298126418143510818481445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.70317518258870839037433242424413037952035665512084960937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98108922622050827087546461298822670842973092479525322691759952475540660272868395330655428828449033553950251437644999243615808527145214868010990354809843842150796169597464947831412602935689456012651060606674408759590837715937317107067113406559618224088301687347090716482594166112826991011166298362788e-1" }}, + {{ "7.50315265219419380571252986555919051170349121093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.06222517749687384025492065120488405227661132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.40175419689520964937445314051307565108961445693694723005043311860973648366068520257018285775532813235354539177271941463790001972938524250513944002301467776271129144936307452041012641877576914077850978415809262774052418002232753061586235460151777159128199018488311311211799819289180487350061980646390e-1" }}, + {{ "4.26847036788872134273342684451790773891843855381011962890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.25843044022171965845742491740821833445806987583637237548828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99967215285852515192073395540137950482554540502668958238310575910483321879481952698928091493628164541705483350832773369892703138436296385686888980010809861693571807457349075609182274750398269557656870778473684116326560067055000556274923680535552295628380182973673412404308833575096574012516864815095e-1" }}, + {{ "2.62667296496937296979012899100780487060546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.98943432793326180699211569447015790501609444618225097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000067498249093796554190906335150484537007905333805853084798522029363004660855846859261868482180160316566139837296027351379815963628562093199672797915615284584800543052123602981811247334355647141931097257473080865200634384690696676990980451941954802180365065774462909125574737179287520936788897430" }}, + {{ "6.70966669446914210084287333302199840545654296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.16310384563290541287683410587305843364447355270385742187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001744257181843369125556914164986065767377720999640888705793438430385027106235014113094055738186706162642114104415940235112867181288621050157885040444050793876376258047873939583048138039901310315757778797936384132441774545886210926930901727852204521859059543099653693673834002390277355781829097039" }}, + {{ "7.41203371899830177426338195800781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.08045243497875006967630373555522282913443632423877716064453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001460353450390109753320201848917579634289514937879484407258848004890744776169944597998175250117503923620359242409184317540187082543653993640048666001395047165769964336795615132413269257911431079896523695358479509374941248440346987424514128254145411471716437568325046246372300034330801593929796699" }}, + {{ "1.69159255637993624077353160828351974487304687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.18026386927718329733494329047971405088901519775390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01763302348245649415440222014057755125288511751974439494118531238495212343084716356590900135150471489029857630623786718849006602487868725615880115082270216521029606377055101314827010471252021762724425333126829904634616800319752383603387644619737656819562990847546393907303039685961266007323499371276" }}, + {{ "4.71460529249768889314964326331391930580139160156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.65188827816496541345259174704551696777343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.57039862156640741370099717884062397571736028728524050580037613318788846117662035095375103738860527021001943141141148597120492387251375648252287053831107964249223144395667696166786054472499439767489130687268705183565392558321079668035341534647161063188715235627145576677691259556611945549071489064974e-120" }}, + {{ "6.64982363517832908428317750804126262664794921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.04124859899293669557307495665554597508162260055541992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99916721594674747376600569188805403610749202879145587384797447934876298553391460440217614450811626491475153827239769211949770987067539929764774811195211928780393852025574440532735397207179531706592529705918782911567387089221968997852275611755107175151890770337885129722749288992344581262036121822096e-1" }}, + {{ "1.16893441744004085194319486618041992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "8.15678606859390242789231706410646438598632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.51388885705521092082676462955313303770964042418254877907252507964234420916080103781270109330079123766686738994000772870583969928581773756873588657991143050640555136731739608625215812170605441235916882843841833089297543893622016574335981753027769495373907938555110085958780955474425308783814139862813e33" }}, + {{ "9.76400625826371292015348757331594242714345455169677734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.86442986632989526896153620327822864055633544921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.74623224798347601232565592691979711045580692330641567994756260200814740060669606546590062265074708542429821154943403107394779336685935160305728814542562226163058396994725320974264154815235226634053969860486205541938719842224052325659161610602552591765080618174794519808159266445853952938084827117419e-1" }}, + {{ "1.87868482843651634084380930289626121520996093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "7.16929872732812327740248292684555053710937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.12028119371494031430335044645564708556145176065304647173808454044697019950167941050283479818252925468559303066000892193796628006878431527857608384081735638513924751307741786259324802053021768713537078672257166368405154064404708746524318561350343547073960189134086007775921344634528456932868446419630e91" }}, + {{ "6.10956934891920536756515502929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "8.61245994668030334651120938360691070556640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.65700792854128829481158381754556960783201446467603874396477753649899987199726050381764154587841579338454205142269277734568001743334867145801385330344031718733980559420806485323497734470145803167224651985614888601581616073332671350983075972830731246525865989689804085186895425350117377876021236432000e41" }}, + {{ "5.12940713132187653400251292623579502105712890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.28564435019894255014284711879923861488350667059421539306640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000373701282973747520930655159796229096921541589463952802693848825441766023480118817224366828254246104620872707491850843628745742807472462411859435943238658855518813616022964453910564185237673973654468864102738810104394810487407665604967406614750596030541491730666890517480494969397423025082726828" }}, + {{ "5.96919527975153832953774529768153911390982102602720260620117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.57180582106150705794678917870399459388863760977983474731445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99977473944483761872828387581066184030968843746303338716635967128051482967926885604187120298468309076374477372898167140591203610593108721399453839682426096478159671434202750765691646383078954275710747248498138805135910075991839124150638583040898450493059066421550145802666193053679045930003027645237e-1" }}, + {{ "3.68606214248608399230988652561791241168975830078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.49260037966346908013329231046384393266635015606880187988281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99985103565493113484475922183999881089207789606742350698567516671823393925981239943259423556444582299741676725651226703123182719333272364174176377120721866858898501279006570635020422790273788959353152995392898746327367860857986758594342210926743928260938298323338805513021194833182527623776519608700e-1" }}, + {{ "2.75108139709647048221086151897907257080078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4.50370430827189238698338158428668975830078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.22207684654158090072166193557643641149481975652647701708530399277363664695064351610680468504557225898194931419933867113331640493326162327026706800979963281990313857552256767561246682453632232432467037080629483164984556210425989798928121976072588554960434306958147259366170108308967342505596481568498e19" }}, + {{ "1.81162455673292015490005724132061004638671875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.55260000441009051353087599967039977855165489017963409423828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000739442221122260724005033635770725844741914207974197964181739354726511926916714698090584379202017604302885037125163720681613028683344989131816590462063741786918631523895090976438946284620031268598318287495015673164204411596879025777677083658398098322196424671094954029116891354161564494388093193" }}, + {{ "8.96493500879970817152297968277707695960998535156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.56875157541190674237441271543502807617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.18186472758714615747935532618938695169587522725634994323764763361322541875338494379271005378981383706775962465651100098009942121578720737172235160080858098630748438403135919432305006360154000115695658966205609995229485314131439314904570801339124033312271333615588491334684665719513845178970476180503e-41" }}, + {{ "1.26612879808979481716102455379768798593431711196899414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.90879340262861951771355961682274937629699707031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.56902896481771879143877379682638527882901861190229819789042792546979238367054331337767498254741605069110970147845996240165269976456347023401814558426675219095881612725781553874494895757386564444732770552998856125193687086542254594118439921159929235553297916239134941949770234940282427408194492643353e-1" }}, + {{ "1.05179746109396965946490565269044736851355992257595062255859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "6.59374100718207543231352829593561182264238595962524414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99092782662380324729163640655313848714756101648128347661760755472309885143398472302956067855710190800993042892779094559399021527010697359107101541167758299014549008387517426503427862359734988159027154498990787998696863714462719474369182220777439814743092111459144669908819231194636468040015004769487e-1" }}, + {{ "2.26677931802150922635519236791878938674926757812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.01284500605095928449372877366840839385986328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.04799524981909743425238268974274974124170089470250115095198088233403741098790024678291238778471336000887693628348108623078030852501843027636021269414992355439834109447548416843301419510567977485938290387496561912410461657784176868621026947292962832450377901755820567805673466030070278228671530695195e1" }}, + {{ "1.47645383833588006439185846829786896705627441406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8.34770445962486519420053809881210327148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.81864953170833366001029957686457080479745389229343183507996187270256012032168347753440691289295163599099444007484206082939466510290612710007371495952373847856242772883552123786185299979765598455416935895627334117098932505280856391911876837712397381549095944110724452719067485663398985307194410072346e141" }}, + {{ "6.83690460562575097469562024343758821487426757812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.83530767198103986204138493576465407386422157287597656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.98542687144721504190991783229244229904437024428948393594123834827455412276977464755147963505927618995184986289919531376928027005710396398910486083058794955925781790662773364003988254537015097017811287414007455159323257827799204950099119284414629154584347927772687791013118617040392415483793228615528e-1" }}, + {{ "1.00205353905587213336758622972411103546619415283203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.21472319667746432969579473137855529785156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "9.08953646324319429602818744612054042909432561532126770140572825180403651664408870454180981154606920328617475099247353850589948028434533205453640961164641456021776839621300753911422835934782850338468313312210488559936609343534193099022841479411388023651172446221865345603921529386692401675022261632417e-1265" }}, + {{ "5.15232802831238245744316373020410537719726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.60510257181055615571807493324740789830684661865234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01431289853951002532506377614168990948051280337886607436878494527645645147723859636940385995419356184615086203041458176935646525562258868511947236909026624331932959131571326296466151873473074426347666272446566573176007728397599624815497760954111152173140369195400219514948443921717606923360226206339" }}, + {{ "1.50327863210486480966210365295410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "3.25928705204024481645319610834121704101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.21705224525603686559675227491858310594380597690754424568785114801297385692314088399732454361300955075549296567427255869777962816305497530312793581969492733775461667703068826501146498955373099052386164214730524062952781381010426318671419140310052915928431939434595652675036589780009141539593357125642e1687" }}, + {{ "2.52103950481096059522273522546242929820436984300613403320312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.04572569600166157249149234687024545564781874418258666992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99677562816744661723525153627124442052964231793875730324917063167910023632186323828596851920875156111103787347156093646859907405739307639598484356543171131155872282222202848608366838457688692164646235280817749009555765844448651859985081286265963272205351701235959915053427147246220456364075290757788e-1" }}, + {{ "6.69572868673203203115917858667671680450439453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.16763271218019875231225457312689286482054740190505981445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001172763619213033390863469162514923787137097731257478379858496528955583730797624990721270466292542630978166836841730894536953419182253636303821927335171827673847960943549331513055995583023583227615832251837950408037083523512010882821232754743304332778547391577736073428707081283889265580574098969" }}, + {{ "3.90611154895943855080986395478248596191406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.09392819734250876240189143118186620995402336120605468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01257436238989364436740053785780748984877719711041249303794530677616720891994615335093220833940115128861191606642103642393403535957041953141054150817528925853538686389534782202437853737346681413564667163289005149907512827692491679645604032151505662903966426036149340526908388743360309704155643902314" }}, + {{ "1.85738968908478855155408382415771484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "7.34900449082321379629112456655093410518020391464233398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00007223974053029723271350039259412141636069806425386754509098025549121050837680692710943206684686658573776447604596802766176331791002163659401284496154417281082333498905606330772551902793976098371405853098920109852460783688567109865594724989116482969799710457089092798143235841330467446343910216945" }}, + {{ "1.76070615176634455565363168716430664062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "4.74889370868937987779645482078194618225097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.45316765019878240189602403680427223818770335223288608146347951094991305163036799974448576646914163732716464031107846083674367407256925355345653200850687798959392811940414372053909694215614805160729642095127896071955737496902022738055554549005006428357198315347861922794020063710653902271293794797134e20" }}, + {{ "8.59257176966675461152189718916361016454175114631652832031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.23640678060561270967809832654893398284912109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.75626791055079856222412335079669380796397627500002019826921615591957724636638189051537678939438100683331885757581588353701345439775420172078880839292692181866988352748585676000159933320197094086021294353349620582341779917757035411891306338495037492064154895428084541796948375617939605049956389592963e-4" }}, + {{ "1.18373366744053128780857914170709932477620895951986312866210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.67326277601629289126013849786644982486905064433813095092773437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99977165516365318634154013098062676051482936340600676508115018286371174310194281664961388300484701624347701999911368618575116158865905431420415090042447533719781066713262060337264603666364847020671540664275635449461141562032657119830142469510330575908700332922190579477083626027776803818572001718803e-1" }}, + {{ "2.79297046837543444519624813437985721975564956665039062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.97135089362066378421145529387104033958166837692260742187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98254178388410952430693242810343707992963411946313883778028696826023938537768767830025754426281554000607392763511414140886618834915773502093937010404359418681811029932841236322654028803608283276794373781000755359892344545988755782370138251235941283542297935477464591913844965660089628462450619495872e-1" }}, + {{ "3.38113855762533148663351312279701232910156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.09301666014966266347874235265180686837993562221527099609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00010890478594524709067739908022368917088132812449962876399165997211946438304504899291487317819472340328330375585022333633583894340550549675803507677712058170618442005704437605073252304959372965881786681685588681179433355904579852317919540925268445449423495866437480095339165546614783853750408452453" }}, + {{ "2.06425930083115716229258396197110414505004882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.22320068732874709382940636714920401573181152343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.56994381329744106645164401249639056164129850194015191524774235721349310749300345652229762055800940290782810800288250321003967654939060262541583665184611869025848444849240326580936044484294913651408991979990620894378054306407392449503735235963890733618686812461995281192108663576402590588669671991241" }}, + {{ "1.34087695405307183449394869967363774776458740234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.48273418616638036349186791085230652242898941040039062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.97025233069613645577452155667707700431529405119046003459330154763708616924139333978711947517286910376855122315920165412886432318792826535847675162918439845483335638190760733366507881163660357422897573743052858674336878106847554903297760383077263299654131223242076136517464708165444087161451001347315e-1" }}, + {{ "1.13795829837500036774144973605871200561523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.03500201236379312419617904073021463773329742252826690673828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000963457189792748049744783509653303667431326364869818483704842948351380610875652979437988682746278703117572921123081696661945181740330111308085604188704279357002138744426600265673193487995475006875655840336689027158444662492494587307695412667171074545903613666004574014189607190377465209019809696" }}, + {{ "1.43733943515224175686145757779854648106265813112258911132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.32214836393443135875713778659701347351074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.69028929542482647910462333162857910188985784876407542387662931701295222184216133407420608557785163630976401541135533394749225188544894532723554319205860877128881077879568220494222775086397987960274421371074192662130785663013334009285908262792624635778476059436229937151198221859566242280319019160525e-12" }}, + {{ "1.40044272789335991546977311372756958007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.53744104780148727051880541694117709994316101074218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01763558978681810389405573088195138451898513946030420888756116873548356901540068272802595421797514887115185086583712361722645481445016465906573909064890341678510048829617311165144452645678278211232399208153808746476971992206798944801345917584439323122735213774632862994806449009371980892407850308879" }}, + {{ "3.33770615636067580211943095491733402013778686523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.16340691059281198249664157629013061523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.74932879103617263287699269441230578657539752277509100498121992886363492927534654879230172186557771810338441534937330485904491247273189306610489852019997049552119104082607943340924820476508529648819831797793990936006114678588935819382061714015089476930073162215255275726210879447826384500950556498380e-77" }}, + {{ "4.28996264268685627030208706855773925781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "5.55843482735151467322154417161073070019483566284179687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.04758858160148749573207693865097611258682532053580644741708378607626299571741454781489071163331961478583318303704887429698138745438016282037356465726871543404600493318018423949357845164509841052287336032095968547544265578409278441961772371247405527391823186341452132702680834735192488255543508774968" }}, + {{ "1.28110344596063102651228859940601978451013565063476562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.43418931353877687762121695413952693343162536621093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.61015280162581259611603041281312219714750672075712379519625520748837900282815093599469657102449329452585522609992906027038154076071639645146113938200595344162570525215006263974571317023675884323716943933613404725430584249433688012398115002318410911938391274174242791011414117839535968615208469771466e-1" }}, + {{ "5.16672517946984571901580807207210455089807510375976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.80381185032818629470231092115639626172196585685014724731445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99990502044552423124036840709042864832582112050272720529614683113869481837430803897286965523406403026476324601866776220157395635334324411401951420003880457537783083750584239021034205680737146324172685990190142433894632845319189846259349630351570776916287281796804645673831673367339618359511691534945e-1" }}, + {{ "1.27899907316783210262656211853027343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "5.22536024090327483326845481315103825181722640991210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00616341899333551359328361392752162344577264467244472586370749414301840554961173829121346442368844768868155278219296270614015234651325697529392935793355916715136924941286676982861345063267744784667777743656327428634674404454023683239192093835032100591051537658643852513812450455406749057692109035777" }}, + {{ "7.11730850188353797420859336853027343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "9.60788079495505627572460305430013249861076474189758300781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00107405241322382059953913596876333435454811871669131165966566428674069591664017854016649566117750922070455790150785398980453750449040916943909541516125417685189264145037334413362116738563574347465747605135946915752491452923545893529316360034715492483804067411471432361687478500733144787639791290510" }}, + {{ "7.25343826567665018956176936626434326171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.29954091776851328177144750952720642089843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "7.04970290589109038711395049954355776776342381310886782453562200726034000844667284742622588171082170563883520775218082400856123793786048177341878726458251943347876583569178437736653743701492064380769184875657546923031668880530296652280260428229230807500261114316496980898463695380987245993698126306466e943" }}, + {{ "1.05425305597257192857796326279640197753906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "9.41211561689230674643269480839080642908811569213867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00221940552517387456904940935153668768677803438018028587024892341085297549561710698873774378670329922261139925263482590967131460066291169951663366614190003024630959832086281000186573153943388176622129526851339850140935108594752581778544126368342198113455082270613501744317697800189856112116044092035" }}, + {{ "2.06616686835977376654471804329205042449757456779479980468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.69516133890853029630996218202199088409543037414550781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.85720096393058346372084885893839606320554663169456270644249004310463500725457211657627998908535169742871675934174757999843761965159654941281377745862394591058408452525449223020548106433276286869407305925521861569746775217097838170535894284575048909646530082294345563168457886536304399266956794807072e-1" }}, + {{ "3.64402451110348510332492821817140793427824974060058593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "3.20455824353290882888778412507235771045088768005371093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.74947852438644348963594070779458486239729374924703758041706549021145269914102751629698949629550481353884433142728878758835488685283460683679637491539837448325034596988851330419929610091798061933767303224300754233414005420110971299300889653323675957445130038468323617573447274322484402694978713617040e-1" }}, + {{ "9.29240918436359104014016924155683341268741060048341751098632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.10041539819032330171921785222366452217102050781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.30375096076042540689175588676000039497925847630595558133397707131285132566953633275113891277016515974090275087097707081223643727147456085023753621384884096242056199349318008502416132788061805089253485591443085259511013177192516510953942353610198267062490629651968866334656113567343023162640866499116e-7" }}, + {{ "4.70374294317859518955657338601383798959432169795036315917968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.29316103610866321105277165770530700683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.15122965827666394521150958097124834553922749706241413675626621322918765539817839286128014659593143570942315119838489669350005299860384297452971974330427527438060831168176929743817135707477251203472467806027668891154074309800997369457141925072379579611854152032663703570089179850821080592817602489379e-689" }}, + {{ "7.90111168678090834346927628928369813365861773490905761718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "2.50142935632569063386654306668788194656372070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.72554973148662694166759157160166169303284736393781157514352684466477860400705537599392645875431865905681445772161441577785663278326674184262006684080907675404076284363331862467589217294540329968481020258307213288969704999028809892457240851077890832023610976308448700744934847296072460694151132193050e-13" }}, + {{ "2.19470224538514946388545467925723642110824584960937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.55402946608165493103115295525640249252319335937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.15537644035230762511257501642891052274838428807882763659106583075479589103986905326616108567723817554261320425463998387402938492727716723367633134645452074625478383896044161060182209094299460842378984988424538062120485203568234956869861031978112571715328186447068917826940102237728367749115256994036e-2" }}, + {{ "9.59375752767912236013830851177885961078573018312454223632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "4.70600447818681459466461092233657836914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.34074971005352694977724271428304704379730503069979006543824421982543154474277701862893673330086806692863058917258547615336829675716810145864841475235135109391399496144355613620559781473891279309689200469472005874869702401500915898827498117462493418903426151104912981808366378491461635507492430973906e-2833" }}, + {{ "2.20730165021212201281741727143526077270507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.06815138837059212754271309009368451370391994714736938476562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00003305295163452281794976529673484400203041012190269638476184821369788032078572490628055955783906515975070132315405678121749687518303529356301281556543290455691541229667405975677836660331331546866945589821129205572181796808319706436826468956587053252695087454167269382499127173288396374118362076812" }}, + {{ "1.85780789842078593210317194461822509765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.30823413709633314283564686775207519531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.59033859659617126254628613087390514142443448071790104857905386498498208916927300817260750485505223182216712213534955208892328370772179606978553650153083374335774046910050899642665243305280141884413167811281876091816572586748238812963621916941228650345907682195313189327181720960131248296641667634950e427" }}, + {{ "1.28002693604745983830747735332522552198497578501701354980468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "8.28203848010336862728308915393427014350891113281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.86706798756547273034023259748332998697114154360428093064398895642136945343512222443801509462788398508116083101485126653725181025691107909977090006260480711914768000641955268595050193784354949171562687163857371073429271907026305099383798868693635018067191669439164014101281294813574568021616736489720e-5" }}, + {{ "2.00223379702332143770249217595846857875585556030273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.62365481395694466471013583941385149955749511718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.05235460797399961706826012566932005845504749468248264540170967631534913675307979194267567883423064423939335134422258880838785383291061227375243059330869736175934549938928557322841085452000578723759590054565129213090997527802918663825422738502966602188020267614510519712792292721325579607440137453800e-1" }}, + {{ "1.46975278087147759168741567581406570752733387053012847900390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "5.86458989513311337860024252677249023690819740295410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.92154549068701501199366439766982295808371482320630816324433379463381296202639580495789257638722760912167367897485745357403740992265341544963450873213458100774396760614353635868165234585261876587876465994053070011062897736386668244554072898747895651881702386350638799402464850863950102149208151366166e-1" }}, + {{ "1.69869769328567166155607992550358176231384277343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.09451664353347934838245336663931084331125020980834960937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00005799594795372584357977768556944656253178249587480331145989344864034282666379944361611058467140259982713730781408566683105999320504528967383185252941819780496432948156779669264240460517640856647134097150209519411486934323027426354907715934579141058953345456267906766103552413735697517517849566921" }}, + {{ "3.15183975929332882515154778957366943359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.02384029084149653920920997052235179580748081207275390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00828189958217090945616829239889322422890752450091752768664294850744665096849748731214361917701488824218313674215416049035608435896320044761285630475680013499593324921963112908846599652343142683769107300940314664453753090942709855630290654440762603604322610449245678270429752911593206005276375357381" }}, + {{ "3.55087476619042874403930909465998411178588867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.98956931787756730045657604932785034179687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "9.32018908151418417859876732852718049962350652342105850490583184901223805273843023839695354873994074279947349253543933474250055215956442663452932535132575000870445343325403706967004656960749057879238157659107219147411710899538754744145348815414311088777452109665676822468399972746650501593917415911950e43" }}, + {{ "1.26775488796815989189781248569488525390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.00502285798295979898919760842090909136459231376647949218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00071834700218288240776940900136375146363527699090847426981092022769405513480212911323057036382071349683106853880233005923304991341200308955960878969600681793506999384869035120625501911973134511693383019876699301926591009688967553141397068289179934328294897849913598948019612426308123680588484240861" }}, + {{ "8.15220048105761634360533207654953002929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.75025311305504219921980180174614361021667718887329101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00038554010810039170759525901230037332621377704113376782308969416671995519944631372963790226541075839243378526551356024850278824940678165140037685990966568856425831851096416371162933528342527414028064433797747326021549595783932074419350022816349807211737168691836224208314746714465025589975731455428" }}, + {{ "2.65027968976974648285249713808298110961914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.00316549124626845923557993955910205841064453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.76325996094662828651112161237788953415887952374670102134300653855113287125254830377423982732034899162480399742930099350206403828614662703257591959653574878666923823464038672614887656376458325931158457664475267311806542914278433869759036943522883194636568041344283954333960707999807543121267715345128e4" }}, + {{ "3.65182751295248817768879234790802001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.67556451265639907433069311082363128662109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.92218138915478317609234268428449378609898504811886050861657038624663939529613919692032879990877291035109701590929770282532279774612429349026418707716959296859399988519535881353467118924067126621065164445440389423581971051504964356883522778929468170495170856030672143818408689238481847643503940756672e59" }}, + {{ "3.06064234847405454518348699721741468238178640604019165039062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "2.20328027949478477687250688177300617098808288574218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.55974238261708442675674596584944622380379860666888634356645875331625278958028151760326676909826129760886331850336797218123658397234427228603106790759796963957806080469839015421053939928057033567772138680185158581228274260396763090865346625773393191666291620910582819221973998350912562080963747333068e-1" }}, + {{ "2.04040793254407122731208801269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.86284726793166655056666058953851461410522460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.58821325525680163465105847555152044190569200388116750112228338962598195492329497459385020613020256287552717930952139248724578086838832538138376726496296560875204247514233017557960719338882649967806582509446295835645176351140001109236587197833843059204085625918013701386357232953416141714287393580849e15" }}, + {{ "3.02716069476693064643768593668937683105468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.04039959726672404105585201250505633652210235595703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.03510986044313446578771317219744132510998690381352607017246273580247626695630046904160285453167383058665284858123740052884532347981837364373948718495188424769656549948930405672217230120189497151355681193015659186537151773454794215525893522934864014682466868462268390720016762737891468184834184088104" }}, + {{ "4.47552570179789768189948517829179763793945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.42494522046174552087904885411262512207031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.11929646387532568976168597828914488086907276576025509760458985730962224619833220482536328707584889009590311478709195034015122056954215000823555978179815671349373291996702460104546989380293121918158085134301955237814810326108959984625471199876172816491246653847194071812034535823558646590118729075911e73" }}, + {{ "7.89920944916936605295632034540176391601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.04372395393338365465751849114894866943359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.67759107384668464385278885844815795751161179367906982405379998416580527424480738041217566954239691080320039512890036456504748798096287871747642118148076943027438116523332662829876900574449886819108021138850402281937549768122792675121441618853423616832699349260369305453263152392638804725787763327554e302" }}, + {{ "2.54801173789754968612708552200274425558745861053466796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "5.15927661277336413458982633528648875653743743896484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.58205367007949169809279999461100360912902896399937272021332641770690450812544971532999275755132753113048328902348279538087441845456071781043743985319802898282971020600433571724744632298362925010469603804610543751544460798372376992115798540860563907814359172789945116001784572399034814979737998689779e-1" }}, + {{ "1.89928750500089372508227825164794921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "5.41078495521190028227920265635475516319274902343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.06563424507714690167714042623337538555278963530996591844954713364193688715643758076458567982650781640747670966188519005031306885869355129425908043628325745338231076914378682618756362764508582923824741998110533664940173863055464267380496758389944654061554957122449256611900453680459384297799878623896e2" }}, + {{ "2.91020477415979972324322488930192776024341583251953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.10728022839575198851824744394889421528205275535583496093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99890103192413085441074667861315652249320196657611339570482857071941674209639709864703891665811884603908304481549592842627180817065779143546842079140388383757073035382383336415119892457712538117493661547669850819233137331852231641783994865993482070326235283184181541427573679758103030801595943776744e-1" }}, + {{ "3.14872001537003598059527575969696044921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.43125111933481261039524667921796208247542381286621093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02802334347014804115203210525086340106221839607209085819487247743041255274944512485633547164774253058201682853956553615818500164452268935135547407521495805328007119673698391733155607980906430692803512122247717040507439060960157575458288088753689807084410223837216910150868125550872659514690258206478" }}, + {{ "7.57561563668409548074483828017378073127474635839462280273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "5.50776874093542589960748045996297150850296020507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.22360322691615293009344442522576915365414410103567546362459956848539698481031529793394942148327475172323264893580159766513287240943753652400314434832413344966940876720610075372213401767379175382193046077868122711719538872402153088637192089166340900530573304907112834730373371836607562222448960151481e-1" }}, + {{ "2.62745508969974561619409314516815356910228729248046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.54116524398034698606352321803569793701171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.65627927121210139869453772647172972010233396005753285235163657937204725700240182301143436917519389589272478600896823141333467649759723515447005854045233682059842082604402664004516169590843725236432591088329366055949159027684989904142732333954835416376354569871287255391194720780011944013876616447352e-244" }}, + {{ "4.80817610372865829049260355532169342041015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.83678291961692252698412630707025527954101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.41928564331678515981471338829811408659000181192686008443981749115702769340722053174798292070290561882896008338642826088125297911559295342634515669888076588557229523820060662923011009955171952757056636448724507715649589034168433634032429475749149003931613573665241664071010924406015748971161354696738e64" }}, + {{ "3.20537873291325013269670307636260986328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "9.12063633247133534681996835935535727912792935967445373535156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000736273879463173771441699203291296246037525214803383466819484064993717806192280443913585501602480713195981402804796752564583674811227808842648414027111557663920686825861938638104671353044668858964832448138218436863850713355695690765716750462185486284733337309942715764828383697583139810455212638" }}, + {{ "3.61912176346828890621809549088538915384560823440551757812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.52277102882139392207860861816470787744037806987762451171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99641674908429772727741716066692522684337586976236285526703123104244360091941899419901468194625324926731894302874406101537005325420303987745335631550541398216024526757166654981325659490102941309976706722307972204026369136295841549401634445497494285259254938938876164197916350437289297642860805084296e-1" }}, + {{ "5.47727150864758538517662600497715175151824951171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.54622621028518670346224572753612847009208053350448608398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99989699815221047195237797415460745692681672883768835967449812852073485700626675461871958759788593113792388910307095890907937872017129700062714402629139690850899327106043179965950904385626167111246937006767223675683130961170323257583625795510235931710927527056466356951973276658601609644129515473818e-1" }}, + {{ "3.15637438341709639644250273704528808593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "4.72407848923734441370925196679309010505676269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.49825547286670319702380922050187415294618434375837006137892453203122331928047047306492172079078511814726958266726273319242885369558258257128888847286538356045014816657847217085941522774109065130033471139571270092091883178037417387674630454737070888538218688730956097543661382768897165490297639608102e1" }}, + {{ "3.43503294936064165085554122924804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.27250150145350989297488020213222625898197293281555175781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00162336779090582285668555617540990956375149416793870895822616882369079038963730293631724525621870732184904017056404166569755879690536542415147024291651047693012257723344966042105272046767388935297934745863474716190137901174215179659999117641456704254362366255369408392878120515423933846401645588741" }}, + {{ "1.05074245129533483122941106557846069335937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.44512744072382729528143674446738486949470825493335723876953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00001005416673874970641874885661095503816717227379033676876612730865335989893449582345456543451081149107465171659175604293715962189257810117721711365871006508720993220186972724366817623975260748578680835030711473739357905906032894783455531711583331359705157662673931729626022752940417931688341732378" }}, + {{ "8.18657910086106118275478538137690520670730620622634887695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "5.69535439208307230074534999175739358179271221160888671875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.93351224746448996937113594504910401882994345207771800323049779691276470148213924723483955246436042747455629177564845224233210837232201105509371449087604601761437328836060853287056217115691403748052298316839138971392756481564106383080155540424716692745736592178985310629391299501759133150627938918074e-1" }}, + {{ "6.94796213109996792234301921098449383862316608428955078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.01032189649519636986951809376478195190429687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.23006490342279217571806140077665886981099414044595093418295957860943720284086984665743578056568297229139299500245761284073691802977046208070538242215508979634862568996291341587581554469156573033924350089621252836592701785348565193758908337598409016657851371246098654329684058361927838809573986193758e-127" }}, + {{ "1.10592794589664117665961384773254394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.25260821850983816716507135424762964248657226562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "9.77248676688621920044634297401786442645385941311525110002800741928600473067163385046961591455772161080604895545524410628330763921136911631698147157554500689676133210576592147935248743333122279013651774018515939625427205237675732186795164784795174668611013924030393724917154265078516887725307445272803" }}, + {{ "1.25391642141006403698803850499388090611319057643413543701171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "7.33579604520485872853896580636501312255859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.68392795308248572652843135364969720382138943730339914636303299072150410868121378543408470390954010868594468316840003936924097765196715356527524435528061810352989069642830612407823386666008449194429503821925534277567874494596141278120854458833913072506701454712189004957264318701887957792196559450829e-5" }}, + {{ "1.43124739542791035162849766493309289216995239257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.20942048850905869983307638904079794883728027343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.99052723424150661886931649071103918452644460542298398165637531920915224385808227208964029010419121462212498905692527594903577506198009266794868206489817939747878141799591393368960481067737790483228614343187263432824490432996787531286395390254093241449602142598445964130129975312810018929887788198701e-1" }}, + {{ "3.43751575420593244447609038161317585036158561706542968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.51206687051705870317164226435124874114990234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.57663597564430277353448388417312985615626273703902768815220625590828356254147933705830400685411299593103143556639123246778758775852967467852603984265071153374722320323459885871194691907711626373620710017973655475923376123554952810313797438555025227910644691182176423627488188876492434022067149277036e-38" }}, + {{ "2.17472395590978127746101256079214181227143853902816772460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.91971825175046888034557923674583435058593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.50169709235325052632986882192448754882997090613648358141414144591089112598426944965520244801106015239482741658118850562377407270011579313225688643981938806077750575133252661340927273680933994486522267294226372481412223764992202845720067257372057887189374997685336348698935086839444322249450808054944e-1362" }}, + {{ "5.61856815780757930039405328992430099788180086761713027954101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.29876093753134198849341629511400242336094379425048828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.81481816351315594384727007893186507859436644672331091167617928065788693663352781510746621160037607384076966766971591864898782687655354341611390803359295084395315487119152362491516158659729010541073082819881189326119491997777097209681555255784910126963441436697354364542857530552913114970532656768045e-1" }}, + {{ "2.69252008622562698292313143610954284667968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.15330514334751887961516558789298869669437408447265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.06666279730568497198113724274678005155752498157046477782004178363192374164474721840040331312046115275560496984877594971350062701246211629447728806246316863840490103633689163217579393790965785864180257773316151663393300617519826348688668218517932804149442470238145344903593621930871763066878050548745" }}, + {{ "3.16092590727489834989683004096150398254394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.48064997212848559193787423282628878951072692871093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.12772520348616005115304677929962056919100702599904589876944000234727659228749834981600423100421009690523247572724398560756474248595294433046382239886297029833469577515642633205214954504439619606667497183510745512915018311469959758235733226013623764492488909973197069967553629996698907871574676780407" }}, + {{ "1.11417522478442774288426297957244059944059699773788452148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.07515622779491204497048784105572849512100219726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "9.37919294955190238371406645550683331410621638917073656116684574199081255090910984115004225393137968138900076398279876623105976571541314203892497339063273916638860131717065142379547629145053297558185567155580289078804833133323155623898592227362901992618266649001082738287327625009340169715002810953003e-2" }}, + {{ "1.54818678360652516035056436294325976632535457611083984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "5.62060471994897832819643168633660934574436396360397338867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99950690212005897959136097299917160482075781519044088208212676575453006587694459400083447882136665068803314657182010357110987268971672741796887858729353234727108572424227132082469362733286450718291677866426969142840900462763239110268260519434037322501413834614893396154343681850902784948541773957467e-1" }}, + {{ "2.28067710108071286176367742370985070010647177696228027343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.22516467629786623624865704584863124182447791099548339843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99645746030268443121474912265456530387059240825775542503945117534294341852612112033263023994402497137577664903179947031417093395690539107266054577344864123860512144985801819409282408928976825661093887120497669159146596001826170808186934642139325551337232119779982282458342982953928951761806573163414e-1" }}, + {{ "2.20739083812885155566618777811527252197265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.63635428348883159158696359858353730487579014152288436889648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000883141260854728883702175584015782702915499431300231183450474406119123947650012070542489465023521252692179702983050986429423066780728766911719282820886407479657520041375764406817735028802434658714254220988205387649994799335160542734586791578044041036401530550092162441750788372567864862832251789" }}, + {{ "2.11115639194152252336444952618421666556969285011291503906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.91611178791150109645968768745660781860351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.03851749220927707096105838017357917405034340382528308320810037826391303266735158295669708446462859180309945589089175400795292926848603356140832744578280150360981737396616217244331933441226205091493168502347016694353942358220609837333188158011389094568440922575728826317171755408132992139505746448351e-181" }}, + {{ "2.38633916347037029481725767254829406738281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.47350156205279176901967730373144149780273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.50492562190358454748346649100342667975057580840217621906828483604765156733043048058740688210262627421835218492853562454601684989325985386603026971417507963657922417960947826930994787046883004260577743222590669257927836671693436821127356903028204248621426323317746936948905014560414890048500518981483e58" }}, + {{ "4.16496490135696059015080194853908324148505926132202148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.07526112190653293509967625141143798828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.95708970459274514353705613356165057031575229424640773311770967490560575262481854947938662630918869775857057855329254545872812061129308665775656748897011265399787487814796202063476887242748791769330372489092700441649278984973352735989854637536188114328280137258357850310518955976767163293227505459553e-135" }}, + {{ "5.60807874972006062050389196826927218353375792503356933593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.70244506350627981296208535155756180756725370883941650390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99735500279497094553640363695299701240525058593455541261394700469821111611056791299453732067954961427582921898800842237144105286658409494042658058247679724238096009700396852983653186891371272750369926281385138909360300419604531575348226930671075101518323161673992501032516753200240811209353821343888e-1" }}, + {{ "5.00853676861336616008002486921668605646118521690368652343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "4.00645550345715264484169892966747283935546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.42868005311869594653291738037482789532744928595938052618021862026535850449639612018073258671047578104461913132613998217526422325806836712765473733283115693708797988431341752008408657974271055896785613419004497755473106128411938210880970972796033569804407750025332012993610194266901383355037197031359e-213" }}, + {{ "5.35323167813788168132305145263671875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "3.62778514750403147104407253209501504898071289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.05603230256580909333512613256181086069213372778044080861620436376260245170503316441303581724403388552683668422287401763124771418367914789920284987220255387646685601968642931765033670724000770308127910918065433865509022691461489073952236533017504964013454255542118759406756885123664390687006240095440e20" }}, + {{ "3.22976764266951800463889554748675436712801456451416015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.89050305023335795340244658291339874267578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.01732691727954660011725367716319147371899471036670702622303272300897410300692262400537048572027256759129565470020582895602617924506137374758437886475976576037363655165839084170315722377939735400391371695808916328159137254265306017499308291350722410467152148965233006027461767679652965168830636324127e-849" }}, + {{ "1.09048941423813448636792600154876708984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "4.65254774353689448673776496434584259986877441406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.58980988503590960516637371738014660727349100194484396379725478994088734700803526572947540745308063381145664972855458934861597057007568531182327714420486870282357356343021375166932444789575430439279485545025094851301007569967666444995213425647227644871269194317170084391746473828083433195180432304317e1" }}, + {{ "2.44743479435021299650543369352817535400390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.82995112549842228050200887423670792486518621444702148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00266010667859458204491495940561046268243246346579041029260554228176172232635197593622622290922199036969298596977304010218474771392718302157017833152484401953670784025973565870850532277945591072432075029519001358625355897190571211275599240174542923282378185576537237233948130696870807231732661924935" }}, + {{ "1.51488749663457274436950683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.02354275702668705760531309145733303012093529105186462402343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000985234516448019885473896561732145157443536520866911511897918118736186775473199587722487758817093449012349451559620294147840372481518705271731392645893056248771116553702829600792931868987911801336627246125357506584399976395776801325943965572049289654345210028541577738692060413098304903948601150" }}, + {{ "2.67331385687573711007480881107767345383763313293457031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.37764930215238656785459170350804924964904785156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.47571438862309533743624874136133366541454712127562663177399504286662183346894197246880043192629661657584457838166576178504996182224295507635623850476949534360416194135273172780271343507597813231256012656614579448387095352094197763495149376101171772035626900389244626161777607049448871411562278802652e-2" }}, + {{ "1.01808534444340903490910932305268943309783935546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.72211847836940634692837193142622709274291992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.82611384964605354323505795669056920339301763307089989948479130915805719954810517867370884785746904749334148062069679398152101779177523464996450923425943206891878509254410570738031307822715129842441609577961369156460374327926946469260053825787159767563643637983753386908235973617270978178126680100594e-1" }}, + {{ "1.00731276656660706514401226741028949618339538574218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.18228984435489814508457584452116861939430236816406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.88175560346904726742930639398687086396036352224271818500936901685374885901648764892385495076288151387225190990418969616688304224966648010000551417499596854632379457426863173605879611399961688292945890600044144991480340984880181190619092493192482621545694847376381337620163394916517599662918605010835e-1" }}, + {{ "9.87804687799645529753395090111212084593717008829116821289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "8.48295760044814414868596941232681274414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.06922896545426989764243576324057040501874322165012440675766666713649225255160119756183042369835830558457195704471707778294936068250116736974227601059618844500705991834404101497665868066256287785153513125539305523985206318973305432078184236844170690028706643163133079135912179653756316354134757605909e-5095" }}, + {{ "4.41825747491548099787905812263488769531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "7.79827462222631995203414589923340827226638793945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.34369652134197483793288072833308732535658609465509415675669768410932243039179437886058214288267645007975345260332874670014492568423533076540783205684921434471069515293441857790677592200203989418352589897685209311617733829289352336172155226574531882652742067029068005584363117523423189997997484568014" }}, + {{ "1.52968448456620720321552653331309556961059570312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.63460821261542546913893281246288324837223626673221588134765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99996930989216600191785450269008898634303181250066938686025190496179003638914112281154344493820093586185759774048968741774280050131382009162499732926045936023057461223555387483027406180587409400576483490119308402153097647327397891029914779646839934539999749442740222968027612552511977099477561837845e-1" }}, + {{ "1.54590681969825345731806010007858276367187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "5.80711944432144022698594199027866125106811523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.53179160234960851931903141810390484338949709737193408192930930410912781308171727424842710235568081208824229115859793069399719735722193263870374052840504012604354910230724690998586625239385836126384899034476217672957422789468436133936022499041037971795682906772214055897416212584774512114169944288303" }}, + {{ "1.06149875426708788185223286681946319731650874018669128417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "7.82539004163816664938480016644462011754512786865234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.14272969225465289903926091127128136862591595250320697667906487225773277795209213908946435749298160698748843670986774816760975159538180372090105486573778335998950914987159909756145213525174507361115992516851061441846585401483368166991251261491681595295047033029078105940961946982855869715287402727788e-1" }}, + {{ "1.70942859622804244762450665007236239034682512283325195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.45014151369056887470876393564367390354163944721221923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99874220008245006855542326558513156408919554643242887993818629193137080289456989925446796371679686209603602304321606023129900225876158421172053263787015124593801332165057745276555467837973732533352070833078756655605565367486807321355073518225701436176826535604183999704696382097767183866284922545237e-1" }}, + {{ "6.89165129121799887451649269110021123196929693222045898437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.03300713262715859741547319572418928146362304687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "8.04313106664538570098839747789552148131626561809170196746678563650616413426296764086879429552165570381706960290576103965119389999281879292911019435355504974691551612891938410889406352256775463548603589074490341705913775216055301816238813657180725380061984870607389371696477377291283392196645786369100e-3" }}, + {{ "4.27946433404347626492381095886230468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "6.70089369397394089659936167180376287433318793773651123046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00007146201085226752984788738357625307865767014027631803309640949680577376696724418376175136252913773532105485594068985474036691750060444806287575074228772867146937453568465581121950409526897590340390497454647087617789150538474509489560078795836109491866150406233412810302502603589419003168433407796" }}, + {{ "5.40162932367991470775092643918924295576289296150207519531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "8.23362153160343446245406084926798939704895019531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.06423742747299574139652654980590788059822860773454214351500321781043318590458743790589432652553137712034307825892416077869655718345307052092676953436188880309769835515354046500269913785918625489459139881331406660934866445646807527177908193314853725313276753369974838311556362819425625446719126859340e-4" }}, + {{ "6.98480482930233392835361883044242858886718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.82423550256237437978967808049901577760465443134307861328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00020487356414235503163915728935712973913169358041240146118411664231468676920896629650395007895636986611826729763726166983962518312776000911959157822099221405201493001705233813919293314432879950393142137203274049451871519519207057550355386892818843802770417350657588091700213982000763521441126819299" }}, + {{ "1.01174486687951502972282469272613525390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.80096038819214743220697982906131073832511901855468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.21386628363111930567875501391228231832773971221469956618940994372919354601446271218977478634940587702534597215097311823723977361204234536761437991482874205192547888855528921579052205936359371957155208181288324241439984156409711039174371275245144079425493549183603159162251977135775037801563222969321" }}, + {{ "4.58527642677075686350463001872412860393524169921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.20426803030317546711058795949611521791666746139526367187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98276019906690498641979219227000354726256121309260540509550375256349346398739094196651394582546860191649946783658447448964727247382391275461932541094336719168645988397711787831199214881092736264632640564846015317413042211277375865471754751928875230345189863352333606975129830522964976988522205012182e-1" }}, + {{ "7.60517875978827806449089621310122311115264892578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.47867011136062753706710282131098210811614990234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.91022318181765750138709868330053023824369950588567785742389327678334961200987486582852651651749970246817747258718976307116965890616698349626417133054222982034680094324870404036435780314465221090580409266996951521555820905007542674615310907131989836681135988524628981589839950536317534105789412104573e-1" }}, + {{ "8.74441787592109604670184003216704127225966658443212509155273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.16721737539795736814107751655456013395451009273529052734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99872128426369981492114383609632051952305521589536821086005990494116094292173923739983506376030713210025133335713606540746004193037337306885070775500980783374129579854971973151969528024543815880504327167057351706595072153954661171897742253459693134310482723707663819212838281958152922341896338434956e-1" }}, + {{ "1.91138738236028468236327171325683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.41870493681337528357744304230436682701110839843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.61393719165089070084284302313399424679983675134163509852591590498735859530953368982681984829992497504960254661066913076235623948356021050016415986014420596315994017260378613566207333104954408470522228787617243604128057260092817202582188202107977088110567991555379686212833460754614025473450009263444" }}, + {{ "3.95935805094525858294218778610229492187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "9.66342798237554857082587389527361665386706590652465820312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00080082312808327988582209522378397852005304579172107085124537382297137225033557828343923139785908077173538670582197264674005612125502043965115623737220659926592486850580770115661984729610019606048664824477525628872443957605574420631353398611478369946179434030057548832782863477926163435959118485879" }}, + {{ "9.52749482248151265129099130035683629103004932403564453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "7.36644237252481737243670067982748150825500488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.99043290744436080750367189311776962864514898582236218043546095145053426015403970275978470316955018068268507145854768132371105755976745328665490014149700831691054362640281890694866429566348288921720874015164835895723114083232661342953621394611916380955923119767515256749281015210664840084139488728470e-1" }}, + {{ "2.48422895630792811018892896068877007564879022538661956787109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.55993124989414910785967549600172787904739379882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.91195173359063670429359403048505978785219394151399979472770021116863735850753993687072273831783588580026886709426140199445066463954822741869299289627867228462101496659941594784834735871174181621098355725481647468654367330416914560339262972917390166297854884128515599346578674725441419457079115897184e-1" }}, + {{ "4.94911189808764902409166097640991210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.00486277593047912404244925710372626781463623046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.45161540440045450223953783783894469144373503171768310299316311211396701039652476264548018632004490940551121650475174226555299061745541449779441170912616150358121670452871969103360706271231784736206842228875578338918267487091360709713844820843854370488212897734417544669039756642667411365232861750622" }}, + {{ "5.86830898821921187469285996485268697142601013183593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.15714500475533861589827466787028242833912372589111328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98538706799650092346821769070662036641738082636479009372539733284347573229317564170016552698886694627816395005478215973507005929122925461962335439146679105934195547032542346569150966461707254588652749552262131982196536881226818665443124490222705261425197752741794319954946333545210933092733146260794e-1" }}, + {{ "7.83501026710203586844727396965026855468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.38788040794881645245695267476548906415700912475585937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.03084303369653734759444079184018763110189145271757350290747789171120440011979438908956047437954061198621891331998729346005011749200857634828740000563446280260144290233886419978479827799434112209614567540357757105949708290107985650241181647155069956615108211465282807906696708079090952998142539773200" }}, + {{ "7.24040157384670202134202554589137434959411621093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.21397503061749550967718391802918631583452224731445312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.98962718742601158545306104847042012373529894592940838744141601234699871358047935296869274717524339141323620050266212255881930805755665793284647269071772742030623661802389270250239007055699061760303889999391509361560603832488400525248124730452423718749922363976939807153833465852271516354356322016570e-1" }}, + {{ "2.37737491856019333980043484189081937074661254882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.16670398708927525177614370477385818958282470703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.49589428217805567802447379970866851398217501608629580197067814528656191899243702632356211673360505654178344944705028006574948563210523891802606219873940153904076904718577079606890006710252221715434732369471615966209956056482424699085238332051063676105524207191799310422842401999054890360978090765282e-1" }}, + {{ "3.01647874000722708842658903449773788452148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.92136460953186087863286957144737243652343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.67051217459346602496477010560417251705712700254048639078839264060325224717762633346441800378240849611262512392424682983226473649608304764571881449403455973384432668551726106109236708017847884189936294979084049530151497877322166267026808199785689058092334141134841250691148642129989881676444005953065e28" }}, + {{ "2.63540555826397102784364179228759894613176584243774414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.22820432867716089475607077474705874919891357421875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.06662853666315384518454771688957273896640018166337060934230580664851581626370131366235045252515485872195142490483479220526746937459904335480861408290098145258297721984393013560504944686230699800648442282165588666276252945193146150539010418085408269547841393316042913883904363908615604194055289620194e-2" }}, + {{ "2.26046063075346914672536513535305857658386230468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.36270389219972226646504509517399128526449203491210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.49669691356986597021713215820093379236513850713669538194655152931335203737791678558428932820631859896635045077055245394317491407809178976243739664980597540207413635355482092381212167318467695663002155241642388129246468412919845420697165678187848016391630764936016535264450983179524692369001196616367e-1" }}, + {{ "7.44369864652441037833341397345066070556640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.92138014336919438207473831425886601209640502929687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.14010675669123183496921521116811427733135459824631474903189627969592690975861278168724266785431509343760131532834105760648359541103464859507378780843287835638142981311936553660415847409900494706845746029735940277531884780112929935900839635096070137371899495277565868989524061668633390669303733877713e-1" }}, + {{ "2.58707365843879599776045097314636223018169403076171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.94714110472695892894989810883998870849609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.94285469588168562425042075510651649105332456874498432065780910860149873485515925490595348642217083245456881656394030092730262652761300876175697759058061470631341983801941103052127203347591729319027059625352617883993869442078699806792081819748879905962225386908139580991345038356748418452094703929970e-310" }}, + {{ "5.98084615325454649337189039215445518493652343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.54141705573080567892238490479428492108127102255821228027343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000134883014846657688131845485191611848674206835683154280061306464539283951337684813473177431132125670490032207511582839375165363167348982592154407605611359695341748966890300250815981718309647127029989133813099179248600056821756358657145575917892530126627067999467459186401635829661375435200555943" }}, + {{ "6.95026071869872530406553323700791224837303161621093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "7.31225239711935908609730105922608345281332731246948242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99946829922765932774347186827261089119719545372876939189761602548364480617029835514052044796339343249676137993597737045638155557799285710458997819509839368231591299591459306098956962406996519241338464726435617191918273092870466980318418139849371272285377732672340181070589663937610591450209282798517e-1" }}, + {{ "2.24073444824900158689473528283997438848018646240234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.72011372485644930879419844949040907522430643439292907714843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99978273147710365618565727465750018434266860028552780634511158239820481200127637360576082082285493761515451879661983436902590331857062933298024957408602175417434650700857480478630047039957552639826605254005583176460691229891227955796802817287827361621819443402008175782397464338976239485836367013797e-1" }}, + {{ "1.02696336152198410170133247021340139326639473438262939453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "2.11791001950321867638993289517657103715464472770690917968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.98056858099165538580460452287541225753365554206313892868475688098072267264713973803329319240088967254425048329384938932204820454762680502689447633583472338302047491675207245782389326788006117820440333632657775030341985234164850042741621548603372080092391251779877542034296864156086357253603371919108e-1" }}, + {{ "8.67037052863078860909240574983414262533187866210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.52133920341677693691129213959811750100925564765930175781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99277952718489198651035604747543743540115676651768417733688848831717723612326298765655588890670608573536137096893609251918929861039853578444897886108139617036413401117695629638378951997111811960041138307910848973294872108144596558607179052633028242671568000242144929604511881481654385461936722413631e-1" }}, + {{ "2.52535597921406917976128170266747474670410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.67545906951556844433071091771125793457031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "8.98282264364143312494924261974141234695472294090992155155562018911995536275433125782292778674260525238398016330461123980463532873852775335243553615531641077025771609462191107211129184970987736565747180479720790198029098762244705019025351383419378700872375798060833692002857187730789356240125924455777e234" }}, + {{ "2.61640599122827916289679706096649169921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.04737226836765842108434299007058143615722656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.25310610377006493866619672909110501466370730517133791833746014957247005356303121141646462034804208859942897670276612700251850886627624409691966399085604959689485003780186276442904234165384933316935452289326908453230024435075360037297385764282630607352032826861327915100978947458904222670931759368924e35" }}, + {{ "2.82002594439443032836578595379251055419445037841796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.28903360394438468768812944276191956305410712957382202148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99981126663120663978315445418195178347518855090095327320928958000002380082757914082726230053423120527749961157170801907113926659877545130473348116514066094356797962151622116993547396704816898570832090901788549840104993042307779674567777216024811187461718618588120530554820575895739988590245022632269e-1" }}, + {{ "1.05597237376428054744792461860924959182739257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.74456803510535429779793048510327935218811035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.05450439582280470237419243848514333965208787934652393730167951372955494178606431812200728304139567804628971230701860498398849175230634941866518705534394558725303044357497118657164159909944927143807152603979711611331658711835035945317940163428557910521645089962892594811777021284923659424445609434015" }}, + {{ "1.92238907809509029789296619128435850143432617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.08349612860076613971363479471676782850408926606178283691406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99982133131096723846335477747571205458555360592772378989843831769539959961315480174186773210831188200236203659966289556452394505676789152783853641019895730138295352465651299769502538786481056285110475730395967855975688507419189456451422446526295567348482093213471867865722148473015661603656725132323e-1" }}, + {{ "1.04631933860085252672433853149414062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6", "7.47628658058347578263536092890717554837465286254882812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.10918690854877106790971565776367526216180983995819057803660864422406143847654780992569076690586240873186597255294638451033694659817944978005382660886521706741399259776875547778479274738700590433170032223482808245749786294093246294856718197278358866518098957741521257199802713807166809120449267805013" }}, + {{ "6.36259548895734333359697210141803225269541144371032714843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.22809772788395861198296188376843929290771484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.52598782338450286286135450458954573598472802663327374811636800203700927786701774385033841837545251692421774984587119423266677067201879737268514092791650544542213882071172025510515697098553107823303332247548034598510867132891098061561608401432719775239528846321974734634143406918807796517003534735158e-64" }}, + {{ "2.13062266921418196562697244811346308779320679605007171630859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "2.38534614031968601466360269114375114440917968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.19098455118066498520013706754490677591984461696830181149035955535619874262474066374087254218809585126187088590005269981305550987677753928730521021427525334082765124171365549957770314171493849134109885501003714622689267145862269434956103582260650590467252136804225198053437675495933201621005291059680e-136" }}, + {{ "1.40290401591987802021321840584278106689453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.13722689335705595681247359607368707656860351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.76476316747050528850692000246200519522360470716902181350858525854503943786512297020242024222896565430817144786078487939900580658865175044648134728561580288938753166434593435107710997858417174150763109875175878816362192204521588377137231081824131646740939989148534654273494711671253618986609286323224e2" }}, + {{ "4.37201757312766858376562595367431640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "5.50898368829070932406466454267501831054687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.50016375413563777673770541325000240347503109832508653488647336857427144256430628344920480322962866090482161278435394130795573385145704869750655237320185554045574687208211132875092396633526114578443250901360527371315672281676871350085960576744972765455104647558784495896122434499365424664074824652372e2556" }}, + {{ "2.82657718261440410630058739371861520339734852313995361328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.01065835722450432997924357758634528181573841720819473266601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99989414562934374733570123984537478193847375990023521202992404597564318809152441993727777418090556514104681985844118458823465596529403699968559686663737740106923387493303105200565503166558779713221587331443491180025140468746214432126679720477339697928392369627582889524402889778083449486287091857918e-1" }}, + {{ "1.82131588065436497009264016355700732674449682235717773437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "4.66518199450072917899845492684107739478349685668945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.40207373373989750079079577094631199620167306803671706440022399491116271902378455342284164919251165911009699545436187010204381502830971843813249510091499154307328869929569251004649662529059388775244320275509563520973233815719214546857449027774185623555318990471004404713606927167122651605783870374832e-1" }}, + {{ "1.46755915364810964092612266540527343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "7.89043697836551700675045140087604522705078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.64484232464543513497888195163429809804134777698713994865506287396508104602871734408178720046618390944324170991778876210342419644694461221793882529660281950244593440074231456401876196827229747637594809904497759425267031152839358279700896103069795279548051852526590187125738047135851503597639320208298e407" }}, + {{ "8.30433287676949054002761840820312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.52637571399967619800719376144115813076496124267578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.03503345548731106338710812130725055986503423501253010837510324365889248445099107670056377581266593900575457325985155519568071726317821696776190852210129272438899726884098324950090040468317646989831449979292183766681690581501814228892321721246601040936202160676525600474705308542633568308584316650080" }}, + {{ "8.81076109807957895100116729736328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "7.33372790631923177073758779442869126796722412109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.72892191263152309368418398483858745615162148917317277888912958706672096823639413941816735201743610855503568372158123380568416223942437204395543055191166267974357638190306465483077702922759360128463612732981531386413914170095452050612671264384868877433570747466951378322325020744405691770060335633788" }}, + {{ "7.53729022560753492143703624606132507324218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.44997674051331170439263495985926510911667719483375549316406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000626746844722828444925305995099577313805301524404103686494009081743532235207019307339151083010194102029079910572707461595043287395038108777455456317947638812268175715959797135803525856300281211049078122806988241700281453385528141559419083370029575853474851945010647429584718991721854559935746944" }}, + {{ "9.29196125311857485939981415867805480957031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.87364075941672677400040569750672148074954748153686523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00130310607123242618493657884019907082179077698498276221909900016213891825242765534255421206798520599892641330780794108614272121210817595736511473642012182311222406630247676600611837624670300497417793849558413334183751618128852678982366003027694097779362865347129226028454653385495003448455051752341" }}, + {{ "1.43727353532569850358413532376289367675781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.29608176142756548188117449171841144561767578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4.54783993491495810650470280449947427623348347028981499281421336796280567779408506141109574684107695839213640033321254129078108321583824176685378348816016878194065833488610016432724082665467588150668096361892027109844713789484964974482948538692616206482165899790288506924374902752205806598101379280087e2" }}, + {{ "2.70759640224985531631318735890090465545654296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7.30536731556413743149391848419327288866043090820312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.07547877767428083419096142604570911700485352561609679581466039671852713698452759329634869067401784752327384511745999840407965753203664746748858043080448574928987130431330974864221970333531951352649388383982665219131905566066113253186390249711325528920747650049981618690921655600270254173866304929129" }}, + {{ "4.86911459659213416298687016059432153269881382584571838378906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "4.64415295518658677309531412902288138866424560546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.41012673791647055159490710611797984019709597197766274319967811180940457128047417078813260208344264234412901043623761003849931025905704896535929048868960146432780155662155674231586473433894529344683868489738341572805069281662400777414260520026876565570790884943500995948410148791343831009292038245400e-3" }}, + {{ "7.84854690434243218444265721700503490865230560302734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.46294874434749200275973635143600404262542724609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.31540724563669307320322491667157973956200661651434919571593303846115863894103669513415833366999982869469042192760040827577397824232012793869428364179080549290195624467934132481201575233560543620306283174662613044511585064238810137330925608875093333350849757044686376810419383361338035393598016327803e-1" }}, + {{ "3.72120262782922945916652679443359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.94908530795382262112980242818593978881835937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.12206584334504219728846621264973553250302703946785171831645645721830894010675262018545815052840050758849380777393422282576480781495344500008748097426459462508969278927821357065182790433439566919608820582252667225317461885443234193297904549706413625058399088149505555110903375380342716569207812657836e18" }}, + {{ "2.37172835747338208930989900125041458522900938987731933593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "6.40757764503378617060302957497697207145392894744873046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99465320336479719185464362393617871174305860472162937262848024567759736497677820188393809529906684006391677099787283285239332531375600773760223206100883246634220752238455329498878968166316454533321577818353913376078773928516840980584615525022113173652501922620733886925072518116022140332545581471584e-1" }}, + {{ "3.53605103337158652720972895622253417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.84582476913116806827019900083541870117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.83532969791885885135620378353794410619553188299174712267165316998085251325072529407513466403156971688912550231810700054288873685181499788137652636209514628912399831379317778239395084315052983947372535292000124065735878003968456173427606734312841500343489942261612441073694733682134245803236657004841e725" }}, + {{ "8.31048089824369333293314215937996891625516582280397415161132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "4.15539351718839655713821912286221049726009368896484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.43482075927723057531497663442495255886217925614713738709933378320005101165593393456330280592636199704470243210249220699112677280162135519833702952111992891673206729843009842099688221317242192847449764385413153153282253151503752131156497992327652425308884952829049613144312048128169217759285595530627e-1" }}, + {{ "1.14666020001788820081856101751327514648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "3.34127651548888934485148638486862182617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.74479451169065114507177142090694649425184490446641781570460948781576584635840991601731927655494758023459925015377386019778946251375096661299820054396659345784163916943122911769409035509491324432205386045800229510005976694475685559497072577311014446199955236237444975977941360792089045512126998703937e1022" }}, + {{ "1.59284463946466757988673634827136993408203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.37368596141571408519865826747263781726360321044921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.12790541394790276732931574594592716168427963234746835691403175587826006982488095536822241070760245600803352183137207993347315747261870544496930500337717553335079860285134922718636682581363247953489931749833309595523465412068635376914524529775388476847978990731073661981262435307448746968442209991247" }}, + {{ "1.01037463548088457532259099025395698845386505126953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "3.83350084750183555115654598921537399291992187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.46827959515471898774763024079995706113716782750728469166998382738205474672874505408339070961454993286360763402251395607969974201963555866889613983970569781895238062738547839409015372756811222082668539050479266568911339662981230077013588037391296361362960017408451588351832195207411208108858157498757e-115" }}, + {{ "1.66695565004290529032004997134208679199218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.71804015666434395370743004605174064636230468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.16219309185108283690353246115834277672387666007297244563945515894098174972467389980428784832971321037184548414733298149740082669071577857913503517445753714679820984984835536300423998074680014379718142053804437180632038614386541542054507333387434066222641647278889877313111291185910035634611028423893e1" }}, + {{ "1.28464602296116354409605264663696289062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "2.32457638429370376798033248633146286010742187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.24945391385140670639469572823424256394544549042741674612450176003078448450232834405677926416541827735839125915448795224664876170676948629996836691342006517593947756961464160491430339434651171508096026536520981556090838358776179831242252299597098299062165399439487062435923683313278394249407345431587e95" }}, + {{ "1.04339649065651030425752598951305571972625330090522766113281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.57348570830582303869960014708340167999267578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.13059686908080605126564483508274490473647130063580548021629986277623406548383789633827569651948273474979014022501027829260141472868965231700274633764760142846471542740886183449424861759202613481741450387488820213753956013540876031520080117102079251759436887925675362188501650887210343405664270909838e-79" }}, + {{ "5.98527292754746476077798433834686875343322753906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.92842618905841398438405498438896756852045655250549316406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99969570850103897852254602475534171540024098089888531491644885537022647868647455296214377097624078476427734613966180360314627711193584708132475074727707481960045949327090840155765239976195485323033627665295521041657350135494380406033384926325020170964497589858453537791112107981125863527921983931294e-1" }}, + {{ "1.20170821629471988138682103652854493702761828899383544921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.83573171858579975435077358270063996315002441406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.28605001646404799122123246583375017811401439409264242217956456924187147921073178601773640157007541107990624712528914809901097933653148466740296742087373566926721281981068789281547799916665066119657434350735735616423796448248252402292977828214490771898387468010213868209841336736006316556313401379158e-10" }}, + {{ "1.79027858130276217707432806491851806640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.03754584982387711988849332556128501892089843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.63044664995037750836987820374386953646551425036186940515842751543311970070428773125366390621088048509415536569966741084563251083225715464442813762547476523458275835451374563942157742199280762833831415410370539590912680755089996665637460577287883121257390441169299493248423283996313182295602073608455e33" }}, + {{ "7.71075177335318884264125927074928767979145050048828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.64182056353383813984692096710205078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.43972399050369154988520798910605088410360743083682368257478281007222478749780386934407011016164443028717189065642983648339942330570417348717676304330188520673656075843370307967688074309785894752170432378373350782687762813282030251151752809306457995236444306078641839344649086096494148698382826630683e-559" }}, + {{ "1.22585961723861284554004669189453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.01372669446815572924860959780346547631779685616493225097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00011878102928302779143036441761880708224532433147368168056931216968198406137164127175122694955536795144107173837990207593653143943257391177552069467355860858316175819319731322452047752960070552385154812027281420138955970684262089648831370958477699568344849874652831370849460274952408206982772881433" }}, + {{ "5.82595149644963838930777910718461498618125915527343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.85058768638723995477498446282638155935273971408605575561523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.99998621052671820010209082288722125377109323080442152434584440919377662337625060557131747020218413297035621822998191924210038600199853200536989949496907248450515440309961142400248274163420688419892365590086355187405743025995286488853302886303794885670413483577122364857720736276931131470386157699818e-1" }}, + {{ "9.01125395544224438992841896833851933479309082031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.21806070291085433154876227490603923797607421875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.38368157061396129371090614663532617206257134398324144105974743560347038187851945959992361814602150755480311739774866352614225040566667708793196627370259194113771020229764238603211377558658426209396490633521450588911944454397547213176293597692411663128824894095155297793732492904564527595779976674988e-1" }}, + {{ "4.40965439472245090968272052123211324214935302734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.02453990431700336927178796031512320041656494140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "9.19534075097294910062427312364961024864527797483767863624171403928319226867976521096128692940847528103007338680691678979870596291215052686966371603169090630798213135736273205172476019108353742027081191692977102801637543740660392501627319952653856947188066651067307484842658131091249553304134437847486e-1" }}, + {{ "1.93717944386320728433759086328791454434394836425781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.08574263216941169218898721737787127494812011718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.56194064144518235667018224449588679976819296337783156090494451036523029483949448332763991177580492553296509263765798810431727918219796862387760870580577134565230417714219352767669331762365217747400655499790736729474440290141888015988952364748907315410294417222286566628219298383793200309754712308589e-1" }}, + {{ "3.66479892681643832474946975708007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "7.71145011595037033202970633283257484436035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.92304236247268349096312573893392045307545699411902317264880124837981164329935084560551082257778103184407170649203234984204658334295355705120603551098245781624244872037069412927213696722873101986921044921101077821551960590243440000669839151585453297946266135519928259442687204452169702512081165606273e19" }}, + {{ "1.32708985351551091298460960388183593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "6.56531833894015816668887630669360078172758221626281738281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00077473925602097877583679698815018000110220247989590351745049914772258652489667683543311902850183669682134777670514222872443151397469262756195899010288195180434965887160900063533882057343026426147190468334739066751949659071732450855977621834587152702675615140712006936143437739732339126497413250346" }}, + {{ "3.52775045264896220942318905144929885864257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.20207441294177685975341773882973939180374145507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.19164668712694362712251058826210564533792000244902438405631163228898011483361552530774835675890492313952004188178746361986328169935055931569379688204574777223286241370824460769287348812931304022631646073013552253933784290828875633916987679684918077103703055564642008994164871305721849760321403415697" }}, + {{ "5.26721150567696895450353622436523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.02594021105445992042559666401757567655295133590698242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00252610964243996116042029581448234570507107619387893463104238190901401098561255564385433004137657583567661490188312636640964083001255112695679226528406143723662756570159800308402030438165398677929717369572388554610405821138849352686065896479954227526563362385890018562652478441542017212666618852941" }}, + {{ "2.85382232656423795447153679560869932174682617187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.21622084331017621394721572869457304477691650390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.13603045090195516704596534175318401579207918841598587146324536013529784552205952203801294482696233870522877138037982641276177183524409958004888324787356863626406890600708780844863240402886258989044381114275612277702992295412653204859730899096318397139691123133990243168861782693287239971524166152533" }}, + {{ "3.93381694633284512141457867073768284171819686889648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02640519319720624480396509170532226562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.39863675434390989723351064011214037513398262547140577736762821607782111942948883337093856726075063500818067573716198405459606323946322650536233861891286348318106161892821504014313663700097828008365436512713907896457061009150442887680100088324705807016079909429412724343222986472982422270499720872159e-3" }}, + {{ "1.90723973215819387405645102262496948242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "5.12980954046070617650260325959266083373222500085830688476562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00003874831722429751496737922917004435479965257235816453591525868492670813319281541168275796018004391940278219820598993631669244673032352035813333397881915928790424205764915135090114218540888704442481908590391442502493189810976009897523082978954781479402200004590037271385433077485827559023806478611" }}, + {{ "2.08352376339207012279075570404529571533203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.77328372265651944869168515905855088021780829876661300659179687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000308249415661310193935943862153702303875909245307529450912006821815453371252563642757366042171762708256721399309832054533722706035892679765533583739735266608823632317266441068592608135365434098808509810551746075126687287986572543900322800829577692516676548344312574211742425657072976921014511642" }}, + {{ "9.71724513689399464055895805358886718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.53600001609863927917037917936227131576742976903915405273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00014104020491665960642725547509974756116986496973147973056122194845971531406444606607453003866992922578566310810305178136382912507500272971783788119308610688740112803511843108270710764262658648334376396166426766278251188688321297859103006142315969456950763638190401996565523343208463418705191958244" }}, + {{ "1.39802629394119207304099383737394646232132799923419952392578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "3.51936644048749802671238740003900602459907531738281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "6.22241870897130620142553713444278896319414844301127628403550478555392596780554049192378201563747768162180873879073883732945738916895322915439456198565943172406197196260279982663959045275534018807122490359500452521705604768928620538202140216274727339329295923594705918674314862791990908520063913560002e-1" }}, + {{ "1.82765007732204644297357987170471460558474063873291015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.84318950269757237947487737983465194702148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.44507161334831975914976330209249902713146345349963201960249788428960802366282255229864854849664361912073985037641790912699757539023105844864929631975643935921225809946412808629805438733741027621604921419911409131275740749522537202228860884159853851509071131465735369871648912668689687943767400944117e-133" }}, + {{ "2.49872242289261521364096552133560180664062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.70475708243581758338791587448213249444961547851562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.16348084392128872602170011561254935010976642009637548196335495165701186585536416597718806964461847864028617635977334329848073696152520245124091137376311572172062522206250814543168673719325221226847866492589752767830775399781911226358430095279351842770613889036173222279808875420192058143269430231674" }}, + {{ "9.73728711278181032710149489517448273545596748590469360351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "6.49131637906343872401748740230686962604522705078125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.07165047632947683093273589058329846367047057355046748020009102510780065766705586588667687646255828190502946698129852184038457736930348397388946238687402139213354445146888181529201139114650892414118512134805367250310852437034078342906915160983796227481872425495472151960083249503055095175373933146792e-1" }}, + {{ "4.41558345670632190066440259101909759920090436935424804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "4.02580267030248754346610784438098562532104551792144775390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99968900351231822950433739312428495072856038776486153703336951900488129027691896751286362525813536862927182360156159008954621569331770038862723809677808006540779343891491372231781933232571078612298233285052166498857617406809139173150092488738015228536389093793575323664246229233166651636689627818170e-1" }}, + {{ "1.69439965482008625397014611735357902944087982177734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.70724294373208412833875513570092152804136276245117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.82874963902734961145255850699575978876746826231267390332055952052622176060893943203741788304684214781121351119738947541263489494899175563981247061980860747331222509426652450764505228926170316851952179492921780437496906593243321687842665376169899786546461700589626075813241454757704572169462564574837e-1" }}, + {{ "1.03376346181700355373322963714599609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.28989017209520627493812838793019182048738002777099609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01199452382152846374481951076631164582584661608322894290555407864227990207508639820617740715279797178581146570337346215682655494757376897027306747771093102874076785395996716253897920655609144243672317898938847395985100637001354712944101351050038536687079382428227717980685264632621156939159222226580" }}, + {{ "3.11283305234331397759461879104492254555225372314453125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.01353477046427009958251552745878143468871712684631347656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99986074588519454560640521673442935641990554362956049271045530697088039943872329332770296441408515271037076808977915428133116228156704302455915102356256867263136007644093137679299480159178566422686424390921886424606676712277018147908640199369062110318937373042728100659267805929813035245614797996696e-1" }}, + {{ "5.28149186098080924978148686932399868965148925781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "9.16657975145258205884601920843124389648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "7.28853014056156731737794697397317103994217559431541111572375406126519183769444357872853226505354592130101907012445487770770781129901235873025553849331106253792412404560306141938477978026852566898693906386886543485615404988699045603447639500571979436388663669239796393481965967462640474331680310932353e-255" }}, + {{ "2.22250599362956213767006374837365001440048217773437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "4.64204894849468473694287240505218505859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.32843078440077439221637641999286892206805235377727400014747144482178933184733036820827184969102097810334387052048590277206436733653974464975608297721942370810634826788083279979408768576378602999295622590369226553818034587114239802440932660296228167167346743576531361276267309223102513376997022773121e-304" }}, + {{ "2.64401597631773445755243301391601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.48515468216955248692556779133155941963195800781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.22595558957063988125039996231413212457799685089809815878697787456948885300739760428233740293311835672030485009491199517382307607053064251483492857230753137256332086797523013500249415836024187602707789116720162609479623122987122977570646771495383250532455162474303561808394969890452286012410188771582e1" }}, + {{ "1.09582116879168154355284059420228004455566406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.12062729806059380166516348253935575485229492187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "3.40731230607113577867418131365007953849097556433032366687124266265609534681297061468250410931194577479128955229993084028648709681104213544161468193428670594705798621530529153971465865443890890717329532471903443507290510241292018220973611927868861647858691705199882686680328023542042496509604517393163" }}, + {{ "2.87650329232355375097540672868490219116210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.29636994307592203767853789031505584716796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.22908880787878338117870181426636174855444573322349359087228723914632875946311491878034980145023441888073390972797385266938998183475968716718276000295270333868881283934630328911650991709812223171518435502540229986453603655260898220094106548795285001784222894626512051690586979041086530161063766088286e48" }}, + {{ "5.43192335581155216501364479952940200746525079011917114257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "7.05490815336499605694119130472330425618565641343593597412109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.99991447218133598413920881391105179265568552579320617946001886143605253717825160221002770761833078341617996929941439664383856515269642825892255570319730959451798678974258583863414985420861854967974576953145352608585972242996479479728931155364675877878808323939895254383920003458645959690646207544957e-1" }}, + {{ "4.24450620737656849484897847446518426295369863510131835937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "2.42617657776718897988388334852061234414577484130859375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.28295177297287815001307142572162153750668927480049029937221930255174310738192949066940496577252702629998657734311395912708887847618250337367575924375521236807234588840327753338387239581722861162855798729933237542178055913633273793008757291901196363208416962469352000552707123078294608807586649015685e-1" }}, + {{ "1.30733273631510917012210626353407860733568668365478515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "5.28858724063975630660591753517962843034183606505393981933593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99964885633207072968580726334787422174518544602461721143383625224899368056665861649907581709049484723249000855383620986446956783244965088674964206494776757278305799759524067667215395257158003498553463221431113016348494389058271382782227321845047125985119505752219731349818937084514014330356212827292e-1" }}, + {{ "5.05693319148356598344284940083070978289470076560974121093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "3.71295988486159203589842547899024793878197669982910156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.63937121881680868303835544307084885674388908256423717510775350630463810161245157254316013064889945722190309457613724784742119883122943867724213022530021363225255978426044946346577578461808416905152263622045415849140604671011655772958990313726815312540544848648362428160986497782665450731113127323529e-1" }}, + {{ "4.84423969203509041108191013336181640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.98413458911828048669701018980049411766231060028076171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00430738669558002031403659131744896728312485313631409231096866927631637993851247415735380222493024677897434245013356617271278547792035688620287749522586547267897264556329014249359221662180556496497208175354676304526200770138492165863545577626683932270268515447259703077574615595169323328662157853185" }}, + {{ "3.70784803656541983585270827461499720811843872070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.52501708992864104530440272355917841196060180664062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.33573197351168666887962631201029384882638323647836131662987813863879776215233605661322116050262224430353678691583537529582375506359810080440891529163886160078411813398386404062767305381544566179454141780145518165423921596307439563187082576279320332050551415851387221311994490392675793780232895364275e-1" }}, + {{ "9.71655514772415699553675949573516845703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.59166384187756904111665789969265460968017578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.35377653844658353569031679679735299370922232948810544763027212743048187579990164187893014793934410534408779634667801500692064187926463087757507629287841868368096408503740782370080191376158895711024144836742418575636184986247750729343991462010937031402061673932392367262371858670977341473615463130359e1" }}, + {{ "2.19264585936548201061668805778026580810546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "6.96729316179001942387419288316152687912108376622200012207031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00003755636032301823537943813016356575902489314188145066916221494580392625081472816947024292161874513732270899683702071327371665141574567958235034154797657204764921080200596842458370044167411926333595258330617813605034939486089552138840272033589961004832483480269032835319807553392086565465392533307" }}, + {{ "3.07913249304984926180139837015303783118724822998046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "5.05463804011641570923529798164963722229003906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.01796919571840276681288861157787148204747502682382876961304668410493347723226232435621763407251840958497596600197906374696494268910490419389807332560043086656936398322936521311486726743408171670806339766715147358441693728848925652781609216889389399280179459317545232154188799226490332505068768929180e-13" }}, + {{ "2.72793625008602248271927237510681152343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.45107876494454290927649253717390820384025573730468750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.21356364414706225993709314217781803611734556534595777181951409142649823132949473277169982486320740015805393683502787636048469072138860871755431959907851351864995912275227191432009279405103766593019141570051245200073079914866268809278471723253071227068595740039873872137154853304817823898235004618070" }}, + {{ "7.23608622250063859837609925307333469390869140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9.31713845716947162145515903830528259277343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.20546015073919711264373148066122758661068546232444031541084969085534241548251886930568813690809866385000095984750691172127616802373754602142656508934912781801862005537086317665378844206989588374435568687107987862008034665185792976330120721552229886514045101504253350965371418298181204870517230728955e80" }}, + {{ "2.57072303536429899395443499088287353515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.69790274993758974475532852466130862012505531311035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02140974620888944930305959435799702728843289682449376214925750857783066006891649041158724227299321084257799199351924992147805951706584524451302681812312203333848599297059927350897068391576429287666840858314350106940048605718179391844174140189607359928083054157216235380992076831905704302805940691484" }}, + {{ "6.27071378772734664380550384521484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "9.77213705199215154541952932376602802833076566457748413085937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00013045496457016358902387902369248820481792505684604793782357003458740283012026953971512527832247937686018956926918760579827820618149654974789601261789353438501933209142889274324701479760186259188286221595702693452369288516143444427753506877231697874469255361407264955531595418134590240336559943863" }}, + {{ "1.22109376852135853575020973948994651436805725097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.11543635047828820815521422282756702770711854100227355957031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99995551589729160336804918676630911396340574056049766519068518427735361038006808700598379055737548489964622176597729664945550621782605173209704608243388212974829930345797712949588621847644770093271093043600103623962707878170666514346008821208975619634087411931268385031450753049330763535153583731711e-1" }}, + {{ "1.52900990354010689331598626949926256202161312103271484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.07910792856703210418345406651496887207031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.09437152552687759915144210042422837004776738858769798785362828201158918075365450163702134968526881164477730298716543350719085306748967317190021537573795780001155496528795641888775374745803795044275135632851107711558035622505495812638847592959079891240357223230602055612544312975892640303394964825816e-1149" }}, + {{ "3.33574880350019498109759297221899032592773437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.22409910922928020227118395268917083740234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "7.53927322890034742368017335227292720005783821228941858003370629012694382557138392281089806659775813675293365836774015539525201899124038456550795641920581579865504101847353382339574548922971435920120403286201070202878099356466592276232925556211910029587973272230882852354333961947656943741233580547242e33" }}, + {{ "2.93886093222884170472752884961664676666259765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.83152139210962529736886894582426066335756331682205200195312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "9.99965326837122789351065801513643019379691746234431978717545032882563543159129029000520238088911519893688798595680083260598269929340163335960195938697476035130411906261845669886681524297055544969116053569875568029319976030656002722062158836225698022385486930605555120535915405105091329811282147529892e-1" }}, + {{ "1.05363900341240332636516541242599487304687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "4.51733416318811920042719521006802096962928771972656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.36944656525417845173858897538026176879580880507614615066496128471220543538723767528991906038383446820702565624708556443997649629495841259671527437077527127938789704415913380536996498286764720566639200198900869760387706475703380674649201567096875423075710829719565752777057995176317511826228555593581" }}, + {{ "7.04420993592731428016920358636809851304860785603523254394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.83514384888353143665540301299188286066055297851562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.42999851704960956730922360017793140547106959683768718211070193339741510527923658661871542385815054985958418322575081567325471819065963185600217971978825670497003073742499873659741487280818814513977323524960437583297927902838999554519027556228317521167236540123085211060151247184818776639943050911394e-2" }}, + {{ "1.36453344822830520570278167724609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "3.64161706602405751964646185570018133148550987243652343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.04399795038635921897857958256316651977445152567453727222518284598769789391999595233661749274120961391885225992798836625746470159354169324537076101684572935560321844745400772917299981122731280255675880379891143456808614768985468915540339803333726839718219814716863124296189939533443325484535601906033" }}, + {{ "2.96565824250737205147743225097656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.51611044873741196425953603466041386127471923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "7.47522068392867838732450708572135930567101005550555468267204809080882851453167258980507378379243415338266777301093835073449659828508711197010120745211201439735694186362327003324753635700543968787946652069972776477402704033680932298818937199049452926851734709666219333409709557278942834445272506685923" }}, + {{ "3.49571885007329983636736869812011718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "4.05030442875070617603228129155468195676803588867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00424637003637001346519445137047903985527298734444205998841513031143713650570988838061609722582515075163633719319500702266902153041674931227041528924269656845803454259997891649918404783522081199789884938037449889035577760958358376931686006190221056227385652828889051574541455553647177469994824093880" }}, + {{ "3.48704350707848789170384407043457031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.94470451369696548105103772741131251677870750427246093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00348622623956426654419790365515385008204532308719120294458056691444071691627567637464093877906643804041743573926720499607391861016395825332249134843376717727039444569339034648222083969616342813466476442089528251404075917497087087133158228565604726619218594367232783173627524996497743616209681950686" }}, + {{ "1.56866354052483725212141507654450833797454833984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.92382444394148101329822253546808497048914432525634765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.99458548775941655985641049562781270043468152203580071617312952591624765716886645437516907451083025631663787001723138256606416990037410952933773901687094742927210507959414283830075225958048767485241813607677989510714884949211624158456814965576504829085206941026015695802504061055800475236320588403791e-1" }}, + {{ "3.02555496695998127343329997529508545994758605957031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.43476200926107111399687710218131542205810546875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.07162439112148019358772224877510168973399161717373536875684406796915754460308189843582561832996734392043166689610197386058626738901780367190433337506557349349095623450517180395264699151519926104197461968535179024894054340573408793813826035189319052898390671701445304365679647915192850527101155372317e-12" }}, + {{ "1.13301057369715999811887741088867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.63391498739915612750661644270167016657069325447082519531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00152645922689671305334533143447522531808487470636607472600090062282095427316474560067944838274073843864628772883486893974636361201579261003896147984190781801313303984627253458134496161410984325183430174864002871499528387099093919980953756534711057395376377803880481128200568335684903772454493560544" }}, + {{ "2.00289080215499270707368850708007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "8.63919332962040243728552013635635375976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.92699766759603617897105296135509926340232009672802063778499835631207758035200425882438232730073541633716557508264570905405926283429555595877466543065569320408150504538307810614249593452939955155496934950121411097262064539453295031460705244148452908856502571794692573823194011760644101511653087442625e3716" }}, + {{ "1.32507839540064445080225219442127126967534422874450683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.51887862883488423904054798185825347900390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.03647722584318600030967144335207527953463651392633257231597431308252840118498779108498324584815641015064709374407448575779770810144009458027431983385495055750280990347720737478088901276233575808268895728220588756650828610378844764861577519796740508015409537773234457412772265295624580311112182954835e-589" }}, + {{ "3.57603431414909023189352410554420202970504760742187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.25925527701659852259155614184749083506176248192787170410156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99982482017295343923291140868824543861889706024267738325920940955163642168596277387382324596268313941030962899361898533933991225186157467591500415565798572470081783136017764613428509329263882432996891459823007909353566621634663513526224023265569627278594547455316883257611223218894909706813593928661e-1" }}, + {{ "6.37895215316995745524764060974121093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.33606864421000417781498770253278962627518922090530395507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00011705660623425091805720617137318115223118739797033368829524572193511821979599497313069101487866374165387923697805554918674050522785359139471078208862147954503878603840716656103170817064574728416607854591674468869938491395161398773239010400175784333016262331344116781579064223044329496394945074676" }}, + {{ "7.38104343240080229548993884236551821231842041015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.78526096140715813593603800146780713475891388952732086181640625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99992740925564330652806516420746938988010148239633275154076421571630454719695668630175026322867662102076692387029189869547293172340508820534949790931051258505036554857756821592275590340005422029182367955076901146714768419205676755504470790282646601620852828276821380880075367804416790635127471984294e-1" }}, + {{ "2.24606666462972934823483228683471679687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.56224853001515953110356349498033523559570312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.01973918494886267810001894567464669163247766970377570638787946610322435627850446066260492108701967988500602281478606685233882133420407449502588207373547970434356681888963673609480451591224779378429762251379481389292664486026843607177275521955621777327928762357765933587555111806380884809909558908126e155" }}, + {{ "9.00800182710125019180935623808181844651699066162109375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.64432725765355242097953691882139537483453750610351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.93259995118943779913113450886803213157300236441759177808360979990670369813799397673229074691051859756881735508284831070803950318509897851789286938821324800564473083981421925321740139076048924264684734691750703913517330543410997193207195299362629750503027996358069377923999788650279477370768077765657e-1" }}, + {{ "9.41820034138939809054136276245117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "7.77419300288664260104552761188045906237675808370113372802734375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "1.00000890381075384949081595209139696411199492416870417459364082687864113657489926105641478106668362778068330268736600393352152923274282322515415108939987073582719187381060734722668227714154297709452559911296248629890116220184188866083605360898785001127921221360852853375996265543887873427220880943937" }}, + {{ "3.73692731999517979007974233240929606836289167404174804687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.54122149350758519403825630433857440948486328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.92632813942166735469252865298175146289395053013193471532530902730842579927583105349449489218906918310069151271847219223504300355763614013961247019308729802033635205970100220700085021558381217246935232153985446384879850169504304149149649141113162707552300166988589633450196697040655835196191118606631e-25" }}, + {{ "1.36207381223418886456721921263124386314302682876586914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "2.62468618182947011518990620970726013183593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.23349312978912488484797519539255018773821880984944037182332190114599517402131412348320914129812507474815113624208263309735483442308554370722059051755362465566371079854655405434396337539491832247301779055162543337811300162664812836135792078898777055591459214033387458633919871456241380657515870584905e-1015" }}, + {{ "4.99439352691324893385171890258789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "3.82669140887688854490988887846469879150390625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.25800762575108176129137940894321369236803059535403474287787709049193999989553876351149791249607106743078893765328229169808063556877194151113548299740103775991789375636892691914854010648529483996498522632062568652379746122433944483375027665116468292026500341138320088041194003298397510386237462266236e179" }}, + {{ "6.48539296127664783853106200695037841796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.19081769830710604285428644288913346827030181884765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01763841928646063179945311430619776672100366204545937731495139936077193534063748395270846081233643612207997993464082794803985613863394615181696471224069637239381759785944556677466232970035407360811317566511537057177507901702757204703329800142152099723806486139061978862458791045685416916469263617024" }}, + {{ "1.26185358741126574244617586373351514339447021484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "4.18707874563769861381290482427175447810441255569458007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.97208954505633083962348848418154736485944843062550245347612203304547965531131555025237286475690843458460809325029245321285039436520603179307117618768371875438665250167675789128497710216048233584274468422162333906486838232593986287174975031846178589748114260487176217087771250070897293526267935699686e-1" }}, + {{ "4.35488942342848749831318855285644531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "4.98678835531215099763358011841773986816406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.28936120581079817550967747499324146341809782859497306106568788729215792440868081012592482836115918565108733027645928062811796100015424546044055914594061783213133483941275372186699846142681689537346156745852091720729474664315028859269079769914368203114147150204153490030106741528606576208240181832379e2313" }}, + {{ "9.52079140369027854262640175875276327133178710937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.08107909706786978198955750940513098612427711486816406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.99946912731466247972527890006754510895764819973853843000662583785640845446566388520861934833991540886888853432324685563515222422612660717906957938307798158191679485565611171204322088502967506340693425660800080176478497228519680488062210430869030836704176100634086409155754383655120084467598988079204e-1" }}, + {{ "1.04090684013030454480031039565801620483398437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.93673921485533583108917810022830963134765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.11210338662691592819619664979726597449100163292683513479170961681889868927958630114518483290408310841588879531996056535646660865328863109763975044243074863201932805945130071457158971557983161341534770079019284360491414192422030250649176833692020314068650401152520803465262499102820988511235853988648e197" }}, + {{ "1.97149801027129978336915883119218051433563232421875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "5.08739590531112617632913952547824010252952575683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.91773157361409781701715493663763866515090466561690289420891165770114164193580683686846646130438934752909209919079027125210567061374829822112866779201464446464651026659338435230202216580437945262368984290532688736997482187636274012593325315635831427955296981578931251003363149110123293975764983649974e-1" }}, + {{ "2.79971511541740710526937618851661682128906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.78721875202228321077857486898210481740534305572509765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00326623969490901566461359485954800182836515927200276988639325398663724684484176518830065683294723102506600723636309590040090118084917994679575687454329398419185701984750026134555302778342008308134679599723649132979721129657717437355628051914400727321111879908949789141417261266151891576137055521720" }}, + {{ "6.47180277522192426431502099148929119110107421875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "3.54396046637904049703138298355042934417724609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6.11393159288848940315388484390073955173736785149894558116032886653088516351969818186256818732041463123159800744120590173108691581334056179094211775690837141959813271450679799058611736101514220405786918675156348944553549256908731766892776136986705072991002327432436231317606705791658862062772822668961e-5" }}, + {{ "4.68478493824730685446411371231079101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "8.08503458490309867556788958609104156494140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.97762155395492793734284548790084346203097684458052431296538227291993735975496781864258983550151454075639982388971649044469779839674940147551147838593024539580668837295332526092577626791361518961708496544368414553255175123291725694241746786254191457634438577633532650001615818789185478534006606741407e296" }}, + {{ "1.54391459551929816074178347662382293492555618286132812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "9.30291502045438312151759419066365808248519897460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.61942064374907006758472323953419672912600288860094391695046538452658427001421356899386802781741233841276963853691331000772213773371503948038327239870459585412114416103967368390201886001946927622637207918880459451317082626408706757400699845882572764664471363683650469561537447695573432201521718527705e-1" }}, + {{ "6.48003875925739691865601344034075736999511718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.26121082452632900412770045051047418382950127124786376953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00006094496769763278820872383817879036100529479018908630432836412716347076273911182394224909321200839758060396148281450949863621182268008379068612869939290370399199699187329868380547441347229000962054100848350577521278040241049817698210922858722233509600098748764436396006044192563867258556456726002" }}, + {{ "1.02255146268133501052943756803870201110839843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5.89932691098755263015007699323177803307771682739257812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00013156917767091552599892235129254853484398955770015153844565825349128084659104946293310766324345122756751921898192510410177121820174080396618577123202206891707775599129806431636068338328182197155856712217515198962725685962829886150997851437588418591804207516238583892908865355284748545102405714042" }}, + {{ "2.81888129121324254811042919754981994628906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "4.07352602363188209810829221169115044176578521728515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02324693289074461806065314601130588099455748535483252525100029761881094483032981058215632709470546862166291555062468221229877852679809354657976457141823806639541535849041446001105725715917762334478759524935613974359759936992996718201195710259035985781666122257084622777055529931477121573215140197696" }}, + {{ "2.07185404527926539820087414867089137260336428880691528320312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.35292300705978618680092040449380874633789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8.48850440195174823298359540121818302112603372945421421598869878434979555804675505735326375593302973038814914197710751833892726619856756218734694899102028024355384042325664532283875944124268902285546831042825514027899847395159917919088321233227951525026080119430650746383889735094027434636578283016912e-26" }}, + {{ "4.31935286049695476781606906513388821622356772422790527343750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.67446027602891164636454701675205569699755869805812835693359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99973122517169758868298611393816315674468708382437784046013092517874934197350186005397961789565235843871109955511656116413964407693637441952651815512224774438246717669200447114406421198392169132912944363201879586414171509537947822165122722681222879324770937027844102716000158168894762456660415032672e-1" }}, + {{ "5.60728659565255868472196526530737514804059173911809921264648437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "6.38030853130188620203101790284705430167377926409244537353515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.99990816207746297627000228090032149940299388165914304992280548917955938225443662692605137525666097388080408339273626056667955459490552137971306327684500228508064672496432612203803093818358636762048072433804065084080756285538210846111127149390742779965190790248566867146590543170273767758612958658971e-1" }}, + {{ "4.94365872790929563630746290670003872946836054325103759765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "6.08107286586160853403271175920963287353515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.41889634080305711655291544430541860422410170311666966191109605478799772032330347327796646352426019590688459329571978188218768772574725991603534645626444629132445446486278236532522655245444099755490849273965885852698636839519891473821647868673766453693048753250768728056307822453273785810806442880557e-262" }}, + {{ "4.57863041241061873733997344970703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.27996139284958445614392985589802265167236328125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.85252911535679891073378835901479886089967576299789401385670015780551662533990060451545346245206661914640102653229509656129118798311517873586006356564037704026911300448200277564257378774264510533411693099418541902845247573044373703549276907520323049567611007543654341177174512295005876331502328496351e72" }}, + {{ "2.08423524510303792567356140352785587310791015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.35070210371325316600632504560053348541259765625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.69650994818884808551478851790421398330849110943521821889862054443832715742450095948994740658527477301306542925058870703929885411081233767845292798598894899925369153906803097693018622562446710881324699679389099964263723003154543262693904642747226514772235244787350437914151428906711221635213885798789" }}, + {{ "7.03507355339941797822689295571763068437576293945312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.66736311094788106856867671012878417968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "7.68909935340978860422757035820741960584342288164122209394216788923406587897458745269054408633969378408300698489680800368145152233150125878615072546588959342193206959268161227822392820692595901101440058139059566058188384350410226233241151749648406111214064140648607944967440645591239738930953785109368e-1000" }}, + {{ "4.44777561798017704859375953674316406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "4.37314005329937316446375916711986064910888671875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.12314549862845492717877595964768115546325186339715764453604920761210996544623734651949041265076846799054130789000520895961692269440989421981634150513113011053879079524507516981642085862682964932699084859566571367826867471772759871670601934760070910316789800074922999274803369631048113774053097073929e20" }}, + {{ "4.78949184649386006640270352363586425781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "1.79183351174304107189527712762355804443359375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.79637132177375382162263956935980813855595791264327736518378404210637984016731507340572257630052502643907564502937056932274446805895054500000116906646009851736492937513833076602489625307279653461589071484812740516746714953908730424736460829219077432204380475346934742691432944334479643432469277088306e659" }}, + {{ "6.22325830215437599690631031990051269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "2.25225952793516384642380501190928043797612190246582031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01987069469372759270453628912642728954230513534833089604954661995171725801656380902963421144934906141234552439696120736550210382743489449329697576830407056888118360526079463661066722214220114165138840831176499526985462507289995825151030297233511088604059436353741508088143154130210563278515547311543" }}, + {{ "9.12400440701637786139466257395724824164062738418579101562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "2.34400553054916376341521022652614192338660359382629394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "9.97821977486950583166084719161557689663568325790003522306021158417755185644936647878316368235185593329253132043532554677812935724747863173935255764658313396824835230126055857216828346612262350441572667853382236006603976105644273478945602579828808105896550462847104108659412377316272488653010471184196e-1" }}, + {{ "1.33795627811531119277788093313574790954589843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.48183812852515298791582915027831290899484883993864059448242187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000384349299045776862801360403732363545774843774701655200272080627739941386437175886379606902727479191090187794979610761904053274682140855025508483613322969568848488035529156236560186742600966591613965074184599845133474883618868818832890976311295886503114503738779326119140373893527826165039256344" }}, + {{ "7.06939041310026368591934442520141601562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "7.52070113177227312917239032685756683349609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.16601617096668251300410633861451144300904853213668949893514704576723535839139585890152639279492333481781656085682222252609689619088940700517823681224990153082715763605916833922234577262387169239662906567674441665483003247288718595609022710170750805174093013421029787059183231600348513197446175716344e289" }}, + {{ "1.46809474819978857951241479895543307065963745117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "6.55150258058036227826192998691112734377384185791015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.87508829078291473496350060709599928627355203095913409392108636898471105714839831302147923025254259824329731513966469918955762532776229610929533035120642195606951641982085398951090528368050382553009140996960228822308531093162518295270230167711636888797942089811261515649759631850124542086583338696866e-1" }}, + {{ "2.13403424835757107302924850955605506896972656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "6.74881959702026967828913939229096285998821258544921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.02087023232278898673025082821180943357336233310089987611387411667231521549575677239762600896132782138671932320359043850059141855317509884880628897347559802452573752440941620827448739200875424446592178873469737214134752340014718109265906882735838254335143242217171430272779729156476847140495477447567" }}, + {{ "7.95233844752690766100045038911048322916030883789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "2.84851678481346848315070019452832639217376708984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.52320441273088937482705455163451804728010853035570734024869989669472225400000323970014547943529070869582874785761555559916107563529628329435884632549334664560080647778917243975126257892837384804686623525333256233581024540617818741704180357848449262419278792476592443919338009722004675820379508226554e-1" }}, + {{ "4.86469155616132400629658683044453937327489256858825683593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "5.22877434444638661270587931539921555668115615844726562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.49398596693121402232511551773946216238940594887656584112333721649128338309222255715733045830942439483758414668436262063880698192055748811167639524982228502529443333539688201437948685066022343441584667892362197265423697997073104183476242310932155094648160217817878533689247152065556146288540676206268e-1" }}, + {{ "9.97061023610679164619341463549062609672546386718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "5.88064355210892131253785919398069381713867187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.31339250305317586137103280435203540286641209041963686984564977317675267872546421630007855518104235103746292194256810045376453068069833982650717834727768128915903290190711155087191155109113681049655966851631090461344965018352997694452739029417934674832819743056725077543693812469593253205921308221308e-59" }}, + {{ "9.25067228877758662708430392740410752594470977783203125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "6.58041095700439004900772488326765596866607666015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "7.34794411703227640768834559037146678081237450497151808641284692857257405073921261445846307144839876248119821368257643009964194784066475970698686506948363255089072439573285741549161564675949811535766568038690509602693098394199576228057991570285009737564027696021280582562413585412543950911326853262100e-1" }}, + {{ "1.27144511159262219734955579042434692382812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "6.18836319449928007330186119361314922571182250976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.55634262177085310455272777009125596103461766420555774353254576944288801886851836915203973701385795773437574206488784269131348804974222211728133676956373754063980028710578189114584286886146802067657659439377822750677886486205610448378645450751753499248735236114037268909383185086028320044219137753422" }}, + {{ "1.42205871841051475712447427213191986083984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.49175822061007323782177991233766078948974609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.31499443769464065089935605375459683035642863575091614297392875457512297919442473147075015935528487370816930373009973708163470195938036050657595355692444453780282744702410807810566482106290630446087507470829783752836539009991223629616484834464198297022741851935670638283977884632514115384409382379451e5" }}, + {{ "1.79830846471683798881713300943374633789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "5.15740741801222002740900940409574104705825448036193847656250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.00026780930725147708425182905646433452420215464014520968261578887024273841780021979940791064143678705875846798937060716374571767664452465951073901977576420551043883735274454852404885141087100496560513919957329201186421887438051030917217421635429456043545707951122601188323754670287140035060211268236" }}, + {{ "1.41617493747205998033678042702376842498779296875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.06659473408631241819755075539433164522051811218261718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.00214037426842670551611147350147052752193345171802567422360034056719592273707967867550926051192650203531759829732673928643729296057128383914827597014066465351929167430158631190618779931772000386360976972135737607634338444086468691888473748375182457345550820744493891034677687786078596412978684852640" }}, + {{ "3.03620445696295947202170140144517063163220882415771484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-4", "1.77755559529355344761114565699244849383831024169921875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.65907453809699509460147409829901675941527854788885630333979265214696163822247505595008528776776735251807610239492515526114770917079309768787319965003601255566849812163333057688474056980168539317656182802355025321396669769362336327872219770789870937515083196007462468888621524361865732646086424336453e-1" }}, + {{ "1.88150796984490007162094116210937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.96075222779542400530772283673286437988281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.33268783679377583213014321394305562443708551652324893198731298378098553656636607906131354129802125769805603337990709647117721910862833606977379369954861887407787985331605230823250624512728814254652735899657072127956911865541366861599183456838203731048557393074731179271410020592240238165188774584943e838" }}, + {{ "8.89727582886910006720881938235834240913391113281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "1.04127996077174773958962106235048850066959857940673828125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "9.99878344302358244722248144111222437762654865779811772935718213218215174416593116585765566781129897695750076434329093650632173287168263229734935010362448649517261601361617830618010680773234135778887817284697256494192909633866400288905649938277337678717548098982509457693289514879908537721749577461800e-1" }}, + {{ "1.83083205221824460440238624414632795378565788269042968750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "8.51305815268083279079291969537734985351562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "5.08759465190948202575969824985581134108808966132826957045953621966485495100532942367792704772987024490520063202480279983957515910756497430137889290866515761789926914423548570454774810411630371091100113544891279153106437138536746735808516608107152208446229082973737250416694137957514739571766896873306e-404" }}, + {{ "3.34665340825903966375139131361748923154664225876331329345703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "3.78685988588032159896101802587509155273437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "3.52212078787830927194297643296251781134291925779877466674871728836105722487573580131785145484495276918545575844013070305855330551951353365366550132397674036846629030890995284036782751533644901503503905390007269189142085867922573306793968734446410118933272999821289312420310855129959801669881803865858e-2074" }}, + {{ "5.33927735030905274151661471515595280834531877189874649047851562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "6.20766189867572767122939902950662371949874795973300933837890625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "9.99991034310800110010707678195555035460840436574922962233018600570397473321611757701145927433415065972844383465094874922585959664097551124468322387734536918015102243687653110114625528443011692213994065730522520240541725522418247328328568974843758308408263849244150678651666777627782107985602066092068e-1" }}, + {{ "2.19994195074324068173154955729842185974121093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.06707480325778616969678580517211230471730232238769531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.00952545862365855685219042115608145190455235613268820530406120489310419092421063376518661644406509494089174786391890344365290616699827245940846567812410266752069452669091303167176618868615804832415636793311353407444727299687139263635273616648724056070625009496090575286667611858626054037393426920940" }}, + {{ "9.49426131626506853745939285005306373932398855686187744140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "3.33658593189578134285966370953246951103210449218750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-1", "2.10953513637051167906362488703903898283324995313357160919327331939686921714903739192273840983847338772103005796728222224591772689334463276313863779738778665022741134644128703431090827473653846081611135627094959784765932765625500258444912393296945910143335619574776807349923037475968356403544804516261e-2" }}, + {{ "1.58204381201744226359551248606294393539428710937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1.69967088875234341601404286503651519524282775819301605224609375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "1.00000077966919198536118506000604021848342587459233214812502825319036185927111842640720441778472762148840769009480654434988580516960635247026640481971290957649218368276357248615028690535272593446475039055115505472342603119011692356413204456935489635677140077206818440909527541341514742179392759484948" }}, + {{ "7.89159836081502775182242026552614788670325651764869689941406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7", "4.81696106146368038025684654712677001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "1.94147359401180853490618926342983857830809890106752620847948172427377774972592621604834694930262822082783398795004418901297871494637794539318032606545630879764294273346094400196886499691750495365869112152459387957968585556903274684614177896724684391146995388586545846815713970966406314356957705636188e-2940" }}, + {{ "1.28909708384213387034833431243896484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "6.93039877413820920581954965200566221028566360473632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.08496647090160629262865176257751429047729744058064486558757367783712447981236338124011887293782800275409466363098994983981904989007840757365461380428739706364354348918768376442904733609028311603151255847131247523710764847675936168535507206845244124708518371354311381017836653040028826211975497871572" }}, + {{ "1.88979339146257488413205294364161090925335884094238281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.50746279790036936674368917010724544525146484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "8.76918423991144038304021445193438173201942067819279237648900596695575024236585474624026460405210909663314261583560910578839787952809598740673148266220449752385049510413309645447866767727463403580780664879153239139760411591518829772808581212853680494395035365090735562853954119264286528501466090236373e-42" }}, + {{ "8.41517212362860789198748534545302391052246093750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3.64690954096749919699504971504211425781250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.36385641555849335879047779054573450503531219143280186506059811952516602814802026798922317458022305556248077861115239238036534162971730930403784483407045473794360984711531633071954017599185535725837014265828161774595330813847033913388549400091383297967089159291617295023155265969142242902513558326176e3" }}, + {{ "7.79453915372945402850746177136898040771484375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.37570185974411316465193522162735462188720703125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "1.06022076559461302576262215724290203547920286581395364873074659478022575993646868223512587189711310741927159850526321306597320278985726000202501743927791980296512242522543006053260060771089791556404973296770985910119125940674256012428243689156025466514102435785983398909290409351186888763744330929933e26" }}, + {{ "1.53996830801468109712004661560058593750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "1.55753945580631575351659989792096894234418869018554687500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "1.20447431374301175187511662239775886280442123057569989101048717965641664163683965122530380365781626549245733448495292659434928101251174655724999866929500920292760069066534315397658186379331270528348085084759405281722204998903474609597521346801285181467380964556686904383585877178604246579963496131145" }}, + {{ "1.58292085642406949773430824279785156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "2.39839658341223938009534322191029787063598632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.95369184630899349835322600435195771430552393938403392920497743251505007693757163085390208500076347439614593692001276141903681987497427879862172599262551403341684739246319058993775975522937386429303489479759146923528741632009619169067978673180741577543638362298805900307916877489621750277562246056785e12" }}, + {{ "1.34007962789787852670997381210327148437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "1.93078487352859630432622140006060362793505191802978515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-3", "1.01851774851557016267678896947673493426952146980838508956199625705868791978344101642179134412654468177801448310465798049263061832294449615311708734175434429497593168411288076223275335865898358255932555661831601275564405349791579099870920484601878548075981946266790952650050188664408833668093366337128" }}, + {{ "6.57565090460510646153124980628490447998046875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "2.95349579102368409166956553235650062561035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "4.92883670959819008737323351550818895693909971573197862669756297233542900030950953480711710193053129535412775508169382249001427538228339649766961919628309117712145393012207284297044617755253176225355208718450804357511545954540599873761726532747435308616642768909463909723766874135347528684022648860560e53" }}, + {{ "7.73401481707858096115160151384770870208740234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2.49148120277696079938323237001895904541015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "2.21022119284238444262099118632640694751857489911985882302778583637174384391251394588072250813144879442061174245455228341031066580984347413608919792407019123272438031870871777573323381609534176617167457318208979616222032754767955294734636001910121462806120247278470491361024670390806812831433737112379e221" }}, + {{ "1.10978898863228390113400134708854238851927220821380615234375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-5", "1.32219377403916382718307431787252426147460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "3.07947867569658321194458380597181231565685445537647073748124994390202466909582021155440785847623999110729024670271166064504654713592331835440877924887265726281088902886492996205474623955394661696347608605548560131153946508949187941058346142181719469523416895370937975489878692955467549849494731965625e-66" }}, + {{ "6.01388538493091151515557157836155965924263000488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "2.60022931107700908527451122420615092778461985290050506591796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6", "9.99992690524283092045041727666257712294170472055655983655789156306985603524706361035867762480294454684826579379760817381252880474747063748101481751389649370586878847928039436815138481244723824252557644191693486953238362877605577315573573222917218930477592061427550313462645068276263623663297863327092e-1" }}, + {{ "2.15534801432384071073755649194936268031597137451171875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "4.05812814671632215990371150837745517492294311523437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-2", "8.55799445393602464144976083125961944702079982479924287374752573999342183140040918969698718557087349720031284500593972794455976395816766982409031253828819168807248785638632014800512514311905184872890032777260194266023572565329278809193542262172193713145497824126566400120337339261082686915643720103934e-1" }}, + }}; + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = pow(T(data[k][0]), T(data[k][1])); + T e = relative_error(val, T(data[k][2])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_rational_io.cpp b/test/test_rational_io.cpp new file mode 100644 index 00000000..34e66e6d --- /dev/null +++ b/test/test_rational_io.cpp @@ -0,0 +1,145 @@ +// Copyright John Maddock 2011. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#if !defined(TEST_MPQ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) +# define TEST_MPQ +# define TEST_TOMMATH +# define TEST_CPP_INT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPQ) +#include +#endif +#if defined(TEST_TOMMATH) +#include +#endif +#ifdef TEST_CPP_INT +#include +#endif + +#include +#include +#include +#include +#include "test.hpp" +#include +#include + +template +T generate_random() +{ + static boost::random::uniform_int_distribution ui(0, 20); + static boost::random::mt19937 gen; + T val = T(gen()); + unsigned lim = ui(gen); + for(unsigned i = 0; i < lim; ++i) + { + val *= (gen.max)(); + val += gen(); + } + T denom = T(gen()); + lim = ui(gen); + for(unsigned i = 0; i < lim; ++i) + { + denom *= (gen.max)(); + denom += gen(); + } + return val / denom; +} + +template +void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::true_&) +{ + std::stringstream ss; +#ifndef BOOST_NO_NUMERIC_LIMITS_LOWEST + ss << std::setprecision(std::numeric_limits::max_digits10); +#else + ss << std::setprecision(std::numeric_limits::digits10 + 5); +#endif + ss.flags(f); + ss << val; + T new_val = static_cast(ss.str()); + BOOST_CHECK_EQUAL(new_val, val); + new_val = static_cast(val.str(0, f)); + BOOST_CHECK_EQUAL(new_val, val); +} + +template +void do_round_trip(const T& val, std::ios_base::fmtflags f, const boost::mpl::false_&) +{ + std::stringstream ss; + ss << std::setprecision(std::numeric_limits::digits10 + 4); + ss.flags(f); + ss << val; + T new_val; + ss >> new_val; + BOOST_CHECK_EQUAL(new_val, val); +} + +template +struct is_number : public boost::mpl::false_{}; +template +struct is_number > : public boost::mpl::true_{}; + +template +void do_round_trip(const T& val, std::ios_base::fmtflags f) +{ + do_round_trip(val, f, is_number()); +} + +template +void do_round_trip(const T& val) +{ + do_round_trip(val, std::ios_base::fmtflags(0)); + if(val >= 0) + { + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::hex)); + do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::oct)); + } +} + +template +void test_round_trip() +{ + for(unsigned i = 0; i < 1000; ++i) + { + T val = generate_random(); + do_round_trip(val); + do_round_trip(T(-val)); + } +} + +int main() +{ +#ifdef TEST_MPQ + test_round_trip(); + test_round_trip >(); + test_round_trip > >(); +#endif +#ifdef TEST_TOMMATH + test_round_trip >(); + test_round_trip(); +#endif +#ifdef TEST_CPP_INT + test_round_trip >(); + test_round_trip(); +#endif + return boost::report_errors(); +} + diff --git a/test/test_round.cpp b/test/test_round.cpp new file mode 100644 index 00000000..fd72c2e0 --- /dev/null +++ b/test/test_round.cpp @@ -0,0 +1,415 @@ +// (C) Copyright John Maddock 2007. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +# define TEST_MPFR_50 +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#ifdef TEST_MPFR_50 +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +#ifdef BOOST_MSVC +#pragma warning(disable:4127) +#endif + +boost::mt19937 rng; + +template +T get_random() +{ + // + // Fill all the bits in T with random values, + // likewise set the exponent to a random value + // that will still fit inside a T, and always + // have a remainder as well as an integer part. + // + int bits = boost::math::tools::digits(); + int shift = 0; + int exponent = rng() % (bits - 4); + T result = 0; + while(bits > 0) + { + result += ldexp(static_cast(rng()), shift); + shift += std::numeric_limits::digits; + bits -= std::numeric_limits::digits; + } + return rng() & 1u ? T(-ldexp(frexp(result, &bits), exponent)) : T(ldexp(frexp(result, &bits), exponent)); +} + +template +void check_within_half(T a, U u) +{ + BOOST_MATH_STD_USING + if(fabs(a-u) > 0.5f) + { + BOOST_ERROR("Rounded result differed by more than 0.5 from the original"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << u << std::endl; + } + if((fabs(a - u) == 0.5f) && (fabs(static_cast(u)) < fabs(a))) + { + BOOST_ERROR("Rounded result was towards zero with boost::round"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << u << std::endl; + } +} + +// +// We may not have an abs overload for long long so provide a fall back: +// +template +inline T safe_abs(T const& v ...) +{ + return v < 0 ? -v : v; +} + +template +void check_trunc_result(T a, U u) +{ + BOOST_MATH_STD_USING + if(fabs(a-u) >= 1) + { + BOOST_ERROR("Rounded result differed by more than 1 from the original"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << u << std::endl; + } + if(abs(a) < safe_abs(u)) + { + BOOST_ERROR("Truncated result had larger absolute value than the original"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << u << std::endl; + } + if(fabs(static_cast(u)) > fabs(a)) + { + BOOST_ERROR("Rounded result was away from zero with boost::trunc"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << u << std::endl; + } +} + +template +void check_modf_result(T a, T fract, U ipart) +{ + BOOST_MATH_STD_USING + if(fract + ipart != a) + { + BOOST_ERROR("Fractional and integer results do not add up to the original value"); + std::cerr << "Values were: " << std::setprecision(35) << " " + << std::left << a << ipart << " " << fract << std::endl; + } + if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract)) + { + BOOST_ERROR("Original and fractional parts have differing signs"); + std::cerr << "Values were: " << std::setprecision(35) << " " + << std::left << a << ipart << " " << fract << std::endl; + } + if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart)) + { + BOOST_ERROR("Original and integer parts have differing signs"); + std::cerr << "Values were: " << std::setprecision(35) << " " + << std::left << a << ipart << " " << ipart << std::endl; + } + if(fabs(a-ipart) >= 1) + { + BOOST_ERROR("Rounded result differed by more than 1 from the original"); + std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) + << std::left << a << ipart << std::endl; + } +} + +template +void test() +{ + BOOST_MATH_STD_USING + + for(int i = 0; i < 1000; ++i) + { + T arg = get_random(); + T r = round(arg); + check_within_half(arg, r); + BOOST_TEST(r == round(arg + 0)); + r = trunc(arg); + check_trunc_result(arg, r); + BOOST_TEST(r == trunc(arg + 0)); + T frac = modf(arg, &r); + check_modf_result(arg, frac, r); + + if(abs(r) < (std::numeric_limits::max)()) + { + int i = iround(arg); + check_within_half(arg, i); + BOOST_TEST(i == iround(arg + 0)); + i = itrunc(arg); + check_trunc_result(arg, i); + BOOST_TEST(i == itrunc(arg + 0)); + r = modf(arg, &i); + check_modf_result(arg, r, i); + } + if(abs(r) < (std::numeric_limits::max)()) + { + long l = lround(arg); + check_within_half(arg, l); + BOOST_TEST(l == lround(arg + 0)); + l = ltrunc(arg); + check_trunc_result(arg, l); + BOOST_TEST(l == ltrunc(arg + 0)); + r = modf(arg, &l); + check_modf_result(arg, r, l); + } + +#ifdef BOOST_HAS_LONG_LONG + if(abs(r) < (std::numeric_limits::max)()) + { + boost::long_long_type ll = llround(arg); + check_within_half(arg, ll); + BOOST_TEST(ll == llround(arg + 0)); + ll = lltrunc(arg); + check_trunc_result(arg, ll); + BOOST_TEST(ll == lltrunc(arg + 0)); + r = modf(arg, &ll); + check_modf_result(arg, r, ll); + } +#endif + } + // + // Test boundary cases: + // + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + int si = iround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), si); + BOOST_TEST(si == iround(static_cast((std::numeric_limits::max)()) + 0)); + si = iround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), si); + BOOST_TEST(si == iround(static_cast((std::numeric_limits::min)()) + 0)); + si = itrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), si); + BOOST_TEST(si == itrunc(static_cast((std::numeric_limits::max)()) + 0)); + si = itrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), si); + BOOST_TEST(si == itrunc(static_cast((std::numeric_limits::min)()) + 0)); + + si = iround(static_cast((std::numeric_limits::max)() - 1)); + check_within_half(static_cast((std::numeric_limits::max)() - 1), si); + si = iround(static_cast((std::numeric_limits::min)() + 1)); + check_within_half(static_cast((std::numeric_limits::min)() + 1), si); + si = itrunc(static_cast((std::numeric_limits::max)() - 1)); + check_trunc_result(static_cast((std::numeric_limits::max)() - 1), si); + si = itrunc(static_cast((std::numeric_limits::min)() + 1)); + check_trunc_result(static_cast((std::numeric_limits::min)() + 1), si); + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + long k = lround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), k); + BOOST_TEST(k == lround(static_cast((std::numeric_limits::max)()) + 0)); + k = lround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), k); + BOOST_TEST(k == lround(static_cast((std::numeric_limits::min)()) + 0)); + k = ltrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), k); + BOOST_TEST(k == ltrunc(static_cast((std::numeric_limits::max)()) + 0)); + k = ltrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), k); + BOOST_TEST(k == ltrunc(static_cast((std::numeric_limits::min)()) + 0)); + + k = lround(static_cast((std::numeric_limits::max)() - 1)); + check_within_half(static_cast((std::numeric_limits::max)() - 1), k); + k = lround(static_cast((std::numeric_limits::min)() + 1)); + check_within_half(static_cast((std::numeric_limits::min)() + 1), k); + k = ltrunc(static_cast((std::numeric_limits::max)() - 1)); + check_trunc_result(static_cast((std::numeric_limits::max)() - 1), k); + k = ltrunc(static_cast((std::numeric_limits::min)() + 1)); + check_trunc_result(static_cast((std::numeric_limits::min)() + 1), k); + } +#ifndef BOOST_NO_LONG_LONG + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + boost::long_long_type j = llround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), j); + BOOST_TEST(j == llround(static_cast((std::numeric_limits::max)()) + 0)); + j = llround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), j); + BOOST_TEST(j == llround(static_cast((std::numeric_limits::min)()) + 0)); + j = lltrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), j); + BOOST_TEST(j == lltrunc(static_cast((std::numeric_limits::max)()) + 0)); + j = lltrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), j); + BOOST_TEST(j == lltrunc(static_cast((std::numeric_limits::min)()) + 0)); + + j = llround(static_cast((std::numeric_limits::max)() - 1)); + check_within_half(static_cast((std::numeric_limits::max)() - 1), j); + j = llround(static_cast((std::numeric_limits::min)() + 1)); + check_within_half(static_cast((std::numeric_limits::min)() + 1), j); + j = lltrunc(static_cast((std::numeric_limits::max)() - 1)); + check_trunc_result(static_cast((std::numeric_limits::max)() - 1), j); + j = lltrunc(static_cast((std::numeric_limits::min)() + 1)); + check_trunc_result(static_cast((std::numeric_limits::min)() + 1), j); + } +#endif + // + // Finish off by testing the error handlers: + // + BOOST_CHECK_THROW(static_cast(iround(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(iround(static_cast(-1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(static_cast(-1e20))), boost::math::rounding_error); +#ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(llround(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(llround(static_cast(-1e20))), boost::math::rounding_error); +#endif + if(std::numeric_limits::has_infinity) + { + BOOST_CHECK_THROW(static_cast(round(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(iround(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(iround(-std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(-std::numeric_limits::infinity())), boost::math::rounding_error); + #ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(llround(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(llround(-std::numeric_limits::infinity())), boost::math::rounding_error); + #endif + } + if(std::numeric_limits::has_quiet_NaN) + { + BOOST_CHECK_THROW(static_cast(round(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(iround(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + #ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(llround(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + #endif + } + BOOST_CHECK_THROW(static_cast(itrunc(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(itrunc(static_cast(-1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(static_cast(-1e20))), boost::math::rounding_error); +#ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(lltrunc(static_cast(1e20))), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lltrunc(static_cast(-1e20))), boost::math::rounding_error); +#endif + if(std::numeric_limits::has_infinity) + { + BOOST_CHECK_THROW(static_cast(trunc(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(itrunc(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(itrunc(-std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(-std::numeric_limits::infinity())), boost::math::rounding_error); + #ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(lltrunc(std::numeric_limits::infinity())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lltrunc(-std::numeric_limits::infinity())), boost::math::rounding_error); + #endif + } + if(std::numeric_limits::has_quiet_NaN) + { + BOOST_CHECK_THROW(static_cast(trunc(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(itrunc(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + #ifdef BOOST_HAS_LONG_LONG + BOOST_CHECK_THROW(static_cast(lltrunc(std::numeric_limits::quiet_NaN())), boost::math::rounding_error); + #endif + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(itrunc(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(itrunc(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(ltrunc(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(ltrunc(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } +#ifndef BOOST_NO_LONG_LONG + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(lltrunc(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lltrunc(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } +#endif + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(iround(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(iround(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(lround(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(lround(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } +#ifndef BOOST_NO_LONG_LONG + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(static_cast(llround(static_cast((std::numeric_limits::max)()) + 1)), boost::math::rounding_error); + BOOST_CHECK_THROW(static_cast(llround(static_cast((std::numeric_limits::min)()) - 1)), boost::math::rounding_error); + } +#endif +} + +int main() +{ +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); +#endif +#ifdef TEST_BACKEND + test >(); +#endif + return boost::report_errors(); +} + + + + + diff --git a/test/test_sin.cpp b/test/test_sin.cpp new file mode 100644 index 00000000..571beb4f --- /dev/null +++ b/test/test_sin.cpp @@ -0,0 +1,313 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "-9.71360659712083391437631022096936715962104815777147739346439739644168480837178969413799829610404829247283169084501281105e-1", + "-5.95431113317256105006804890684659010940293672390817519158205264611725147142085353698349092164137652363446368483953564682e-1", + "5.09924118934356013545988500545586843463766955556781588535384546070893806324487181574368899833574915659357543038822935347e-1", + "9.90602974910637417521410554344955057938063175873799034495811832851567842600306335485818201417146475654562543760051881571e-1", + "2.57755634110962773819397192502372718147953063328591480930319110437537556577887190430547163274290595074462686853519200826e-1", + "-7.90852129665907861812449876176102241731921451584589870529143390612597378289323905030142878920134443274067663564142249906e-1", + "-8.70636054394434218558219672958497111094237434037462776135170928197514857325641761722162169311905082223410873872693125021e-1", + "1.16142192225871586802402588799179588339908282696987123538816621894316618250692422106879105583060486278819650782761165055e-1", + "9.60641850565339311654365605083646127348817546384991780755200411966145627086231307074524787693440076802209868233548778731e-1", + "6.28318825240308217440049590303028869715272770671179428040549526344092598897275498972932981684079339892035243316790587027e-1", + "-4.73718579778960595001132927360485548840577209745936881040433718918629103032639945353908537818475936329314134212199346978e-1", + "-9.95432766494621395340223548609251497842694553405493731879049259799325119533316838972006879914623359183523219011870805961e-1", + "-2.97704078652633309130390182393607392013126109733352620573058826659738026681661456497779386104992235762190242017128767206e-1", + "7.64723391125286889782047394187107836056829439952009227196240883193721606229047061163517791688110517783506991004016374431e-1", + "8.90335717074674250432504838435892622513509178529392798127561987551398090841490265311069534613651712468228001675091153605e-1", + "-7.47469618974513669394515485690188234127771130501791709462887130373371023385813212165673231177548426835629029005547008861e-2", + "-9.48261778982069330544079494960981900232314056127899219497335245577354566418258722147558010380033694835705634428764954401e-1", + "-6.60119969404606610211922488494059074732492583049845598285779387022002845776084527598443564095143849120847643366330179739e-1", + "4.36693827009658961576344650626557410722590226545637608661764593658572210930294024902150766064738444736422263939746970132e-1", + "9.98541130824430070642243744636010968399851408459030982248969144276197147611376115185206245742327729890090526273555800490e-1", + "3.37137695943362070360548307779555944485385294617304662646987679063953108310365389494460188124285214040163147170304540339e-1", + "-7.37272196933518190054375156317136276073182897209685319124536092629865074949247291797880288692223977281455156619510259042e-1", + "-9.08495699506960201290293288218820500948312195353635174830883006841931398581001427066173033535720385301624330783999899511e-1", + "3.32224697427099307204044509056982627738295866011152619834749776109067529453431741767996787924292629814505731320175556430e-2", + "9.34241854135599266375493853147210486293657026766576383005045752264274587199837314096798394557243705656211732557069413970e-1", + "6.90779551281016826784976005137338585011513089446563025258584317423906941741640583083551185645679047405447557105684226754e-1", + "-3.98913888475082839741071010629509607776766095858433376450534753556286110518195743624946499527251336022805096741714382999e-1", + "-9.99922692526403520897313527841668431397204867244750030781062964701898557028332255650446046614062333174844253917288331438e-1", + "-3.75988292423704532504216998833472116186771022412627192871974303806891208635376610998425108046077306043945435504842144332e-1", + "7.08546019140379445669962535829318394094758212505515423960726677977484727061149949358051741627739138448760095710063342839e-1", + "9.25084597170819667485373176055260044057716794391569156042799693611964098948722923916237050181882167134906470192542857299e-1", + "8.35947487571472125423673177137150279693224632368449469153892167972732129345714981936363891382927399742266512920038864004e-3", + "-9.18606321039298722214219289469027246078943851192917449117591801249272620492502932760495762195965214412326830491755901723e-1", + "-7.20244550473164405555518647469765134103488938825118543602681358279149452868549672550326500728323814331193184035259160414e-1", + "3.60444097985855629825697367385029316833790934188475151408740160657889784929257301330229580694580194294034115152177674537e-1", + "9.99575062430677992414643463029115424067356090568060307410717467085018957489304987413609313388961297483138454662118061646e-1", + "4.14188682766963304833862149212585018360876819555612195218295874225032162838027842720351664698295767693697842043579048219e-1", + "-6.78594534657286312316409269272929566493548786915986771929001823358451551885758307761400157853363173388867780400090112946e-1", + "-9.40073722462713282312837596921874850901167502371739429501407718251639587081137893231736511487958940802467918593519005653e-1", + "-4.99269632411748222821310824324558181913141458235676771744322439351386139493233963671531219603373207564905654915871172017e-2", + "9.01382218619061521491363679812206948759377256420255657634443270431495336446996377562469573885297156497163691224107230524e-1", + "7.48464012406957686684753003872919309910943477238245908909177973105841950470333390670719219379167068809799710776770734833e-1", + "-3.21350982331168500558883709193541886146178412146971245706190880193067020283050714591560922441331235332970961845050217575e-1", + "-9.97498841702838239659412520756556451623238132913559678626409839807628110807613195403956929948379909495726426243705794281e-1", + "-4.51672806064485973599605876288778011355969815150135195358334589946828629430271875346142404286368814526016297993583170592e-1", + "6.47469539349743367777844577149239337681085253251300560380374646379682072633705733561446355539618404778987844138766238618e-1", + "9.53437154306238691456130012770111782377503876017231780889420296856266641153714110120975772709549811845909173386912105405e-1", + "9.14081116365893107669584386407698218216480671014671832303147213716318806206478591012619084058741626713939006968851852873e-2", + "-8.82599332954202005638662236444958997569939600897565089251125658458817750203393016337212996488633688567918453254294067039e-1", + "-7.75389136447631492669594511701990356678047393586968390929688701894781023967621486245394406725747074772996680491766725244e-1", + "0", + "9.21877670451674413245307018032333288624288893879527153976730741889055419244554390143014969580425598422296522787223865492e-1", + "7.14420247379307162288182477560228852605155250738051326022559557923361829606843109334201812861061126243914893718333771523e-1", + "-3.68229061503980158220203193441625324286779814470455045264018328963975686564161509474566417124652588774892207244798533238e-1", + "-9.99783810945210864429782835782052003838999970584938136857974918523615732378678641269300999292060748749245257644847852880e-1", + "-4.06565491434208630299086167510578859920684132980243005899494321151205958987020300473732138517681916554185382528057861016e-1", + "6.84710967469127345624707128760638003100107237269026812211460044517359789036617753689648451870956943571853410785082804567e-1", + "9.37190534692875414284475879207349713030454322911019395907169592096165438597133651606167760904128838721803617281109050826e-1", + "4.15761692057244148543310701200534576325308397337003695681679007540324069366547327722258885686349619359915993749152386902e-2", + "-9.04970579658619470380865991258110513843850446973806499697900678159194774744593408797468966041695053471205276923200577190e-1", + "-7.42894062146919717307486895770712177633720181625852464705801879158549930143011385755502810839808877188169347497140463278e-1", + "3.29255843672460745277513964057060067396377984587222455665841087186879420769340447084849343957766905952270152874052907066e-1", + "9.98054859318969984153930327705164465077718593220578997216979734167429154849012382322757855259404199572095265136279871773e-1", + "4.44198837297768694342150710437773511448850303134514239359160353596186338967438818161771076138440975975069051604632938785e-1", + "-6.53817599431343721060913145888825198919543068369083977787231740776950274433927919565042681494795499030972133972973154991e-1", + "-9.50882691455803790808811011811129940528171185220498569922200361836899859377942311459807744784166538095896117442350480286e-1", + "-8.30804396823694462619418608693397504202900045660409997788297791645107264729830105800672434941805906654953509298579082883e-2", + "8.86498500176738212245618093138553877114943127333459437678466772704535139826656179981455385901664422134192971441152486596e-1", + "7.70083171278361495868782270594413506070341191348346709317329019377797940394556787220273230008072684372906392335068211595e-1", + "-2.89713235318575682157337623325710322388267200178020040738121279630672170355171163891332847251952971324782327373734923025e-1", + "-9.94599945986602107902462030221489305674036413322184167100620086215068494963807086265519051279456167270901961176645890910e-1", + "-4.81064018790479216363003919039401079745827607566793090566247167201506427394383426836725220489510187378030886775425254046e-1", + "6.21793567954698234151923123976248746751871911018984490371928031737872104124834908200003970971778452547150523318639635937e-1", + "9.62930462544790791995256817531759605974030310743258985429278608944994805716203043054967792555227147404499205611680348343e-1", + "1.24441037037160425420824052419427892644210865386492893504553391973646623439822770473194845274620957661128504291608680469e-1", + "-8.66493376243885476034533210550037276824055111358129259572484897399197578809821587005093985112028866251515011805996119334e-1", + "-7.95940555954229526911811786010975888490876487056728372525209250018208474961217211282867562886053609351620626802054272020e-1", + "2.49669618482792917975718339302754781070461300705127317300546100189317933291972223791458678771914034385073586648459580423e-1", + "9.89425045617789945796335206411736550560149597573171983909624851636680028232543261568285131480585113303281176722731984359e-1", + "5.17097284014384149171097163430722725596083616428334032893201431916692899725128152827282357887267679461332587145165393473e-1", + "-5.88694253013035419947972745515246684318073372460957150709985237608958241550865774225576562359889367149484593966586261944e-1", + "-9.73313013442224866478107643999632554759604190263325143130961313777287157745245701134838602677190253924612391775436901182e-1", + "-1.65586435334914172055850479429458408174448669771862313204835451683387762284114799645762688524058144409210946183564694437e-1", + "8.44989803230758608979729460217254170202748876564967551526138387646760352687916491884649142029664716335759879232648284164e-1", + "8.20421500340164168068753907367027481963552257850283600606773656660614708517253273174848291641569969886126754639035754147e-1", + "-2.09194241612317592929856274655591551278574667482924447651723415490434554354833563537792618079275726893013991849104465053e-1", + "-9.82539107299636472172005507105476251789057582568202763534005396813858490465264145708502581273803767931004018272989858624e-1", + "-5.52236319725534543207688775430217404447704139560595336544456138148662731976576062425879410116209671353021251780801885578e-1", + "5.54576894095302137473562870411642498454159878739464625116831971740997730359915227524075717328436463081497500485416831879e-1", + "9.82012389338213987427432686899213579991770436451929205950504261612336440523069987734051927060071228336651935114247230018e-1", + "2.06445480789661722781085666935934466710665000093111315471318244086154187788240397407764949071589419997001126229699279918e-1", + "-8.22024967814241172490083350373664443948382772873119098939533117836179462362265599942085298240078400862839510315401568501e-1", + "-8.43483668915081157881609334416452212500481988371373212797897630926101856989377353686006695443683562952698091745372956064e-1", + "1.68357099807987317797633647903674089665368628422558854222230995142941489911909308417314277825877040168111682241442337249e-1", + "9.73954039060780508698548127540108987785881109985102169990241290387386676882934112332475075476604334818263785540220696343e-1", + "5.86420359093869515237687266954561200160006212641211187483350874672859136679499954407470935299385535928011115437979374327e-1", + "-5.19500491219840443397382144913775579016253538466887540765306393159738082663675375499840773403952929977354698339617261390e-1", + "-9.89013546180296021750901758474634735102493497248279924875522015911873550276888689676425102442986261848126775556194306727e-1", + "-2.46947514812703938169894550153319655995779907820829748198209521180129269232387596803077057086642606505827139155491603712e-1", + "7.97638583669534812597149574893980942155226403291812660315816507318428697361476484505958849067790885048775312980075497096e-1", + "8.65087179683067252708187359165577777305998628817518314353161876891989239932835217904989326717355654871984067712207255166e-1", + }}; + + boost::uintmax_t max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + static const T euler_gamma = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + T val = sin(euler_gamma * ((100 * k) - 5000)); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = sin(-euler_gamma * ((100 * k) - 5000)); + e = relative_error(val, T(-T(data[k]))); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 5000000000uLL); + + static const boost::array small_data = + {{ + "0.010890646307437399028563191160252839599929232814970922208664909237494716181484215717644776933044418903207919912063594159099133490979634344811936925144447725948305353257042599564404885434349760121009797816724142318243738364307036155852011004353462651092012819894667485840322627440332163428546845499107471983896711023161969130462687924045508477090891879273259947713367290982391204265694893491531721581439", + "0.029754394000520972141380267705677256353702996169858414168445272181777338962866552847084800544086743338130195210005002660881957584567978770485056322086472328896988088721899728258224129935989180857437073412730903070983582129359565450458299328041955729258476583848159389714290107649243089149974776893563078190705561325124542669960182002956940545214147678093802442811362846262655415145897575707676223535749", + "0.04860754948595027759689273751438643634234576398271158524070718139962965653841137425728738193533514318422431877217110239554743968609870039776938201724688048349972662394084789924867267405853696017478160702683117974766657840965270625814482422398422216605490620054574252910928068433847115132429726072853170339113804838625536981361490008602432476302086066307320875870985443111858828925332085101376920451257", + "0.067443401266329792365583268418977022587089806595860818790246293104463576184436096833111903064801552379988362224633198052490234517656318474005568709048710308123967082103235230201516378834855764348740505470176912466587139988300259624310153055247378188811239571439869254255368050758213303082097176168650573121101094016896349982672715603054645687782535250201448606757920212668324401846105554332382154705308", + "0.086255244004175604199645786226683865650130764638142939010554245919172299560583634262067769465886944689883333394099120765964771092069938753689253686543017871063587988437235057514131760587649504670117933814486942187589706655157340717185354058186603027300571692666150552274324933749082047517987509942119060274537912867956274549119040817359639741746006374702951412541338483858389306953539029174581171144916", + "0.10503638090893519164596691292161072193010174143933600597680115817738720676321226654184308409972393036413684625874294713490753271261380987552528236660688624108474124469034444076627315674234385578608111398112242272762722849083801773818689342174907858373883192220827687618321085007917387951532673599267211035785307947515638810735621964273183425401191468313574763898720597251843424536611952986478638938787", + "0.12378012612096459891996422671239906394195356627713556749926735466337892925173796651675302282473738808218327028589606894825728784823540605065317506645900565980161901287116410208049542818796994171203890952761651470187834173644651508025088970034800067245131759655003164127161058084682831906406941473650395873577925901419536540828468001386512234321890242266327761400155849351025221609783793228816606096155", + "0.14247980709161433833827358255114404185333478069639957369769805221957506649654851981837061160249376538785737485777248817812720592537597263252706422066438137522011148566625861552209380620325080441618503257506798981598559897331754555335688284111417797211888381141445522536739542765207936516297907076923899840216864191777039028622886076254231994264908278499537587536902686114072117102531777746791366147472", + "0.16112876695857673825462942280040873226725445145336882995544646098546697397681955191516861690559627281570477802647683153249828731761062718487424104325152088763220776831248566486363299448443795266104568555186977695939803420793575204146124697832793773870449082377964029658283741910741804550762511379894890589132658450368609377005630322641674351408014813725947288936865021810537922503050280596331958949813", + "0.17972036691564914131189073707203611766536704952071818203835281740755093560444625679032703078557333645546302532200674729781663838075105196332695024246509042831095553050804767663788014113177991938252225120228302734228632787082072480689719322299247090887229731260135165819595797392665106642595359433094386743214852929965104946276195924300495453775467378376551444126292108291215861133471208854009513721707", + "0.19824798857606934571352609051549058593435535174283382080060738672122306773474119459815363636791069253463660528114022041674780565798655265640072669329819802234483545444085426470661233958030668844326674768815456315879868376252722369574694411591080512527683145774214215193268992508938562109669843137270238454905091555179756374512457742554641355319960601765568460966738628365652972463731882673979926092423", + "0.2167050363285819704223187876642169717474346025766606244643176750460657731203611217470241676182041675112171974414875203007374497968642376196256262296063879827128970901451226217571636202438144440234868076467587220541438440149682254317134405302648426790500751310485432990930185087578150399032543990173811106465656404530116032387260432178319507278340110997943206401370789106214680733463126804159766688178", + "0.23508493968539701289801441539326267060915175918342580386836036980227948313782327655061004506711767031388143537081826986030990557707922203603349984851809173788402101756510017046639631528282698404857654444279509591873678208318484036337040837844539190863615310872984455261973647897667843302241773795592355085118273592671348602240382153223466391512738221253451636183066773121830262978729780866153048605159", + "0.2533811556212047542679161173582151227103672187769971543582388259784795155332622779547839459016647290250036005712168909799523370471647322112833886051217950625710683025675691585734514265087749450457714578451290681140064635291501640395753290532318406110106892218388811781561305402570000283806458134435822529043797962340420841850011846648265787470508569124672250211852546600514370101687713861131209463861", + "0.27158717090241435065755609312085387589073221253701701142877476904254125053252466469600403650634482409879186635717002370089097070045821182432642232618427944489732133359996899812980722107011126957850576210476679069162561257167921627603536603943342268770727524690332400255408587654094512383349857596775777725888982277559281982571487656535560758087235441872907962373375423740325723506626374882319859924962", + "0.28969650440578692965912855479777150523900698183973110358010443581781966348171378962307935462457921708108325003566673849851640304571019200113280406744551445148200341554501141174444530008329262826786160080931309057528673711507934822659456861163197618813727062179453555460400169858233923358238607875306523866767536243361049306545596678120228677505849040202788510059415993219975440657979707947898632705847", + "0.30770270942563778634443222550824378057595253208974144909939396933701715445493088586920897452838893301853350676955400357197838773823140696209649573828382477454711986806154497998912926265388494228459988323524548750870702083339285969468391846533348589851520262990720843670148790211009236063622194282315540801467216625666505663699480592080398449845511909092071640909885054719301078547683325662349532658001", + "0.32559937596878634249263192973385963275552570142977727375619908690982968889531407133936548327912894149757305868454394002531385820341045863161146695151908269553629121372700695833373968533510661265854738947940689721812230819575490874211279007289828369964583273676393398981064015459284982970048174649094549631109312941188691838118955683939990881732219088392629316401227525790752712758279892546851835776728", + "0.34338013303643689435259984865624959352259286039436985939426483729323987764837568376066164703227630278807584950278626035763399164177429894322425866236150336898079573258157833074772287354310049676029566569737995054499018518699450946056626536479822852758163848528920078247789349605898976290484284018984355696648190967701849464571286257873661615051036433297599097073117151941857301740816310919312668936753", + "0.36103865089217782674224266392907326208964452822379102503439414768728197653534265911503054023760783622236800804794470785631737993143180071550223728801984904852623160397230839644629077782630949486339104760008566935013234195735777070582106661423219379374522941522832331186147905332977726043795737008218909226025962294880541867964419424128310806148008435847967256901208159302482322730929744194185143496647", + "0.37856864331529191294683302986737462527422720295203122486985051910813389831630458742420433021640718832999264813674938157273375290592788753133996741859965258034273428657399863159488519434113093863042179261649202584979828347495161391780592433454809420632605178105958049630938532568156789806946629309375790343585791884755866400295470651281289167454617624179556306285775538273640784278475358303871406797294", + "0.3959638698385755489557710011250921602780605301308457595569865098132061251227321128681128349835212212508810246299921462519655630208347321575504292305860152320513799100372630595769065936291506594220617567642210250680560302662459931036815131767702563357378794733903424219866581554015722958062178902473414883933807190920961687912191470152974845756609418554739641361171541363409996648143043979357302190703", + "0.41321813796987028521091431473013916161596830805293649687424341688961507413716621591649879163383882641673238540682782626959358955002216003316726344623613626809950993449214457071292961126188761860214007662067345193545393653191742497646193189677890657992964660139924463087072704096969748995358605459064076775540679952182100013584273877612509536257834358450242426357122974687246428904315337788603554112487", + "0.43032530539651581726649227346608528709372859200683817125277384462849187532000288969537766724897319030479860713591459932866508254904869456423088312945970943686450425589907227275358186473310644458353392107693439475272544181726520566221333846008220008702070460626739342310039148106649726719665728169819714333172605016313499067227953767878741853545763313707499816244740855778447731454065384788859848319503", + "0.44727928217193967651655712666040617006236300257644793444619887007723922383970962870988815495150987337761018019128790177957898245520422485269324604484642139354461290347689315448558082058132330317789105861674569680430563377440355102600184370927625450804550114009478901349833826102470780452480255838220723171955252412104006070322080932915859579006653276371401264439817338080069936810866666557553662506811", + "0.46407403288360522126660904671571257203469668709200603873826642103612288853249598361813813213381052968904786566929537791978751985511297321991996818974870946807510786919602279514706154473236597480481149516597293844121405001964448599792635426082163120478756812832932606227610137817312140031064078333902425335570730565173883252754294319888872518149175050583958244086010074110878967984441526026195572046031", + "0.48070357880154616464768530714893198018226307768872832018696934136162055774617690112915494983829868655926209174893609677823844628976682666861087174925649829592164380174433963170047900751735818142724368678683601091750819984658303806035572915499999180599872513173096429390456178642478189724903758698238722978406369084171804020040246631229610021517925007543961283845124822740019511921386188934760298241688", + "0.49716200000672278683141570737786924159326600032981923078600441023882683095816876734389429898823686013764499093454507915253215528870989821318738227798745591597923864925733083640574132559603114206682739488541451077277291582357627881380008066440685837422009543184722898767087492264154499861112499590934108906196324393034778681622285346845867860458748417916763883649390228287689107774312170267691257606116", + "0.51344343749844216224309565441486087365890516381683759696704839526386373494321578458551193514743669178342420835082611868891019193801223760604220552152028015878259509179672236586872004169442377393342941368136686044214656339879518691219516228434732537186028321245942076903928921929607502848888640267094590400556200402256089794954485061564115688273804254406706725374971267431122825004095102239220991848356", + "0.52954209528009218542956877037980380998240467111773187487177084701668417706002935457309027480414979338624119758863233287969233845786459113619958146654397106933375312089626001011352424174223416515118670901639015699899005014886945323983797633471828049323917701068414699189471811508040323789047713536270617216249222074877291822920747392986535291960399633972613345908694327479738445245500914715996152461985", + "0.54545224242244689926647810432697721723945987179773365856990386707254353534614807468692870318816991084937065603191754270239773531928848863926268254420020634174904439920465735399587679402503040251639815041072160696029528969373711375024524059535996077596844557011786411865071706766713049961515353664484996577751962474564968659755104983468313555304855249829815310291744255989014492588353749587481644931913", + "0.56116821510380861353700162760755101727268623115746212675907859515911800480855365905235006799852352328451502804871577600277181740574994973635138803211912076695967558806493981733454148905054449991651227073996616835900542604367257843601995979944175684600136575098939764120745952964355353589317556067474680987527548079297833539998258342242865222215681747969549869015697939554127499557081626950060916329896", + "0.57668441862626054773920164705882295031880435874490231795930393597704964539534854834250638055542815083463738683146430082379073149079998953871974990605030531115748567904948229002538680465351816034414085890696196467615521969543006224204433997063527288514443404935419253943724579872472854300703798475966107579038880496698051818375532546368197809806544115496171522444187250876233927302975709248591908972346", + "0.59199532940731223634617420193837196766186356068263223313261061480558639436412180991021350240470913092271149633483820904350945127229180169976070379470147429711011056203078210298313829635000565303787641997857930629432231274870246836108452732993007541125359738273485061324228778750531830069944570036169084871305329515261365955383178502917713214334808810726412625844210978481512366368025275438632291862785", + "0.60709549694622869462483067245797028399468956070763942538530335526853282815406226053099893555611232739741099281199863420254333016184720313024881100010161759837083928797224725640021095785125988238992410296927225409984765886863313873892022531648958451940083661715815760806237878803609330649695132473889046508160482887768573723088361332267243452286610176948724186843039692112797106039213976473403724518188", + "0.62197954576434335539696684219824327976988998993669475584026026679831221725774460365328908947620452777457191790806959938899059379387140391128845696987642418506611453321626607869801717870254836897328796165084605948086983949944714226464644755644542238083403302661596239269476252222614109836597348873471190787660391585694078779921390758232910639208518119325492789999941075221166054973249356136808607130253", + "0.6366421773186640485920116318191204083389644098160828009666722635549477083039305904975813615643101060893999315509501318081025137289051787335454356108133761354485193083183997634369795655283340428506642872565827559825155045924936470784378552800563136355526499002558162019410271880717338646318471375684163442601830537613691628498474632262547856029932241457937391840960919415488213025664314613747543749464", + "0.65107817188809080279752785471799265973958362274943758073000075578938519480042543196041314945170036193559782763524413154927612489597355144799562963417455961310886431794132437757357185377007718709790504976900339191552944965308823754898079933186431693664015814010551367365293786806527034958873669211570906132849013497458819941168651227792824572805777219160376304646562062564773441718051418178414899683019", + "0.6652823904315739978766556052897347198651017349760138699519597733553278561013395851136458951983261597283585391502588949649092379467069209284755289821255744166256794329589771465045421874634188329764638118238723545310838064785644468083837991172367935880462068347034222894524074808990476036821633127927532229213401486467496527893691588255513769781016943243185567913995336109327864083859254466073492381187", + "0.67924977641755138662041086036801948989088186294785002709809874961811116536667286127777672928127306388394020078452402417993836722984523906631302047812425809759286220237826357465064765092612104224837992075711035615650942777454297235908308024053950635657488001916036801234116581671119069849133344664024677517075723660642709275823456343659009540444032487248071553674961012055521740306092600444870718199652", + "0.69297535762401272778114932738244728669670875114228232862389083194872888693112134130021641463393969624412179768291914405554577080353247136859984307940401373940521815913274464950964347624918449081645304540343160683388727015489772202472645406318288749244334156857814927405528763108558137488794292057315715995191324964500528600378291562277858608403425720078390497455476055579003286296442406491998525563297", + "0.70645424790855122905182233963742667718470686911515869065744744473731249895412640632516625097411541437953942564566468313798077366853928608154168668667806938130662439220702019172328936889436324187304262248463334787504456805683070026006307765178787997020889111556678907849442591478755800698808480163225125777511828352357189284217101098738405458071150544253514248561787426067001460586251699075230390564367", + "0.71968164894777168289159927814596788937422432901416956306230349431557362414856173295064125294878325237342190029914430775648665560145040598898117000971783978541799092281781000633902779626437866517288284324732827083065703448279654800632624171861777710582293639879819116932680545313562525074940809403693475624332169458744562386580074420532959714281903926902622613852892104465683714186704831143197300465955", + "0.73265285194543608674851404628602868786755398311878599262050209465658337331457767882450516660833910207846986678480603058221329185506983962144302950162737505562091432645466997334653618075359372680522922578429510783107155224742867979206003853893418268095936450823867623873015528453108944563276576646508412198497923383466470895808777876544429706485835161864475122029711660543090876323595451165397047981956", + "0.74536323930873866831066285008063416514858255428941319323031554151661731879818806472410911187787504167842137286019020264008471692607030872105020489874402631524823767448432915438225335869622093354538021006314536198469136634364850042715775621307965524560308901397550829610851125072518884822515926626213581949190024268711827023522012804341871590177804438418738255381261594827085100659777173578154500251787", + "0.75780828629211358196731753685850074775187628883294491833833279769413437275246840580617185041212744084038976069700142887035937511309419495512390089087847775651833369173386038513330257480188204696687136231267595399438343156895032682495327740328291738325217778497473260463740600852973600297913238958828132336080624048815574113414592522918778477418427876829087439774857073733879539765547872800792711360592", + "0.76998356260799010064124325420889481428942836988785464918451704687709959533402569414853910266075223008145347866420469852220997470992987183595134711278161994827010482478666523199914707457365681979989417199177427808129308850228595726632468139527316915481709465938257650120793934685421343443942356060396291075752713480402305699120964704579260218579751719693291565685728074939857101460901984240449471777639", + "0.78188473400392189344901888012886357289691591193533323711550248487573232160560048524966536928562079994581390209192526509899176077393862245482807165569409036943146775931090958041945317489351020506180957959482939768275851398130892970557450783138983566392455270904228057175489097967314871299150832712632639718878702471658606369540854496281803565819545728647765960328269135853132407415684491934581417388002", + "0.79350756380552895006859336306152006552993066088382163294295016384877329185292344719536879395060919553184640006473875955257330264813115929942877156894433233876161573894628944452740080653935089289153173836334040374431360850336851424574668632837338016740333716530963434291489645017931035529052587483629111178971917421121398732580060101294617212337648611654041575132820234403350225337355214099696493406567", + "0.80484791442470288298134387731514331459831415420391927496917008531718727007136925375073869996549995938671025493755987802316807560672754205522916341547950527416285009447065632296220924964603370109747266700136618832767813938243784759073035555035361911772169687111972294262096081393656654067512785827139608367560009298721819281091010743363153063005841441400130721362346287552727162527118465104052539630019", + "0.81590174883253870457705586780548750833668862852238889952372206236774966573191832400412494946116015154305873210759963247859431688393192829248700535837612167242633896627292821666890819736549652534738107012873094812825219601489880060491958385552979476621004236099490018887651186347086675381603801017940808290855340870383683075409122477045713172106217670870448929077822708030574128623585863036730829850118", + }}; + + max_err = 0; + for(unsigned k = 0; k < small_data.size(); k++) + { + static const T euler_gamma = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + T val = sin((euler_gamma + k) / 53); + T e = relative_error(val, T(small_data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = sin(-(euler_gamma + k) / 53); + e = relative_error(val, T(-T(small_data[k]))); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); + + + // + // Test with some exact binary values as input - this tests our code + // rather than the test data: + // + static const boost::array, 9> exact_data = + {{ + {{ 0.5, static_cast("0.479425538604203000273287935215571388081803367940600675188616613125535000287814832209631274684348269086132091084505717418") }}, + {{ 0.25, static_cast("0.247403959254522929596848704849389195893390980386965810676544830494398136043486821690984848527973792338327197752176516138") }}, + {{0.75, static_cast("0.681638760023334166733241952779893935338382394659229909213625262151100388887003782753145274849781911981438190343146876189") }}, + {{std::ldexp(1.0, -20), static_cast("9.53674316406105439710335272649306549801506698739838753888815787489707114648106832493113326022411646219016312547902694921e-7") }}, + {{ 2, static_cast("0.909297426825681695396019865911744842702254971447890268378973011530967301540783544620126688924959380309967896742399486261") }}, + {{ 5, static_cast("-0.958924274663138468893154406155993973352461543964601778131672454235102558086559603076995955429532866596530638461663378937") }}, + {{ 10, static_cast("-0.544021110889369813404747661851377281683643012916223891574184012616757209640493425707075673894983216158293824238262832286") }}, + {{ 0, 0 }}, + {{ static_cast("1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404325664115332354692230477529111586267970406424055872514205135096926055277982231147447746519098221440548783296672306423782411689339158263560095457282428346173017430522716332410669680363012457064"), 1 }} + }}; + max_err = 0; + for(unsigned k = 0; k < exact_data.size(); k++) + { + T val = sin(exact_data[k][0]); + T e = relative_error(val, exact_data[k][1]); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_sinh.cpp b/test/test_sinh.cpp new file mode 100644 index 00000000..2c45eefb --- /dev/null +++ b/test/test_sinh.cpp @@ -0,0 +1,237 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "0.33937643772780730649735035088117439284797964277099188367427256402032493952288848579083622213428182842627923924487560393743204013166230906610274533504451302298480596207257724471359936027198954417317381228420986152562253196896619001418292769103034561794393400788635610424360775622370491149170501475453034747306600304507650361914904138327962144190354572359428689767990353722392457982930942617983634601752", + "5.9746833446871871874685235810964396457491766537010251792063372398172074828151074989468673672535421045923659313715467371148678693662985453590831122722616951299822923837410906027605763677066945998696776562438704017846907508677186762421899376364636371743116519071733413775650991880222096045615827530741679305666041641331859757012015389431793705875600863391408448065773828563483223117178640044499399723744", + "383.32826140718915582837967448860824902040431804683461630967288341613741467095168380744762629948507973653220772087887989292128183196493611623766470283358542341824134250511562240487252437079958429586344329111208041197054162309164204144237855212391474938076935722386012246677813568519769393617755607372817372398764101401294149353978426057544810680225593132066193858006901125069663362991172745649465725272", + "180470.88334757918167934673473709881208559849920820465419382707969109187448281704429118605409224039018180517847684905660962429505828088398660499158213746722168139372781263849989865384042531846290813274318773753295025006473736660333640052386121946183935053629928496714560749082485275242374067168149435272169334475060524974384307351757201698786200303374802146857634893509516262245925287553380389076772488", + "6.2781497954189513207977998975338639259302378413658035459603622432839117790845430762753614618299222131433987986511235061633658516824123179660244932375967566163895461895213509376427850290780942550513918615228886566287592461085762554208269169000672149592375451149457664991726947185145469263932975075681560662428417041932848357447220175607720561540370653825438750168143857523868718856189519864027430308779e8", + "1.6137831147508521132232267071463247985636947830692243664921522457394294988129666666745854084767325882717254318322908201512400243137564101564235450151960593110176457803621675408660678871179456625850704076654060872094257085919134755925910859520026379969099492921728083639989029675808598278170215911879751320574053132699172028082102336989338403081942130794464992491330850160862146024982135931859868176809e13", + "3.065121004865094886953119667134247741359538615435533822684602797608029400610449009335078883525336625519599034934744634528257351124420564267197918749480389135525897886434344884370577475363556341414615470556433033106705280531443046669163916446454890662947185057748542735928453570069226294801221403438864013368364219717148075652123561545773399076318560221173734215703610924057158101731263882232550297741e18", + "4.3016893602106215864771434464025735547192956887049374680649926707919814241961779812200280749930256501997849507695395125441756421661413154730888574483309057229943886742437071251707738990393977398403536175642762242808350076543018009682725019125106175929448866428526984370017465117236484653179596869643117790492866002064306593104169410537341890174831622159415936125041593936992634719906123727028419057537e24", + "4.4608685929681360001024935791890661655506049487122331222491789265929503651540405036031990380918459104583255735620288691363060079360758406339887417913286769718423759522832754263499878135869223253358698774066131403822428286318351390574838877307934317251880890827523325360658275060099119902102399714992704146743744108968362755624325107486994088414126705458507082103811086372240878942983212662081104875997e31", + "3.4181315955816806472569357441100390029536003312981931954091744304974491527743599822230006760631204302243855667216955365986192324833652299336285826148922073950348547795494738267861098328516497599288314822606511466743212319770180141969147554023326883651348621187276823849839283609071336923316655316828855943689100621619083822127788284160652232283630351386798636794979234576432977468152969056493038423561e39", + "1.9352946282727908101414530212785249763640776919052480158881659190625166733449770912626442628329346416132299268886589920690636914906717492301836773331460154604580407945460359957380672599434023197425489039882987443681919056322268437224184910074985583829184831034293865504101338027818555871946080687710035062238789949143319550108801094190098446234092310048150477274502060870736716324117412815209633124145e48", + "8.0964449511890098565841496436016431651692307764702784234901741408135381374668439020986470675941110923614446905696410406066640351065195237123718468440597743167713019447544827353458477844468727834630038609140168354634397475741840053079910210908251252223665806813131724262334693137656218010287981601097259534068903471812189212459231851835393208367369054618963204727992168556204168791513644815218096463093e57", + "2.5028257092625174549175008952222569141816383637904981644379473858250736896174216539673733521627607209322019413420937570273676341726636306931304501320694017061891400181233108050930610234076339285157392030024769366663118692571469493256243952018705693924919037621083041696227375589264811876761430035546270312014570431860268644276406457398485042029556392894799022733858611415899182421526634018060028309384e68", + "5.7168370213792649967466315312864179662895170192695050789061362839510836418124645968032989149068311018994324517420345278843446068634292140996241291031113395887824145000873531937856827299256489358571593850210528248202703396455363364446996158929674989959483681393263782486430231288067231095140919741928337466492665857902913114664767450432510739209971738097074002526312039248809036478310948111740897528204e79", + "9.6487261169670031207955841899729386502708125098394777808615183927342163909284025992243201020435915122698808649711566042372911206942311277943247994427354130507790526857797833309691667375441761513692598664419973302444660838882173718713387158013802112502169254860961105745895124415352002289485483908952674562396552790441656755711709645516914188860464353624992313010889765422981069429049436524222321550149e91", + "1.2032977660238608232537005158851668311089986235965463249220377778638489972355974848209035082333822309902237165042868213438627625544096344578102199846440476859557339736747791529782018329078191477783605471526120462726353510147373798347292650122930289404816748193194907382572774906323766342758092979989633448828636445074016110331338699464788279882402189027828261039788079556739180915346692779065476431369e105", + "1.1088306081278288754492401130897590262404571813281460605683836139669281218442501421935533170636990866165181664561596333701204545493730707210930818738817252706131805203538144119244917164949716209095542194899833868499263375700313934257155600824601418042452138211549248837967344874095248283887929145923103153332810091693393888809653081365270947112297406471162377655179657693898463736926911943490619163092e119", + "7.5499880591625965663868042832675300901799245732418501707646792135512053284835138294796976048691668315442427834949618514094329533376442442492757936744857569785450769927581802961191319878260712808001736830227501518832554201816224207300614310712430470538022948957433004823102746037654096845266998518623332118892916505020627868405618942429551700207476696585635930562973459491424179233918050890206232214765e133", + "3.798536358006797624025033016530070695826982685154937173246022092345982280900791849578041210970037835270398289956157015064696375146357207576854029748413680946201805214954504282866534528711715039215051307866373994662368105368505465037259587291440042344663580680646178313958620437868058550744621854406871361710599007951099013146571208384054250556080476992977623024059268095813712424244902009427293468485e149", + "1.4121319341572581270215359848706630542776633675711529687593487346259283960708095601494823112486631023721124235640943167173029348028743563902367757599140008654691320430919753414890689949599421028277624880392344132646738394546195638261279687543208503932172926275294218429086816560213399180179494004109164546844899632385177835442946174653663068675983237955855108059376913611877439522917217336109804190399e166", + "3.8790307719997974510664339744260233373881096199933152202662556556779783775106563986911859526413282055258612522499767709123313205863879946518297779104337686883587019222829967005608205535314284003183828513113021722123872387036435113517356676447376715595408179555267871947671679098986651665719279348025058713817796876795915844151719103197410787508530261619841035613531487094949084263218956635085585632719e183", + "7.8733605373835840397434523264038598405672829925651165847065668324385430746087633348848905637835428739401439679896923081980364912472282573695612463537585283007941057172128277340402716645674443632827653710173742423648839359547777694778576675604645880219833375227941998426325886558435214355022240854563558864080627758653439429917072753785194675103766900514602432580639079224631229479607396935864512990879e201", + "1.1808262995038900942517891457926200063018079695348469762725520377876370005771518954251015338402886097689762895044056273430051256244413916763438966705458118354189107806216991150264176024521937328179762640422127608560103802431672144866013216405157197709788484197720057702118788168789816074560208078260433548283881535909071116553897893659656781376448427981358955547508806938614921874867135186509274509121e221", + "1.3085817499987842655130548827168955655838432140245228169691892267707778790498773914833199368916114043966197329562444577848635313938483757629541576533880917215885485474416704968999200090496252044959849927443732134176975867869986011315975625868009065373046224716063168977788103866885720471095547385342868632018951910603936835789387464412366605713487321530237148912677199033012777178113821791621549557963e241", + "1.0715308148006899161903881353829644069217121138682658034413051575604561649576261428568888094218620444635013220705511245290719605273316790249367622122178650529000528086055415007045458486410501636380119413632657994999412652188430063128470336817401482172580366374079331295129200936246446347832380606353293858222758687479612927181530236387227215663399410099251455256898414199913458340065553949424990477448e262", + "6.483319651006309502237640505955012384293570932602353784849377890534620180296272226076424490097577093511886503973590409376477611667988893542117173598716788837179265384921201772013611631892729250835822804494742316330406688475091973437669111728949960922002370308207819760146543720499389938855072810566961589413895110830251224194598788696990065693705615156654866578134664648091752361824241438921952031149e283", + "2.8985391304542768293172709775230767981477721528885408305355619530690119426207269563049756824939397157221877775531212262059946098575425050827283362457005503261796116156917077778477251551070762614233325253060283603452216492681531839154649232080928787066338399915850327381614672456102374248950210248266796072457623370079195574322846594267768883120374288952014885152055438195794090975578878933873824774214e306", + "9.57524433627083921372674145950563946532138741951042299439035158875449060589509856903496678820625880407684156184675763001790613289835869844325821965070261880894138207436003366195024403902162467929095155787852409710735775347490909311196315332711680552044467458169615366116872469435840608534489425322247278926672059747911266981024366989976214521515026692183039600169984107883592297128416659318858313127e329", + "2.3372734503362369375381009524197350830316472034721759761797536237738670471009423543542251572488229045699598160834162677357730620072441755506075897500940629883044875771104686291523502165266242030847074909362622098365719455332359938746138629161304717385265309980898079489959955157644566232440805137701071311495653330606071611331941246434767948905863368638163788562679785940566685500460815077065003612487e354", + "4.2155879126937199240969909448599186868484717887298729605150033299123534992857332918168135230843738695925698383815575417820480732378749635394939513838137876524333991937836847074991505476867647762082587225838063325020413513077128321581439429001485977751765798011101092072613053687422983352140468569171564773941232256057064161142341661775359191159220450305300322654184921617310753474842253496677498824723e379", + "5.6181811613375701248970224378256740494692066242437602652469740512738297599235414593999616891945156186827736326184687322137498447792007445397397290336810468925670064733464757082986791232916898141597610692740388799796632396708149027243436859752526805112778790645096555770227809873695589969805678601106157556386974221647669590827712353133603091803570183764883405340587430017053183637835511899658145649708e405", + "5.532511069282205350923830187073466127274584467195468607886763750877294392993663821432158885753563495238131394373865428654052604326264330104646257659760161386620716716703631608643312613245804625511813964275109451513736558514977338129201153666764317441936156609643185133981728847167450887861106642311329612564652645663234240748195490808151911497393974690166034839217817023634217121406163178148652748479e432", + "4.0256666306761331240653217136731531623017017695713942917027851762705346357330788586411431378972009980532310757689380174461664677676028378924382554201434975574729861177781849023768222381429947872325368088023224591306630434887529215459580760863075907686248521168590309636468448648513752893851767315693469638980874648457114335557202115472595647478331668869318302753802858726588719006447471192697846325955e460", + "2.1644237346681663424601781769159797919834245365230735589058796985974745594485988855971413936820871935714602237643458356241187573307428309041919648027960168541647193436225977495680484218384107820095589356463058222584008532497069179993678533431131233629312850771528970443634604290143149079209513868130585713006080733488491160321145735562062411305931183571279530201672366980412430529846635995189699318073e489", + "8.5987580981195983662047247216936066485731760315371506386077056691409579856014763032619539539935299716110411688793466397984311640631361934500807639285587334983206556915704635831992012926186843826981296831658998834850783404713050829093753126189556625095994621605300047199962332098857236359801681157419606676412198783092816364336047306243999363335004760439115355072350465422891365411868472688286678516314e518", + "2.5241673163187127276134610716954724162270290228773641734420864618245211926017624829840685860130579257772126398622324109858115624706486522844752512951837805396709793171502497523431473021570806024043139443284538862368635312799539108264084028032731295487282188616820261689634926427135060887942797635147693849950058672753458576476491733064455826768562371858057444914175251596852571637211466017938478085247e549", + "5.475067911823387661325942057081957044927796274441278042805014835144678321092623034147031518807063234976073102574257079170283458172046752719724152941316842521196069804425876507927418423409523739261726681120662097159943049401039490818332686968135012747332468921142470970507219403290422458185430415836291605355383658657658638112408092789126678938878667507151950931633694006471359998448912249374833586727e580", + "8.7750549689950256776639468724574158629603320014390275681028674550826357080136422399476213432791376656222763800628593282303459051561266270006921840049305819767639184391149913915312831894296821356222752594264134130151457242713539248421883837353442181724530706933220158507240760325182068001553294949268596178418634164323874971937997072367419479635154591248667559627811893588163238012665671798461211917208e612", + "1.0392000158337773273751156576416024664653679689973856373456304843339302977923254238376497044027728158058903302390909588333829463843362779584402914847447592731182614369968957680281500946805571235013941407979569788567794900810257154433592958167545186687137810101848000107335074486050959387974516414654638879740966175786016492797845169374594168995878543584318334800124941205910589727264397237600733483158e646", + "9.0936326753636727240574546678839170665019169110943878894933093211555976995701468041449327370073681898690638466136204694745206283652338526673125958055131610409923286526192661778126811265116493171283319361595267283588121098349703951929669281966675596890266483864217591555707552765565756842701056144290075867893520379419521775913047964393758374891516340929062076304350159966063972713118995033247759001609e679", + "5.8798281636930489964162009429009257867906792508058801627042121953599912951265315933723440185825519080102988056836911095299854840387008575164090793635997912930561430335216151607097220208013034399895832350235280120270626904356196935166701773768680311063264380891331021514518757839220818506905997847228783439015252768055166165941582030353226255576433910936297965207260585437762430381969160714956727596198e714", + "2.8091881292911108404345975896815558958477835260737794579417284512413473388968057587088555041266297486841923628702282019643659456724373332519583025947015025975126598748630623031951723754960589046233996595466021913942587558326660593063197905288573353559106884645285531497626940379800500474282446929237914568534665868703742731713632349090897884403966643055728471509474896855575286123275564417626861566706e750", + "9.917129372597671132067673866739246238179742417231064062960232866725337575281938597212073697168000155027158148165861617400080837699968785505107579831803685516054837447325150388867488754170677228096524224392410232206238263933144338637103531441623303187445874039234973380151391274490746625993568552049954630793219419614845431626975962881182662815760423226111647056071831411664335144052772436215105801395e786", + "2.5869027163543111121878679987081647715187872826677398475096738640583659800068967379551376322170347537454918190603891312949716382621902484616361664158953484778255247083652726854621059785392022847887382779010079407502679229021085320675903109573769331277413372272363218896397965662581357886739691376204316908974081821980432178065394228926767529685562155837452626029223937027004015040825450642409597700449e824", + "4.9861251931207080923785686798881789193813879610842675205361210155894774686328710893906543682447029206928934967525495260314937837003448878215156341411477636831113484416124080974502217578408248150338565305116223944900839866528622960352723938548713319425798453345402992146078868053263606234074443024155243450623634720912438841022969909473424559262711669905282193529250216454066716533180418518228387188393e862", + "7.1012569014339068241101751233953234216522840280342406520909288232012799547871960723719836516359548198842749536961644100550279020276709043358260853581760590386456213180291689322352732545965831405519844109680619067101311180959399339922706596098526969148981173519865139508665631317310424178378833370605922449094745510812618563813537347841030916512147874232760564378443782164868016244561788356251308121716e901", + "7.4730215360486642135431754747074885377840195683583018254892502245011973712084221116813364423492802080799768174534590613188275471080608467087354983850284805514875889145266688973752185071777341375422809910165581997555433091939959406569831183459872344778707098094941193489061532160249775856426569696127193453339548371679229676272663084782830276508737129506676031759345288056484158647796152349867328841634e941", + "5.8109375364209112227579654658730977030869454388607076903639465992296616832002964138000947668837140543325908222688655359602408511410663722770167244801973012245657865182739637159804595049180263175014778215232564251739259624759589953677661356104554831551073263668188283861123521688445132164147762321111597028523130093864153999974376790494383016372210442340324038686843345053322425194077414241243050491297e982", + "3.33875955701899627718146291382268063073604182131575843695486667154496711979350813988644889979275310892951143249901398447859083674739840084454465850475774696325142148671937407108540250845900941142800157345665761403930889797424808979569550325271558518404559007551625637761142662107757913763221912282957681784053564387104062317729788737215450574233690655931888608424916152893688106181220341997128198692e1024", + "1.4174672877823334709610117319768830739080734407353905145632612088824955720198734996604261250019291955883620333545750761619015467840567122066622229379056280064206319780047687015558007624774062399477328822231085767309831266032616053065858739373818651687128093335640388513396191118537181280334430292439188737524362269789272308905723812818882228503013875816702686587035844437102478263525616196832018321602e1067", + "4.4466189016791091516801723880812533528438597080549410911235655611382010503145789286158745555771483577943662768773465284793798720178177605712848440200402906836390133865748188969184005230383247111166918721449908133920663776952786683837038180436264738937354101153867171804315769471050303182129269442292354388037298125177941217926845803005587166270803697433886463469168814941555804311717400657004050157245e1110", + }}; + + T eg = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + const T x = eg + k; + T val = boost::multiprecision::sinh(x * x); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + val = boost::multiprecision::sinh(-x * x); + e = relative_error(val, T(-T(data[k]))); + err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + + boost::array small_values = + {{ + "8.223167319358299807036616344469138485821440027829633696917375433348917938654659351596020080036406671343718039863220496616e-01", + "2.526123168081683079141251505420579055197542874276608074880949653019810769068593790606537020961198741487692473633089323967e-01", + "8.342981744595282037256218647969712476322487890550784823763249893556153270975172951404094950587944959561849750490537201329e-02", + "2.778135016068299789938671680845480653984976507019542653788637161116587306168290886761259072846829249121589698206609261524e-02", + "9.259391565199916442789400306996794489540862711193761818262415211084389468754315525525896238827358889826875006042447587516e-03", + "3.086424653287772358219607529932097884435043040527155440187640095572710676452654803730003577747633690318001961509535020849e-03", + "1.028806765851002064810061084014826478832745077469708149635730407866217436751337520417458090265791086156438275231514030381e-03", + "3.429355348425226988441198390119109217716503769838753365112550442738406326637684639052252898314646892490045395290022292013e-04", + "1.143118429558603374406653541544292690548937361618336125287018361332072426474632105217297150810234138626767253281422813482e-04", + "3.810394757818873406266877296641684693312194735341898368873067089928172619067423751257049691985638480762032673977695116880e-05", + "1.270131585666421832817527834137477593266387525701388601975733237436369505733715799310429349744168792375082834509467436523e-05", + "4.233771952120219947940459634636576539101577724347428305072378100562649548884420218224692461748739725090626754420296122389e-06", + "1.411257317369659013704209000288436132710449162963127340562961271337242582661013580874165903770246169179192268836124421074e-06", + "4.704191057897475365825409916786898392364235667906752767514580467152163619657508910797742266406961516358439252434955007668e-07", + "1.568063685965773714045928492719360014894368531987759414833778466374819836545157375950693756664550256136222396871173634254e-07", + "5.226878953219226673524993193392503058475862017726848548717100658392470633650387274004511940515056405069137033934323251644e-08", + "1.742292984406408185991240874995689487745140228031202510923711784729440494088066989430128101759261047316736074663327672115e-08", + "5.807643281354693692124967044009687283114597355717062156493618245876910131607338183944830908381903728560328284173507220743e-09", + "1.935881093784897887701686451485601671131342930785061493703969418728524594573922282309665275558709040519461560600768780392e-09", + "6.452936979282992955422916851920785543106383715381924626175995859924351552325880931187614903984801793287071578640505194508e-10", + "2.150978993094330985008279519046512957825521218238790792201835497215534851989750722105234826300738623838446309250309905466e-10", + "7.169929976981103283311786261663531258230547972690500493476881079295129579131280734024784107219045379345460886663104148486e-11", + "2.389976658993701094435441884684454421835327948893136184573938864819002944442339456827931472237274353903634036758669394620e-11", + "7.966588863312336981450798799860506345287566898810744342680146925029151178981033890759916168189916177504592939240995619757e-12", + "2.655529621104112327150241298135440075805848488054800577703768668100658036999584228451100239039042920681377381394421710121e-12", + "8.851765403680374423834128412864530361591097252230621965426275532533242581680245794741067906285298655116802944992368126680e-13", + "2.950588467893458141278042461784956914687338675140497707333871358819185395356569206661450997145748756956497959702280685427e-13", + "9.835294892978193804260141412430145318398649753331401112621871794012928366988233744354238387090649589382104704221708773516e-14", + "3.278431630992731268086713799445120869198593899364655036314007566906378666339665297288092596796135684816883503781385164489e-14", + "1.092810543664243756028904599641030626636532928735904320784337625844108091213506619051042206148385975354700234586478575025e-14", + "3.642701812214145853429681998738987398752764686754626492252324567456938623579239392678142797020213493844816454129960310753e-15", + "1.214233937404715284476560666243942169089106312534317920490462975351305354471020532764015606315872085933262687299655265697e-15", + "4.047446458015717614921868887478923169619805517194433471908835726595116905187672132801369948377551282604828733616045843751e-16", + "1.349148819338572538307289629159608313551890152969010184597042496758528297346351553643241208769191557898925543369605617734e-16", + "4.497162731128575127690965430532015584807024576774799020494128293451281927637267192489558050090835454302448780391749096414e-17", + "1.499054243709525042563655143510671412452985626833998379862387948592418229228808284088934491020852037924756758483008288052e-17", + "4.996847479031750141878850478368904541825005460277179305602161748681654262243578435201096986093377131577325573917436618470e-18", + "1.665615826343916713959616826122968174447164290616980189746184851537351248309665330601503343215376981550822569162631313560e-18", + "5.552052754479722379865389420409893912541965834349657578615232567585047309856390957625702896178052275806406957076143469634e-19", + "1.850684251493240793288463140136631304096139902769381795814754672989850701401641374814254071564872119933498619234778448524e-19", + "6.168947504977469310961543800455437680289164351695283493312025632359317744715643192414807145394613572397590534364339391526e-20", + "2.056315834992489770320514600151812560095228784236601072113743484455321300338926430301421880927367590178440922006775473367e-20", + "6.854386116641632567735048667172708533650333231531203539518552950777817440179277823487619201513258000884052637516041835420e-21", + "2.284795372213877522578349555724236177883428507451482660054557452824460619777642844796449091646418601791047308814504431261e-21", + "7.615984574046258408594498519080787259611422468149787192854095139994568043598766360557598146279482678180281335390895949036e-22", + "2.538661524682086136198166173026929086537140604567639372655275057673980680372673609490963070062819520295998328327889923353e-22", + "8.462205082273620453993887243423096955123801934429554813185698344472203995997708879527322555715697860578416576045982358004e-23", + "2.820735027424540151331295747807698985041267308484077168753311108116374235508697904826049959781116012127075951788533527897e-23", + "9.402450091415133837770985826025663283470891027171945709804152456669015193736201020401750153196590359525341207466344738924e-24", + "3.134150030471711279256995275341887761156963675682933328476437810109959425395050019306074135780459168092270327572635795510e-24", + }}; + + max_err = 0; + T v = 0.75; + for(unsigned k = 0; k < small_values.size(); ++k) + { + T val = boost::multiprecision::sinh(v); + T e = relative_error(val, T(small_values[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = boost::multiprecision::sinh(-v); + e = relative_error(val, T(-T(small_values[k]))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + v /= 3; + } + + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 2000); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_sqrt.cpp b/test/test_sqrt.cpp new file mode 100644 index 00000000..2ab95f28 --- /dev/null +++ b/test/test_sqrt.cpp @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + static const boost::array data = + {{ + "0", + "1.77245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362428257066623615286572442260252509370960278706846203769865310512284992517302895082622893209537926796280017463901535147972051670019018523401858544697449491264031392177552590621640541933250090639840761373347747515343366798978936585183640879545116516173876005906739343179133280985484624818490205465485219561325156164746751504273876105610799612710721006037204448367236529661370809432349883166842421384570960912042042778577806869476657000521830568512541339663694465418151071669388332194292935706226886522442054214994804992075648639887483850593064021821402928581123306497894520362114907896228738940324597819851313487126651250629326004465638210967502681249693059542046156076195221739152507020779275809905433290066222306761446966124818874306997883520506146444385418530797357425717918563595974995995226384924220388910396640644729397284134504300214056423343303926175613417633632001703765416347632066927654181283576249032690450848532013419243598973087119379948293873011126256165881888478597787596376136", + "2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659583837805726611600997266520387964486632361812673618095785565596614793191343548045812373113732780431301993880264715023446550489842580232941386277966868361303367582384418115607849009560004137515027529165146122584386186492069906092666409118801573969725237770253874824784863348864259750658951309573876342725192688040202857185924973630809978452538550099964101929825864558813716963467480152897452330473583474775619896089188931497718648548480469365216002979523919601823809165790411297975297712884880166754700558630196824142164233836361751921305615135984170982837036342343558097687424487526178010922324284883919536725153974582825630336511862808790203551930088145604026487771415650048376723275094136806424717481635184471307383168191953698843723340165605500555063029823385865249561125896634362311039438867484401970215424844692673432572876116452243380115662703163531763018031226825617668891776095502388960424467990521700581770868994182958846287294933254842394882655811767896697230383860684402997328870793925904767307522570843", + "3.06998012383946546543865487466779458212212931325292345360920786339428774168895114940961908166467541760759370742449261902703454294050994162164179758776674921695210543321431976582792749695268039936031183310664759907107096641183589015949857072626264281130269822115622663836956231385381805315027562932655928781117811850728886383553772535550181070778545447895443834405205758132853217474114166659516983365541988620856642054467498643554872029717170398214071471942791253118514487638811304670059307541182798357443181785843119089299569008318867284816553359946310778010700675312493633986577498099096587006610844378385188518085716548910095121883158502955712612589941408660542373794977570528185247073824741671612893506514342410201362222059007498227945177352958046758148141756202994673600560820713848287574799339070054752116909136251765469324207685490757710781971553227808407026035595494277776874273936176792674139758867775825077183338566625556426910971465911191049352588901212917090887839548860059100937478465817844825147395110789153650851340493729565322385491250242078198566481445683133486898404370694024388072677", + "3.54490770181103205459633496668229036559509891224477425642761557970582256918206436274990131347708933083245364724856514133247230573144884520505018741920557413692407539730621024569985034605790165245786419075853592560034927803070295944103340038037046803717089394898982528062784355105181243281083866500181279681522746695495030686733597957873170367281759090233032347752011813478686358266561970969249636980410930970439122650312329493503008547752211221599225421442012074408896734473059322741618864699766333684842769141921824084085557155613738953314001043661137025082679327388930836302143338776664388585871412453773044884108429989609984151297279774967701186128043642805857162246612995789040724229815792457477880649195639702626974253302501258652008931276421935005362499386119084092312152390443478305014041558551619810866580132444613522893932249637748613995767041012292888770837061594714851435837127191949991990452769848440777820793281289458794568269008600428112846686607852351226835267264003407530832695264133855308362567152498065380901697064026838487197946174238759896587746022252512331763776957195575192752273", + "3.96332729760601101334502876512018303152235975639619479270725806219673871802657165722877418785963403123274056479329535362288655768235647487599476465537517349983459959396942125116402730874711739662452418728544662333652033991382097872017643021546533893998444782653493302314148486254376557154660429700133894837513481248619445021033294987995072089685196890751303705448870314051631971912137432499217943513505107459328579034234471969034380444279483175756904340168935694146646969758408612915912693951504143726276325727089094957428376128777490747011483653095038326498799910297470352498638922548951534285262912166233490129232297588127154122989932582549543207430381783967345221251717788180706706197608063733887726205509696294918128904282730298886608490931339746624769514837195042182809390984886538469878790432756760740967852006981627342718373868089930899834470763073879097175124340898791818850834951894187606842759251386865815997713188572196024482151907891258713869124247005410786490332294268446455782911914942752568277824622418634516620092362780994044583559067632108995042187023154200764184950878131638370936876", + "4.34160752734960595617808776374477460723265336870727556185727396662220923171777437150069768940869308257867815441035461967651472282081172615279256504443662226606580627885152042042903335792297058916252842051925089290836831715454034263505813680769125291515266958692652530407528011558306762163905143207811598688431871170088962518292286615299738096190444738533203161905492043851016820053962091086343470680514156330656554108208679889001485483033545415301817702473378043508312559202170115728182897990337699623761986171416615021158179762123766012269021534563660979972864906653441725316241881374716900480598276640840394699718984639649897058274667150152948516142801074260038108590401332448730361188129358652703927446859710621067457990618378017703891730724396666299819790072397688972686459430503026856861736069218065420528347106866972580915029753621255304587561985717307629932540410639210302482882847873727015801634901755832519840544096758977294231047035556754992897011888753217953080197537610448726652746992121685068257440261763964980703424121083058605934982281210054435774069392790646709404966217005552197344493", + "4.68947209983475140722248849561783002846415813208241069816339837584532567997445983205028355189765592648498726557587869684603896433394456735512692292415879610033794342501630732934996209978740746985164578019897211786300244708711916089199260058311084265831293902281791295846169702839730909351250374703986364508165540235333505281067384239291594323539816814423865582516577000094943855922812941268841597446572000848645702560088494072507948045804364964153467630734509663721026050762887316466331441449595084971862668493255933265611225629677595775797966272446890047531313544059153687362017301654537115283160575298256857111770084802622759507512748413868494678293024737576577634559012937002405564693237564782661478500575417457048864770102766387138956802222948987452086048547098754786648793023622941962569186040944009281487954082049335826413270469685003200962898734900372045181956983558503256265211391593721293841419380653006415407706145131700572194167555007645631927616801157793244790467083152103173240943823769137606544644820547634530641496507929783339735192083140914072272339899107017006649210880028740845785609", + "5.01325654926200100483153056962209050601397348121987663325984715268458730921568394989319167675611453223201994533040775928973264723625347236191571131193229586382687096091624746227465560862603987760529430046893100979685160465882772555933736722606735164768836231215698019120008275030055058330292245168772372984139812185332818237603147939450475540507749649569726697728519501317902619147752685450385376080405714371849947261619956905077100199928203859651729117627433926934960305794904660947166949551239792178377862995437297096960938730432005959047839203647618331580822595950595425769760333509401117260393648284328467672723503842611230271968341965674072684687116195374848975052356021844648569767839073450307949165651260673023725617580407103860176291208052975542831300096753446550188273612849434963270368942614766336383907397687446680331211001110126059646771730499122251793268724622078877734968803940430849689385346865145752232904486760231325406327063526036062453651235337783552191004777920848935981043401163541737988365917692574589866509684789765311623535793394460767721368805994657741587851809534615045141685", + "5.31736155271654808189450245002343554839264836836716138464142336955873385377309654412485197021563399624868047087284771199870845859717326780757528112880836120538611309595931536854977551908685247868679628613780388840052391704605443916155010057055570205575634092348473792094176532657771864921625799750271919522284120043242546030100396936809755550922638635349548521628017720218029537399842956453874455470616396455658683975468494240254512821628316832398838132163018111613345101709588984112428297049649500527264153712882736126128335733420608429971001565491705537624018991083396254453215008164996582878807118680659567326162644984414976226945919662451551779192065464208785743369919493683561086344723688686216820973793459553940461379953751887978013396914632902508043749079178626138468228585665217457521062337827429716299870198666920284340898374456622920993650561518439333156255592392072277153755690787924987985679154772661166731189921934188191852403512900642169270029911778526840252900896005111296249042896200782962543850728747098071352545596040257730796919261358139844881619033378768497645665435793362789128409", + "5.60499121639792869931128243386880089385432377521078326495835339365228337765188797433638433752458537394171467057445629904555420755398315175666449466777454516186127276489666213119783783503829250827797595051437870440938931280680358959301715436419833364761665112542860561623096658225538557287000997305661352632293104827706037023135997795899396723258283708659284220534304000728311717413345472853792896822724499122866947121737000944102509490771269197783584170349935127887498647119562411695900883847124507613781432804229894058444676290534036738474342530360927632101836180145945813951643250885687876144098262191352431818136969137533863587873139725102593606754797723773610593636883665209271759639631465381618953021812982067002849796433240989364353192362974216155114226322430340671719312492223369487631048057665757861195096925695551107847621963544401115555199917577802008717751423237289036673475431186363543556380872803928482717387196307480474684969943012499128760245113496312609854517190311704797289830560651678579059756085781560282375298034806741180400732788584921019507521738918616603376508365622727087150932", + "5.87856438167412823505442087789707097199843492103867437517314210715732455817816855246687780176492612349299503748836474526021467611461493586217913925495851405816296682706960791383913340375739628111898270614813266755200083564799407766788027485532332352024027224698199060815938197172865670956402289304658624389748945536687871488565787601288863899811544146566179125054361345491299666333144296548463580152591320203647485383402648565396566035890953872530543987300700877916661520962595410666627445873003711787722452859856569260494472375128936533790154715039734447084354515787738062350432618897439009684320850395595213875985248081961123885179420668160222435104348738172793787396737481265016580386986993101160673821650068377182350730255005754757604683510524357896861879706617761317908260663342673848298530050583191985919675390877532981022238129601627016291632330926779809631293070560375804444455958596407594955858475081851191996245268822870776361657887467004531332263395611291120089229481068789229695018187723686024313640325575962035428327239557079268995825494033666401736558372076816062703768818475224366442780", + "6.13996024767893093087730974933558916424425862650584690721841572678857548337790229881923816332935083521518741484898523805406908588101988324328359517553349843390421086642863953165585499390536079872062366621329519814214193282367178031899714145252528562260539644231245327673912462770763610630055125865311857562235623701457772767107545071100362141557090895790887668810411516265706434948228333319033966731083977241713284108934997287109744059434340796428142943885582506237028975277622609340118615082365596714886363571686238178599138016637734569633106719892621556021401350624987267973154996198193174013221688756770377036171433097820190243766317005911425225179882817321084747589955141056370494147649483343225787013028684820402724444118014996455890354705916093516296283512405989347201121641427696575149598678140109504233818272503530938648415370981515421563943106455616814052071190988555553748547872353585348279517735551650154366677133251112853821942931822382098705177802425834181775679097720118201874956931635689650294790221578307301702680987459130644770982500484156397132962891366266973796808741388048776145354", + "6.39067324283344282612593456066836977441869915362953508565729525367923342752058036792717988019560288813706968456779323116609349360225813396901702110619796078057334552019514797946669652098699860634363540091309264934180808145340898043417996593792792270890934539784162252743214627553825160296688912049057995757459733133778428381528832147374042143201083422723391419017423476330077549613969668943960552183346770788992856348755201584958184758568943497685412776464637452851023132948222137176500877587016169499594616364239121570837276604948806785595382545249190023683014214186698190428219840682236280784558646634466507658233281348215201532077497422563499058676631131322841280086826370841460898715011137512038685864392079526912553523177019272440755510704279946872616455555313590656257840391404433847924673482299505689689769822347893968864046186358674105429643912021090605610906309627700793415194628412350783590691473324467581637253579290246840759262280795786394666829277098636383739586574194509405681992353099095656288666217128758044223382834658781601679058686559406948665993762673723079305381020139309264407402", + "6.63191504395654222093463225517095044257167358492883535520176025342395774211712657468200830942121109644363941340107615485128085049415855416468332623498613542536495098385995084442339062608583978638604918143347913056760626947758803721255941289939544782980624105947726287394246015934530636662452762740891034120692720860989191872617116876270993379145692068344563800080161568845297279023268580882621139265056001709415926357601143767499984660052292050156852098465716279953503805000122483365981348049448669145674005237424902758331184292667285733831838736385479377968893647208473593030642721808734551034183742049017463013327984017500270415348903044357529006803230836576763451403141885042163557880315832238470993889819388689962997828261446921618788229788339158160824684571810429272556119989956914418082964164895325888955223056217505031535326694543563995771654860377141087298652099371042888622930700365091746883791244230649741108473410207660026523417093735663777713562847430184433298925557785602803469943746593977417910571201562354064143775475359422531818578919533441219169564634992179085747739421396934533170253", + "6.86468424647826745014070025117717964024823451584566770298700199608686799810550334183271384036184024738713075357138304363500729701192009148330990514337822154917664169841019331985106373480242557119822580196465316734207821863081970176402541887949909079651180860550135778414330866329785285584237686124445664832783599634024854488870218943262246632754953077685614238917113547631797236909830439953169012672877303232625810370072296875077876422022480554261365112845624378648826827015798512264531843127157809664230543124721508342792582642801227649598361094857362199437229919720183995231808663615464777549808840564458629976163064258768399634097749419103019327558046204392219063653339901570969874642832022669018679996962548734797438261313737916279431144129292768130662584134756962916924264725125780137451698441993315631510366262043104603857813311015159104411207656587159892683007990478175317339407414253752547566811439103970532316615414849940518882874013736359501398823560697095317586441184708051608329999378177452455843424936412317738990534790002839870054268627101977849744783551897006721190846394315014179836658", + "7.08981540362206410919266993336458073119019782448954851285523115941164513836412872549980262695417866166490729449713028266494461146289769041010037483841114827384815079461242049139970069211580330491572838151707185120069855606140591888206680076074093607434178789797965056125568710210362486562167733000362559363045493390990061373467195915746340734563518180466064695504023626957372716533123941938499273960821861940878245300624658987006017095504422443198450842884024148817793468946118645483237729399532667369685538283843648168171114311227477906628002087322274050165358654777861672604286677553328777171742824907546089768216859979219968302594559549935402372256087285611714324493225991578081448459631584914955761298391279405253948506605002517304017862552843870010724998772238168184624304780886956610028083117103239621733160264889227045787864499275497227991534082024585777541674123189429702871674254383899983980905539696881555641586562578917589136538017200856225693373215704702453670534528006815061665390528267710616725134304996130761803394128053676974395892348477519793175492044505024663527553914391150385504545", + "7.30801444381621929576410414169825272457257572273051004511973439898925887398217614148081823016200949202834301901341123741998769012029715026961550074765354322325117408706019312795809700115432061001422232366558866090103569420172751971374783210350559722862260759626145820691043338967446065368729759698186882375361190232710825561214648603121419802078232806394885971508914082308000592725279784010670779537521209568997392415395010518735400320816396054990550737425086661554419518324971399666539322809263579915158239535250650034449433728950585403021312904469201906868572755498527768200566105436948987083446413896510763908286033307148367944294928994814851182637242369700047960905551015550891703778083820346244133873451184266447103836670847395501001367479270898875772403881434563877248062713559640372882766006167571899610660259996723172304669594755157014583499099899215181509673430723657636479581940652958938443019241663200400679385786760329883423015546482354218805580324551932049528493376425537320109696781135375077474891741199783559527857010245972108769520093587637938249980386334004821761518122012885593787752", + "7.51988482389300150724729585443313575902096022182981494988977072902688096382352592483978751513417179834802991799561163893459897085438020854287356696789844379574030644137437119341198341293905981640794145070339651469527740698824158833900605083910102747153254346823547028680012412545082587495438367753158559476209718277999227356404721909175713310761624474354590046592779251976853928721629028175578064120608571557774920892429935357615650299892305789477593676441150890402440458692356991420750424326859688267566794493155945645441408095648008938571758805471427497371233893925893138654640500264101675890590472426492701509085255763916845407952512948511109027030674293062273462578534032766972854651758610175461923748476891009535588426370610655790264436812079463314246950145130169825282410419274152444905553413922149504575861096531170020496816501665189089470157595748683377689903086933118316602453205910646274534078020297718628349356730140346988109490595289054093680476853006675328286507166881273403971565101745312606982548876538861884799764527184647967435303690091691151582053208991986612381777714301922567712528", + "7.72594721818665232400474478573212164113820580488963719814529844615257171391366083837598391841280737832475169393182272541886671862529201489762301217381727573506969107619318907033743713523584964748522235434860386240308259592226625308659565532071953554996921178294803994916620561170523298903408385287659414301910401193614716492481152548641726819012461794117027835912991336708840836650710281453954679059886797070453447940199379600879845764678851272615250256962113900000364647452410778972648375707943133926939195015381201426487954498462993056064744870715359730063675217952027028557542103700913113678148959057734510658771520791956879881016752781141774540974358264943959912543543231872348745595316009779251124673800869204892703157616225827295653493619371958957677652500482852408284671621135986394278188285088465620289846607059129785050607459357597788813170941394726408533348925805369815717709891710786025165701419078226562572328981485933748567540138562641027503508306197019193198804817270177795577482266694943462207325431350513542160949582976461379550638607760760045294712529920901600994240565773585313185966", + "7.92665459521202202669005753024036606304471951279238958541451612439347743605314331445754837571926806246548112958659070724577311536471294975198952931075034699966919918793884250232805461749423479324904837457089324667304067982764195744035286043093067787996889565306986604628296972508753114309320859400267789675026962497238890042066589975990144179370393781502607410897740628103263943824274864998435887027010214918657158068468943938068760888558966351513808680337871388293293939516817225831825387903008287452552651454178189914856752257554981494022967306190076652997599820594940704997277845097903068570525824332466980258464595176254308245979865165099086414860763567934690442503435576361413412395216127467775452411019392589836257808565460597773216981862679493249539029674390084365618781969773076939757580865513521481935704013963254685436747736179861799668941526147758194350248681797583637701669903788375213685518502773731631995426377144392048964303815782517427738248494010821572980664588536892911565823829885505136555649244837269033240184725561988089167118135264217990084374046308401528369901756263276741873753", + "8.12240393759049993775056085790344905374064693901884539671441829845338578772903259406144188243219398035169276840513008383162269420554517811059936012081975520344394583550625149140104890709858952675303897227339074601057818074118589698571155136079180679720382723235231538458633009534010518571057778133890494075838487054606092393806209145857916456072372240571169803355429160587649756506023316970860684505132706954885924145348134169632738593180936266392964765757145617588713808060798434336980045883860242149289652316891255507207532033909817967022156020135008789172223827513417867030366597530330645580768779589871599830015247516272684746457878444123615590973536303130500232072733480785298450742941376024222195955073652956648240243919431159576650278660779563988680861574614265500071902828098808112054130736935301171188377689518808421589113550324566036499684989624896195759485888011688106014339156094756792157734665908674538715149602342862415095116193802949560661722409343540501008020488626114518430540516030303410754550714099923563850234789351977675338732716128448507828986158960243138593921163553099984790877", + "8.31354547584695967940566378712267275288624539467359186240950261388420109063530469298372814586792322543394723656678356561805557643176058539909258806409526952143256265316829288574367192300134911326662579540672482872991356622029261017993364337446668505438648868283461277399259103747660496390168344220787056266691284920945026070198958124599742654165567628853365640939746555309453490999458540074120276825684247685153740702582674467303878126564742370625497947819552642763989933468008133993752611603522750223144711829552595043853200184607806501342069297514482919782863001913353586468996478801683403541333200250999752731449803793607515150980663437341133381305911283161078249341037269510562017916894714417589792091216017912110414165892331827272726552875986295229205099562827308056238370455191631964062828836731217300323551683849308479366652512262425881556198411502851577353998426212961146886854599036602811970862235743112454698389727605325232872049778977783694191972600155385422071256805381015864689257913905946358386236370406339271062529911829230871245337410607604318231151206871615890518289557823950960924210", + "8.50039005178969681405606694066857144339871874464321576831825225912653747873113563539576206921739603496466768191005963101509608216565231580166435976841183722328004091691395570837807106693569643325702021135074219386315687196397182977310724857959339705673410615655661738050498092907663921364482163693412990352699674010982361328463115845819153103736613515518538534444209396391044515527047534370066166976494484027905402462724778219101349242704419346472667550031765101749789603575074461809215731212887738126264415774177469700439565715044625979289026800701352092929127409916129794527211068956300531815748065200493298365734410099333662178356881545890691882401846675346795963611125059579096807842008824231421616080054119488676338739204001665175181321425845571967990452486774866455322197409200481385043451140315730188098217149173808292210439135828385844496694628703028478095465983540068867270220327383626367373083798876294946716176284955504565982296829544751335108774407823029718852800476212574258039209896227934401044333736396538381519446030490401670705477490565602459130058989097840050168516571928831986962913", + "8.68321505469921191235617552748954921446530673741455112371454793324441846343554874300139537881738616515735630882070923935302944564162345230558513008887324453213161255770304084085806671584594117832505684103850178581673663430908068527011627361538250583030533917385305060815056023116613524327810286415623197376863742340177925036584573230599476192380889477066406323810984087702033640107924182172686941361028312661313108216417359778002970966067090830603635404946756087016625118404340231456365795980675399247523972342833230042316359524247532024538043069127321959945729813306883450632483762749433800961196553281680789399437969279299794116549334300305897032285602148520076217180802664897460722376258717305407854893719421242134915981236756035407783461448793332599639580144795377945372918861006053713723472138436130841056694213733945161830059507242510609175123971434615259865080821278420604965765695747454031603269803511665039681088193517954588462094071113509985794023777506435906160395075220897453305493984243370136514880523527929961406848242166117211869964562420108871548138785581293418809932434011104394688986", + "8.86226925452758013649083741670572591398774728061193564106903894926455642295516090687475328369272332708113411812141285333118076432862211301262546854801393534231018849326552561424962586514475413114466047689633981400087319507675739860258350095092617009292723487247456320156960887762953108202709666250453199203806866738737576716833994894682925918204397725582580869380029533696715895666404927423124092451027327426097806625780823733757521369380528053998063553605030186022241836182648306854047161749415834212106922854804560210213892889034347383285002609152842562706698318472327090755358346941660971464678531134432612210271074974024960378243199437419252965320109107014642905616532489472601810574539481143694701622989099256567435633256253146630022328191054837513406248465297710230780380976108695762535103896379049527166450331111533807234830624094371534989417602530732221927092653986787128589592817979874979976131924621101944551983203223646986420672521501070282116716519630878067088168160008518827081738160334638270906417881245163452254242660067096217994865435596899741469365055631280829409442392988937981880682", + "9.03777677270990269726949426172862835196387072970673604230446563698972563128792797577778210699007499500445574250898762044933778750351774122552995617564832932129894429850247153326323323596747185514513829114667599621242841895828094634599104752390660626316359597361160805506977060785864672892966797271805786612860244448725471833865343085096665002696889160030343332226214610521511200144375391579536397373156980251473081426535067176615086187889982851260244145348339114794114481076655003899438879933457078775812975837503314934547103980296764470525861438620896571785240248887907778823513254337650341006992728965834432443948838718849505116031704247005966435163013464172640987633315418180257980416126510536269126886862377598402609093638096342316879109441931256004415158100347181648434500606990925357893191947800032622820087068319734681796146574385134374500536260087114364120328174363307505811192446227573869975931538764994397186624871438876822552201130556306754697296734741569342977980309931897617697257730057945805570021974106384510091603635687409774141632668637120038927426728226929784072977105651339473101367", + "9.20994037151839639631596462400338374636638793975877036082762359018286322506685344822885724499402625282278112227347785708110362882152982486492539276330024765085631629964295929748378249085804119808093549931994279721321289923550767047849571217878792843390809466346867991510868694156145415945082688797967786343353435552186659150661317606650543212335636343686331503215617274398559652422342499978550950096625965862569926163402495930664616089151511194642214415828373759355543462916433914010177922623548395072329545357529357267898707024956601854449660079838932334032102025937480901959732494297289761019832533135155565554257149646730285365649475508867137837769824225981627121384932711584555741221474225014838680519543027230604086666177022494683835532058874140274444425268608984020801682462141544862724398017210164256350727408755296407972623056472273132345914659683425221078106786482833330622821808530378022419276603327475231550015699876669280732914397733573148057766703638751272663518646580177302812435397453534475442185332367460952554021481188695967156473750726234595699444337049400460695213112082073164218031", + "9.37894419966950281444497699123566005692831626416482139632679675169065135994891966410056710379531185296997453115175739369207792866788913471025384584831759220067588685003261465869992419957481493970329156039794423572600489417423832178398520116622168531662587804563582591692339405679461818702500749407972729016331080470667010562134768478583188647079633628847731165033154000189887711845625882537683194893144001697291405120176988145015896091608729928306935261469019327442052101525774632932662882899190169943725336986511866531222451259355191551595932544893780095062627088118307374724034603309074230566321150596513714223540169605245519015025496827736989356586049475153155269118025874004811129386475129565322957001150834914097729540205532774277913604445897974904172097094197509573297586047245883925138372081888018562975908164098671652826540939370006401925797469800744090363913967117006512530422783187442587682838761306012830815412290263401144388335110015291263855233602315586489580934166304206346481887647538275213089289641095269061282993015859566679470384166281828144544679798214034013298421760057481691571217", + "9.54495610016641218053318050888027529952710202531153199575774210745792169686775867122286336893013980770883110393522762476818358876088129524710547725582400752350379006684967820956995284778747313445279111803934019554639715103722176378053227974233654201464826899178346960385701319012743023002834221825212678330062853593931422954382790959273783367681208829081125750296573583945273785727616528225035230730367043489573228646448365807546311686441424497747445818035366984113867781703025697773957490231025374107987159920796065423503962296590063470579872505263841733246548152591941651333013912614638133883335123920373070975004252305213546254181990284206802141740422901313199964786740911915995115427439794642825914605300283815175742959582878011011823566253034650282755730842497543625168601556462908567644285914941630229285900004349592874758990965409149767611455899099763319215107166406191621967564685710927764812630422088568711352107239482256315420275932243379732104022438119314824626037473517483829358567542790510299355289069031782291584296420055747908391149240325877115257851162524812619999740512151814664737655", + "9.70812956277849627020013008432023090142391629970752953381907255677408677683608283777972133699852226057384221251532058096143107203837634058545789370004650021408813594346758795590127624936380909477521162346782666694927945494282229717053636144889370566148233104188061190841182087686652430168640066046228725465172358875908141846376474355637636250095973439621439980693326786799959495956257525100473767694685408934461084692899974993028686930219291782447513786152395692604500383372485738542065647909407318214440351068221656470065118040045018410800167501279347597149519022186563837419966281229875188530501814945342053480368694378460223735611289594593646472862387163956627509412278526670700766402504793826839677765281076427340901353768173748184477638624215647772178191872811543334258915265427131978394362810703976093768885428630849932102391562462424663355002600929871388002261215265969294828417306845017134019844876207436524153517810279329274165301203983428519852972984397790790147707779427760025639355001932966608597649497333189984495365421369654196836993842047830874262598283161232047618963368717192374581237", + "9.86860538583256911820721127887475338860580572014113804764764567126280797502596779665406841324694419448453464475175038076268453561722477590781196193451866802150809759490712608888093911291954287843130175265867101964469755453143964084226755674039351003953563412948117884754289084798586264882426396661496381950383124624978217697985543751868445611832757526512148116901823991753587937386414616186527759915861182575983960867544511432164162055576224548617161606250500799648602173880407153261952724142638011741327947253437647196929757560958075420545787575757761080599830662321444781770561880447820833072140574469797429581558718245198502380676502327269925525873736136551448095090807729668471638614047172598418830416390391932045518785962567615347617805861430300764479148941742520703366317243140861995853488523921623877514753981220597859917397820846973107706661150411207144792858833362409021546109104485305007696344300462841655088641041139133938632803072811438751371559900802700904742289494188612587210415338399019832109459618353269954649298194490921810882187710461971651611477483705188781040460993037832290727754", + "10.0265130985240020096630611392441810120279469624397532665196943053691746184313678997863833535122290644640398906608155185794652944725069447238314226238645917276537419218324949245493112172520797552105886009378620195937032093176554511186747344521347032953767246243139603824001655006011011666058449033754474596827962437066563647520629587890095108101549929913945339545703900263580523829550537090077075216081142874369989452323991381015420039985640771930345823525486785386992061158980932189433389910247958435675572599087459419392187746086401191809567840729523666316164519190119085153952066701880223452078729656865693534544700768522246054393668393134814536937423239074969795010471204368929713953567814690061589833130252134604745123516081420772035258241610595108566260019350689310037654722569886992654073788522953267276781479537489336066242200222025211929354346099824450358653744924415775546993760788086169937877069373029150446580897352046265081265412705207212490730247067556710438200955584169787196208680232708347597673183538514917973301936957953062324707158678892153544273761198931548317570361906923009028337", + "10.1819721846243116158211195253926465666143347779815073047979911288728454119358550456874471060202706503091805338588626998024526166707650425773136658258074400903070578475129191134262714581830920726995815514653824789384673555040322558822640155690142138250981661144460598431698331929864441089428405069965236237150722105664811612049206741649626761309984600129580251270318577455853101292940548425839036066861121228690420716119923444705834233799961792271274742610225908970795751081615038981535248648458311885095799828145600663740483135495656806225462943772037314913924014868167062651948437081797920497967655996219852832742745294377907352391106793565373082008386931837077219804533025205245429016269305924868300059131465990367513110617768155977075582917392828200481639719171646996937843435515414397834073681939587838302796801187221313907962667869992989319909211964361393188990384040622902615977028693735275429763987359474700539603288721055646644016768647749162193038655134281042688011723482785471924105498640148127126652745316007086053077591814555887669601195725983108276147651242913586147914229810924624624361", + "10.3350931404633683691947436472707444709708693615480182604123950370334349544443021679231379500921649218800863593926760528756661011078126321844492668291462478393476503125536591219070509735210428947761875792828673301887541398513337078226608138436426593790404989932058023039769630384800611394806279966525193241106630459881453504032664228967399745528185257298594581458987077801324925958107100694837096169968690367946833033746754352596262639045628825434791015203759110279895685375377254959267384242428992179590079538654788434703331515082118259553412887391533698850248031662366010669929529784194795489078820235616519309873494295540734349932360576182477685064907138632368679604675882383935711506161826635113153997912713265877050477273997328780264216580134895532814312026671290109568535316587756940503116601114428904476514966934012890148992229020985082631236739332830184773141236150086303025054599442020885304151228567409725486746114685532611428843970696553723054870710919524255238928541738356450696516302034137957025179252274911492305284875580251537498242752152958407117066303014561567387290966125697410459079", + "10.4859783938191844505415935988555812169983910386669556187311537807971601489415184480294324534243750962935064587431065554132339655732601450466677346771766404683525586939467074949776376839516117900277707447519492965025773007813570350841194233890993183787851607015508682597768217867560501711087754801339252398186169563368609851974003387177803015256072875765438214167126280799321733391301521412815249368328101551446918784488181577223454487520647934057527710710187315407383842241034812304414618212426764289725514443697625658320934830119552552349454613146318727307440539214183275364282577270889732517818803743197835075972826771689559984211698450313448053374104683526842305753510193148049529361498811259623906343956382898276922773672099874559380274456904526382655867821184634279087424431765532414870700646132525635436192820560367779661664927428988733468931949806424994253052465407314901679252685856376776344476864227019344231976962348967817311235507614203388405955265951309377513783090550287722753128747261754207014515315881341170594023794216162541770211605362973081229737656368414853828067103315720270750873", + "10.6347231054330961637890049000468710967852967367343227692828467391174677075461930882497039404312679924973609417456954239974169171943465356151505622576167224107722261919186307370995510381737049573735925722756077768010478340921088783231002011411114041115126818469694758418835306531554372984325159950054383904456824008648509206020079387361951110184527727069909704325603544043605907479968591290774891094123279291131736795093698848050902564325663366479767626432603622322669020341917796822485659409929900105452830742576547225225667146684121685994200313098341107524803798216679250890643001632999316575761423736131913465232528996882995245389183932490310355838413092841757148673983898736712217268944737737243364194758691910788092275990750377595602679382926580501608749815835725227693645717133043491504212467565485943259974039733384056868179674891324584198730112303687866631251118478414455430751138157584997597135830954532233346237984386837638370480702580128433854005982355705368050580179201022259249808579240156592508770145749419614270509119208051546159383852271627968976323806675753699529133087158672557825682", + "10.7814158709708600973470860025697540134833131069132002021875135200480437122785122611113481677522707878078270440052147356092727695527920302171183192478655274869472668345393510398722323555179529207792958553208776624344340893028683838808544904189559530608618288330229561660785494464076778823090275262667649435818366046674470097351430635081878043122218079020162033184280808128488592626175069016310564044843363282384351603178223984429085151346774445891706273636784622362866483557972819012892787057761108736681050757369877123799164633273904139629258646240624506200184033024483531204256854941841214015611888414080581230610166978791113905519323893487804024647095097676311979368148451812686908830353037070405782315727089541764339584093637958422138796375184575441595432133925090181949043536072178753049486872204759334059020258970699357154378751215836144836352430031659044940188023466979385706234766354871873384990411026120082971281373943799958524209806200235642459562870710282507653952117525804197309040193746636407624935115304309270078857483676519373602411048897743124249850703751765985347181558029527375643215", + "10.9261393381382494183949485187745355142392643001293200037804399336898503279246222062168613731063277954463829865410973870577192080366472062964040509440033278743615823412810808078908898807870613199997974098405643999383690286991545964650196935814017029950722564391559018285106664794338502744786047104831103687602494259961816398342935032870065474763913436754495569767978627808003615457573685732588153239217166014299098858554629191013913370517654023841228586351241202877223367260494855558385058038046339898004510183855157527283289679410125378588229499416948431610345648489884658061910043475079418189307489137285545541133794341838958556245644032832230955632382851912531436083565766604594268028883405369333102861811110938475059430428576302304134018133552423994855168237965050769662481212059909922125002130317511819126236377187306085364203705624983640591322488295607424619160166746461204981597459574970519980426620414393119798825541827904061106147335114790118012457207318406183818422346913078125642646008877987007918624713747892824771389677121777686596898164466209882065864762628266271132718624356253452793196", + "11.0689707511584805117811434659236005479075122572654030261378132541766399464801053452268915436339505264869099960261186473580786841783940799119071862844203935756997737196827013181251824477181865522696656125604284386736805412679099995442756521262882968085901005737598504818120062960533623452879232321601862728439436565082413065419068437974996041360159534876356676912365960559399896203071153029799663110896121451617844812242705440244059051070332217484066565235938948140400311999208370258263622580614733135218175221722605324220534894428960790855444760163600390939087544087363052520657480331091788922029648714976820617337239621908921583216442263332160508780261589523500129489988435510612958327244523134689294673236630152564918827636287844901928132768223334355784295928691382783374669003085509906226346278070859886444582772115212199422165986886962139084337282264595688658520928296714120909731973712859435413818042451694188522026870751629872095477433593107333415373943667221266057108367464732484461448541683512088757459353259534085109191456436195932802460979824143610395941363551604400219577421540555259221554", + "11.2099824327958573986225648677376017877086475504215665299167067873045667553037759486727686750491707478834293411489125980911084151079663035133289893355490903237225455297933242623956756700765850165559519010287574088187786256136071791860343087283966672952333022508572112324619331645107711457400199461132270526458620965541207404627199559179879344651656741731856844106860800145662343482669094570758579364544899824573389424347400188820501898154253839556716834069987025577499729423912482339180176769424901522756286560845978811688935258106807347694868506072185526420367236029189162790328650177137575228819652438270486363627393827506772717574627945020518721350959544754722118727376733041854351927926293076323790604362596413400569959286648197872870638472594843231022845264486068134343862498444673897526209611533151572239019385139110221569524392708880223111039983515560401743550284647457807334695086237272708711276174560785696543477439261496094936993988602499825752049022699262521970903438062340959457966112130335715811951217156312056475059606961348236080146557716984203901504347783723320675301673124545417430186", + "11.3492422124642983926102856582985015285395067466832927043380356548562390804853608284602050743042816031793047600978062552284631473271698301080420930678002935270860213755533376410950434831683129266708417862791056849585318715091316511224772804579306952692391203428022706911552905897215022011255923056920968598357445951686767158007175858503283841137547847702169068881757041416256682026875119665861386894957609106355261396135163282225259885976498039746087649186814655905823222925759171803884806349350968882196634773164961078791229532476208824156202390581863307496926197095334795614010135645721792945689410813947143894261828309379674182914788493173415091362063280686801906811659162851572848118095721313328315435166989609801810101070813864563570801067282282192253552931615123833493584040857696592187534301264584146553957310718712255292573453576205261351861700915480639583301267167270018138941290820062263217901164511455735107338870881079416882936221444752202024321144178837275657426737380444900404799010786716522164241960362132578101367581203971478969200704781556667157536062389987737624943537002727294733986", + "11.4868138076131153078093551672152110823792896720438206208589815428358866831391271502916151740432833498923733353034882653574261402114885623063517466286983135609311347428616058487641764580040391132399123735354188924995726084316672645564644522404101010145113496826905661533851564869311026284567807835770793084267376582965078917724760751368098985709220493218989081195410084107253702771346532326060479533778255009456352092653858186317227040032545274297836762746748179412232929420302325855877594918256439049163258491252026402004889017462470314144712637559338394573924897045814379676299403438700340396558709369818377199922811836650582080165464955651223303653264959752987238908036388800978603698543078745746928727371682109974731915482666302457811317513367974821492659153756397368790555646602353958513206947086398520237613898204615597814371058763275824648368925762130837683909032578524176198944131412130278847693768941107158139354113448426375117837953121182384305427053092552066260458822741364621133976801759853058864467919702658753108948232787444346415009083332605651415456404729714544798893173653905698148137", + "11.6227571644752653007277348109508691363662508507756756751036701167061120453681652358829612013449512186720692331837632298664953191556594884903747923711091159798037951823211201052540116242903833376452779227088949634320335447650281101165924512030256613650508677820241405437704762762206782047959767675141661427645411489541320052642562158115270383536284327256491550000081996990946292465147038958140512483013436893674439652156220554266153922101105181022227884639488325310071375913459006514297537440977563220662148148970327960819157453757205132071390336936162228686072898193957868554143074268366176486204705456695741921244062641977969446800006474326691825663289023526630549872030867738441378997270522928994756399267446297804673669222384728768703789276705361232508520458717382592703150193394825544156320863346704391789739396085519417964187584947528508961792799045137827190950383493042007176116232841260864577432961637844272929218361324891683925506702245396833672138534821860627603036634022415963773401638269124800251684954328516467828750283529560003793822429188759689400075614871516086231035596052689743737025", + "11.7571287633482564701088417557941419439968698420773487503462842143146491163563371049337556035298522469859900749767294905204293522292298717243582785099170281163259336541392158276782668075147925622379654122962653351040016712959881553357605497106466470404805444939639812163187639434573134191280457860931724877949789107337574297713157520257772779962308829313235825010872269098259933266628859309692716030518264040729497076680529713079313207178190774506108797460140175583332304192519082133325489174600742357544490571971313852098894475025787306758030943007946889416870903157547612470086523779487801936864170079119042775197049616392224777035884133632044487020869747634558757479347496253003316077397398620232134764330013675436470146051001150951520936702104871579372375941323552263581652132668534769659706010116638397183935078175506596204447625920325403258326466185355961926258614112075160888891191719281518991171695016370238399249053764574155272331577493400906266452679122258224017845896213757845939003637544737204862728065115192407085665447911415853799165098806733280347311674415363212540753763695044873288556", + "11.8899818928180330400350862953605490945670792691885843781217741865902161540797149716863225635789020936982216943798860608686596730470694246279842939661255204995037987819082637534920819262413521898735725618563398700095610197414629361605292906463960168199533434796047990694244545876312967146398128910040168451254044374585833506309988496398521626905559067225391111634661094215489591573641229749765383054051532237798573710270341590710314133283844952727071302050680708243994090927522583874773808185451243117882897718126728487228512838633247224103445095928511497949639973089241105749591676764685460285578873649870047038769689276438146236896979774764862962229114535190203566375515336454212011859282419120166317861652908888475438671284819089665982547279401923987430854451158512654842817295465961540963637129827028222290355602094488202815512160426979269950341228922163729152537302269637545655250485568256282052827775416059744799313956571658807344645572367377614160737274101623235947099688280533936734873574482825770483347386725590354986027708834298213375067720289632698512656106946260229255485263439491511281063", + "12.0213668967023250475121483705231298685008638313363655540949682389613264866896132906306098642187026618532213215211701448267391188368047667853571572694775536356753264174403972755252732243831827044176139209024924394250581368618462046261557956041495153611139167826243672443648055383775943303041688490663671373136155053510360540267843423005332353653056262845689595224998209096627100780784418138991680078849703487894125005007545215782339870314429009558182449825490593249314052067759681658697789673578678949212809806351598964422253804794344853941490798950989758297119239095904492398955585999875857616109880042018712293986158989479506589338238909339482879806698524858243147005443655293460070165320341112926446082098108538465624611435423462989443724332948895564374322613862644840100579844319808606840135928070026153435302458230552287194862404115544729553555860135767866296645359954013075856567898559441124011177102556776336026301858215217613058011231118563314739369153408486077998475470304773205610152830759374129202640779824926230644346880253659061205608241669503029250691241581669322113673069664040300361434", + "12.1513313969589473215460257145568651201497518877897922428050262513288347242121973389754626809925134955645428561432377800707082867615886711829398230527046072149152117757833141185434477765869902183850205483276767851442668275870416792912369988091698336520343468857746751071883637173754271209585483303314697136442637145609733795560874016392837967424129624669796698075496202528858880383635774883501185883268804218639948489991597161620364526639036982352505612319544441359778240876504358105343789015081880171993801331134760442658432233574812308195804501595367608510691945957205786397773541197798945975331217200866768614798768369352312293373100870145040568859670724160372893783528980570376945737242122861351956826347861801637766043000626205823928280244639867984099618586640713739887577174825475613963518050410729443551908819114265689677577478145683280934590715455378138742260694148005560374430740814239204990726910962840148903954657341678891978442315098243895522200158153790667123362932646639672146391300060334021960329885543548050873714607049607780426796959929658969497274971918388832149882433776112378434610", + "12.2799204953578618617546194986711783284885172530116938144368314535771509667558045976384763266587016704303748296979704761081381717620397664865671903510669968678084217328572790633117099878107215974412473324265903962842838656473435606379942829050505712452107928846249065534782492554152722126011025173062371512447124740291554553421509014220072428311418179158177533762082303253141286989645666663806793346216795448342656821786999457421948811886868159285628588777116501247405795055524521868023723016473119342977272714337247635719827603327546913926621343978524311204280270124997453594630999239638634802644337751354075407234286619564038048753263401182285045035976563464216949517991028211274098829529896668645157402605736964080544888823602999291178070941183218703259256702481197869440224328285539315029919735628021900846763654500706187729683074196303084312788621291123362810414238197711110749709574470717069655903547110330030873335426650222570764388586364476419741035560485166836355135819544023640374991386327137930058958044315661460340536197491826128954196500096831279426592578273253394759361748277609755229071", + "12.4071769563386121910871723833880162795828461928567098974966545289703789921372252696246545971698126579135877653699779946636530700600709582176756559672195094792342638905717358599494762112026557836025246676548757396012224731074603580436169013312966381300981288214643884821974524286813435148379353275063447888532961343423260740356759285255609628548615681581561321713204134717540225393296689839237372943143825839653692927609315322726052991713273927559728897504704226043113857065570762959566602644918216789694969199672638429429945004464808633659900365281397958778937764586125792705750168571832536005054994358820565709437950496363494452954047921238695415144815274982050006786314548526164253480435527360117258227218473895919440988655875440528203125946747677251876874785141679432309253336655217406754914545493066933803303046355614733012876287373212014898518464354302511069792971558150198002542994517182497196658469446954272237277648451310578098894153010149839496340312748322929392343542401192635791443342446849357926898503374322883315593972409393470519281160983565963805711107788379316117321935018451317463295", + "12.5331413731550025120788264240552262650349337030496915831496178817114682730392098747329791918902863305800498633260193982243316180906336809047892782798307396595671774022906186556866390215650996940132357511723275244921290116470693138983434180651683791192209057803924504780002068757513764582573061292193093246034953046333204559400786984862618885126937412392431674432129875329475654786938171362596344020101428592962486815404989226269275049982050964912932279406858481733740076448726165236791737387809948044594465748859324274240234682608001489761959800911904582895205648987648856442440083377350279315098412071082116918180875960652807567992085491418518171171779048843712243763089005461162142441959768362576987291412815168255931404395101775965044072802013243885707825024188361637547068403212358740817592235653691584095976849421861670082802750277531514911692932624780562948317181155519719433742200985107712422346336716286438058226121690057831351581765881509015613412808834445888047751194480212233995260850290885434497091479423143647466627421197441327905883948348615191930342201498664435396962952383653761285421", + "12.6578523191369022687748451647920884211351618089655179455231284731368243638831930092692097344570437079901479457687357718509226590879392775115842265975597049724341563061418697031268607830263630749575108233222183077768581512869483056352211926808706010251598533367951222352547093385705143351301673698003798847470899037622815846893505998436154809431208770604783851594929676185652397778605631719747005946930957513095696933347983859316339644080864356270066190757023433598780191812725848826161342208170182063208964958296027351135838121377963924650053695239000481943588371643194130257120532938135164021072988780496867855135805902766925269096358874433009794964404505124093744345096904976475426376615294176138495927979455477696384319750513407338903997493563537351640190122018222196334825106936172049588584462292486129117684021653955548443028996098787136328122645959968477838803895341464736220878601918003630919411584046348014738162733741711244046308733521756823739827300238391611818552174369697043280135230378038036669764857912765848567411839492389221128518450325850349211951118365174902595493189143091128924607", + "12.7813464856668856522518691213367395488373983072590701713145905073584668550411607358543597603912057762741393691355864623321869872045162679380340422123959215611466910403902959589333930419739972126872708018261852986836161629068179608683599318758558454178186907956832450548642925510765032059337782409811599151491946626755685676305766429474808428640216684544678283803484695266015509922793933788792110436669354157798571269751040316991636951713788699537082555292927490570204626589644427435300175517403233899918923272847824314167455320989761357119076509049838004736602842837339638085643968136447256156911729326893301531646656269643040306415499484512699811735326226264568256017365274168292179743002227502407737172878415905382510704635403854488151102140855989374523291111062718131251568078280886769584934696459901137937953964469578793772809237271734821085928782404218121122181261925540158683038925682470156718138294664893516327450715858049368151852456159157278933365855419727276747917314838901881136398470619819131257733243425751608844676566931756320335811737311881389733198752534744615861076204027861852881480", + "12.9036588082705845248371543632003751697456908407741692410784368848786088725089065725375873804520087666996942746345726834840639975755506362717246534706442221166298621207504273622834658505486588760226060303402875348318760592759886407055350301443543632102422510097863033684320708847504885397025676888805608608575632588352908208382177260510976770708247524111302977184221988730373831487689478022518795416243743368791870779402875990432576302206741559354874008433704301896418503322037242979413682693250947191295393881165307605408058206874512520008288998516843589530555818279993680055875466221805842339665434759158713770816962051147931208116808824595295514375045899970471981704078070597035475020898965145851209954427460157152268663408082085125094326139800815655980081696754509782998928240270234248524845103756193355528876937225771208802709529190373396585475974586241329821820837801569449366833520227139445910446436020810058939318594350345270816751238237726135838608689569520523122450244404454913108932211269247818789816060744177821446724166244434311897023559474757455995497570838056986157112960941696803729504", + "13.0248225820488178685342632912343238216979601061218266855718218998666276951533231145020930682260792477360344632310638590295441684624351784583776951333098667981974188365545612612871000737689117674875852615577526787251049514636210279051744104230737587454580087607795759122258403467492028649171542962343479606529561351026688755487685984589921428857133421559960948571647613155305046016188627325903041204154246899196966232462603966700445644910063624590545310742013413052493767760651034718454869397101309887128595851424984506347453928637129803680706460369098293991859471996032517594872564412415070144179482992252118409915695391894969117482400145045884554842840322278011432577120399734619108356438807595811178234057913186320237397185513405311167519217318999889945937021719306691805937829150908057058520820765419626158504132060091774274508926086376591376268595715192288979762123191763090744864854362118104740490470526749755952163229027693188269314110667026497869103566625965385924059261283134617995824097636505520477232078529189494211027236324917581780494684363016330732220817837194012821489865101665659203348", + "13.1448695675323697034354136539313425180677406990253396231413553532158284729201772491011000710677650219054903693738656249197132353617817043139899355573740668204032909567434296038746304150062741309218977952141761472466065644454165057415693463642194136073230607947203262919479440729879071393287017368357538247791027372780044529165958694345741149609916405379143996738502906726395310549057499135876771945647726253389292849661459433071570826833703064597528372476669325238379807256995707509496936873280377426680968490544204144850652418667102858872780887677263338414336218554299503848227359603371483052714037382060524446989585125868194539667288699342590529933341716843693870456228542919094333819496744852442099842703290379050058483746581999303382422470703068869484513287507363016362925163918396245228476769779932001778978178333151597445957345163009522871315976591629005355442432626542153837481717190476686292454901373614541009740405739756345322959707818426567664529141400786956674079108340389783956916039981285613130422619726646882192158229279130067633381058950064006933912115038270746168224845260024281286513", + "13.2638300879130844418692645103419008851433471698576707104035205068479154842342531493640166188424221928872788268021523097025617009883171083293666524699722708507299019677199016888467812521716795727720983628669582611352125389551760744251188257987908956596124821189545257478849203186906127332490552548178206824138544172197838374523423375254198675829138413668912760016032313769059455804653716176524227853011200341883185271520228753499996932010458410031370419693143255990700761000024496673196269609889733829134801047484980551666236858533457146766367747277095875593778729441694718606128544361746910206836748409803492602665596803500054083069780608871505801360646167315352690280628377008432711576063166447694198777963877737992599565652289384323757645957667831632164936914362085854511223997991382883616592832979065177791044611243501006307065338908712799154330972075428217459730419874208577724586140073018349376758248846129948221694682041532005304683418747132755542712569486036886659785111557120560693988749318795483582114240312470812828755095071884506363715783906688243833912926998435817149547884279386906634051", + "13.3817331184947121778387694156683631366934609178535869224734646839530858830882778845431320165557527082867167385741007241233972349668341335799303120558949874914731632596672292536486840252369343075578062661394846729290886120806335230931470676125584836958188275362750631959355148413735909208659653125785489545299880650571571989789816736276472548899331360413686815340230072317761139617108693201596677053371411718241422778714572140731264458353536124425397143067303995240635567710414918725517399711583125030933885900593041624549493909270279061801044266813541511476059360070953132414715897099793064187618904913446179695444823627572975718616435530412231897626821211591630120456854888471296525545355847536852618755937846705639827645780754110681069739162703086029559215644121294709889120500305321671981859220528418810561091642459738043327836329007402390418543140043048855442197107222952090170835732458531444797752568765756885481280298531950424829111511736236703060978513393719587267334516212509718247535160103206224947196863863264871876290808068433102976710291998849009357718081807090905471789659277124839575212", + "13.4986063691111464245935803057163445333446588880954505218387843221811866477814509702726201994868384090085699517429739877130502525078353243003832198065078057206125867558943180721358516952593492926100016791442634700742497189485375590347895515367419024810678201127613962063650779588258427129303547853247317558007027886497918350521735648476962160113303483169507138322563300579235728423638552959320773585796896051727660519635215799533389594349417041464679040078438099479890297375500511781991113346083206493978277223781060900609203238286306467871141396991230768088662632124270257464480586088316850690383023345309392492732989705825016919526022563362954082266181904414071139631058950012713540527049102477938879051900769524120919579312018938311603558253092272074870766079137716555254983943200583248719785173513772917080626726235739995775731701263869010544645677727292023394850886826745691463821983518385802531448450511994014078687762847948523441279737079750421003933691499255395954393282954286628119050279442723264746413216878905804503870657461514746916596067609999603045774298320322180133249625717533859092149", + "13.6144763601762444379926521651240108493489429948062675392899749011656367981822455178853834668853591318227100171777478230478862293910435061059034482102617694499353623610929608083252219728860071814777496237554962825789860436664713007380885823257620705055571016537859083323332155283573726935538232458058826315899029704394102678491521465094178345832292296568693637792747393915301530583743993444025896838065118897343043328452916631236017814449542928117422626902025859794220329730506629124433815526321617718341415931415683837830843770074490481176348422362162861812661346849873918814224705384024355691424864367748319171681413896659635516678441852608440834144162761248958567982479001381585906063881204351628751599665209292094281446522809539191841105420891950899912208472122984294731662074195162813392306707005283151329632622622723286645815527491117005404146816741085203466335075802165744347567892995323123529815454414242781188328567365653543913086263285794736485546877191137857066664712691746005042143722635223400766012268118857311779477233465292274708583508374133748593182509627918787117455241091542819813359", + "13.7293684929565349002814005023543592804964690316913354059740039921737359962110066836654276807236804947742615071427660872700145940238401829666198102867564430983532833968203866397021274696048511423964516039293063346841564372616394035280508377589981815930236172110027155682866173265957057116847537224889132966556719926804970897774043788652449326550990615537122847783422709526359447381966087990633802534575460646525162074014459375015575284404496110852273022569124875729765365403159702452906368625431561932846108624944301668558516528560245529919672218971472439887445983944036799046361732723092955509961768112891725995232612851753679926819549883820603865511609240878443812730667980314193974928566404533803735999392509746959487652262747583255886228825858553626132516826951392583384852945025156027490339688398663126302073252408620920771562662203031820882241531317431978536601598095635063467881482850750509513362287820794106463323082969988103776574802747271900279764712139419063517288236941610321665999875635490491168684987282463547798106958000567974010853725420395569948956710379401344238169278863002835967332", + "13.8433071145943080802284382623942725643459634316370295832402490811584690521837914916840395377602432304386346321516022467700817063042586192089471811215559491096430603765490105342479464734028031685014017988597008866099563434747509151656359907403458022227708855288944495192855866834164923404580317751114810233440974813740088485452355904551218828581183511828392819322800423143611251652965268254587551056785058961962030307952250857929384076417852708688910729480334385710261322295627380646587526400594088017012104793668923859704481465512725231143313046840031532848517753228102569245860823651766421422437423742518931925679240338180398466042655884199628267998290371715502966743259677385997995351151244386978277483823663420757491844034607904266068469818830496093618976553620949696221798505339106720245367168877405376645269053274617909080172273096809275302452571198400347118006550023013802032386296495237116432503947861118574507348019315687686050292633217476405553408632695073744388341821217781854190838168727859124017786167368413748894627539001773837225674001211236781270826204317868935713403376698315709386501", + "13.9563155783525897163028298734019451091984537120228258009450472188267318438067135063202368534135430885083946298549306330756477989556178368665622436754180093476324880937959506547854538083370019416256575776948316707917842310903894619857591393548227911657101468449311608259623964684665016119377046647048049581386101096936670413063222259162339202191273628263372563875815041957309547200658623166127371954284217563921132238888463255849732942787630189806285692737078454631222616459782467155377806421107402656800251572053070998411099760060179547316216902478018563990476197410484317348357273331772258891407220597320756586444959820203436442764666649896682610015685305787123195940452350461973507211933252869415122355860564522872963830841829314900168567809701229312807570848373079796018588703327116777837136272491150569217486925114594308036945621245791848046986349492932929571328689798094081442393417715210813349185572333277619344160965594558435011430506853671006276522611925991500789685436288350432338677840599188216306552667639876278614865474090999682755277088033035543967117665417559338997296158961230538684255", + "14.0684162995042542216674654868534900853924743962472320944901951275359770399233794961508506556929677794549617967276360905381168930018337020653807687724763883010138302750489219880498862993622224095549373405969163535890073412613574826759778017493325279749388170684537388753850910851919272805375112411195909352449662070600051584320215271787478297061945044327159674754973100028483156776843882380652479233971600254593710768026548221752384413741309489246040289220352899116307815228866194939899432434878525491558800547976779979683367688903278732739389881734067014259394063217746106208605190496361134584948172589477057133531025440786827852253824524160548403487907421272973290367703881100721669407971269434798443550172625237114659431030829916141687040666884696235625814564129626435994637907086882588770755812283202784446386224614800747923981140905500960288869620470111613554587095067550976879563417478116388152425814195901924622311843539510171658250266502293689578285040347337973437140124945630951972283147130741281963393446164290359192448952378935001920557624942274221681701969732105101994763264008622253735683", + "14.1796308072441282183853398667291614623803956489790970257104623188232902767282574509996052539083573233298145889942605653298892229257953808202007496768222965476963015892248409827994013842316066098314567630341437024013971121228118377641336015214818721486835757959593011225113742042072497312433546600072511872609098678198012274693439183149268146912703636093212939100804725391474543306624788387699854792164372388175649060124931797401203419100884488639690168576804829763558693789223729096647545879906533473937107656768729633634222862245495581325600417464454810033071730955572334520857335510665755434348564981509217953643371995843993660518911909987080474451217457122342864898645198315616289691926316982991152259678255881050789701321000503460803572510568774002144999754447633636924860956177391322005616623420647924346632052977845409157572899855099445598306816404917155508334824637885940574334850876779996796181107939376311128317312515783517827307603440171245138674643140940490734106905601363012333078105653542123345026860999226152360678825610735394879178469695503958635098408901004932705510782878230077100909", + "14.2899797929645988880465370254439290463492686909646365784756651098966688981604710380521849261282420820080718993444184921140050946072295733777832552069831871497137709875484943005092844538329601721866028257517525127400112068229653107318786632214087321828354194286744189213884282476820178532929026410946336549250316411573632399544976436381304928255592757344082191936540818455775028244579956105065883479913799108021321113869783952904182528280242051379454218665561448727584030626615636178822706926814162499131369332023155252856087861647757703882420420084149242345266216149260241941567215880661724399293386262636274265942504563029111804888220594251821006906781849767633589028769011495517300679816156698760917682079890665846007154923427386849193920295060178471954901369186035029069580960675884569751521212531321426347035716993287569668349433572526231363707210075671937119893845403234179825305216364116472043430327447622673443562491607514186170086950732726413599236608453920182597620790203604341499252603323429275866821091530657037950087409657380807571921060480257877831704466578263052537696771142883837667113", + "14.3994831552013127711282056937351191001504093681728491932833832593979434994003430971466998201017992112805329010979828688660650916169722207860723532331591812462512916668982966008728885975214700393366748922112781560669442805260850747279232150993153692443149737581771637951619052246592314537389589547596925358885851353137852240888588511143973759301432800806312328067688373837578111007355067907342413561415117098106229593114120795475094598890952936412656420669510625019084604237747484641036400610081271857751008108979431957256358635365498727651936976456111883065483148617986465457792466402273815217241817163501352405823111497054361243886482686577961223780674009485714921257768842405600740516816638273826990939617065159558546972545307457270500896948955482426026947281134410487716638801651876698608693876104397820386663227664888754028406305427233767301780066332483940467863387166158701953351518332400189178702153049021261024299343478982543905250789402003398874430729393561464367541193884402280665307850918818544192856877565661864230591257923543269259287766045586392906627455350388206936516877511705006505488", + "14.5081600415254637821968107724614159379846815250015966632796986302946639359084284397562134794977873371225673488011687447300524372638777391491271044047013009672846765153462292968052361902815148016221806543555516416870983561046485697445468525590089690561736144515682350187091487327533880302736617743526917603555494921673130404909292620569107730648244440333842777280190694749887082191823918012255416939347228605499563575333082299453802606427072078361952092566154166904748856523531473204373911618483373304549076618565708179979210316820872299882348744668938414281930060202535519438925657354409407529756410826043868530687455675261372284869586600498214736517437102860130625263737648428644588668437974421283838793145810608177937448518286819323950509354081962798121406813386052183361387375237142429814580328643754914782720125219937145864600464244591497580867134545593652723923600055555437968222771839658325503488203860238775496018875409219820657867877489532429308420073127288519458470515585824162233002589242653827817278322155993680288963941768325132608929167231803325441134141466079523533004874074960297398614", + "14.6160288876324385915282082833965054491451514454610200902394687979785177479643522829616364603240189840566860380268224748399753802405943005392310014953070864465023481741203862559161940023086412200284446473311773218020713884034550394274956642070111944572452151925229164138208667793489213073745951939637376475072238046542165112242929720624283960415646561278977194301782816461600118545055956802134155907504241913799478483079002103747080064163279210998110147485017332310883903664994279933307864561852715983031647907050130006889886745790117080604262580893840381373714551099705553640113221087389797416689282779302152781657206661429673588858985798962970236527448473940009592181110203110178340755616764069248826774690236853289420767334169479100200273495854179775154480776286912775449612542711928074576553201233514379922132051999344634460933918951031402916699819979843036301934686144731527295916388130591787688603848332640080135877157352065976684603109296470843761116064910386409905698675285107464021939356227075015494978348239956711905571402049194421753904018717527587649996077266800964352303624402577118757550", + "14.7231074538527950476608918508913485210193928960438010156179716284477839899656296406728660773561791479300392640548844362423376122815685515054605750659875846934795898267446279294839998923205284269250511553190404067373365705229426342396747030473106863384763359235329631176350397962888021561481413516660292977014970409803172385929807914633372249932127302974588451306885951998924516950174494016508742886729576894104195203891310671564861400064652564905406159871623321437476286879872259083518836208723342177364371256650666793948295098750435124566209886842002880143316847324199429697285209003531473719741904014483758049310397090719533728097260541450500261317080346355382466832396046849587639939461239781658290728113330095841108422751523386313998448194981539672857289889090299694644812449713503451035671101363587351933041787935726164774892898031020620075494054191750748238175302842601156452243294124366476294688491666489019848361123258726182091191116324806207133930412068583323189688687308435693004227410778794481033787991938082837748996778982096020946799825701362360467247804846582233346459021849435486394414", + "14.8294128592903342463108620791209811162154136750542777284601531691224280305317915513146089525434202545204740516997954296244402311661887141413394532911541491603071708609940180070016261017915762557510278422457087524038813467378351272004581598457324467747373030877616178977537315248779792746942842469899245159612381076176060345997493587854288545462033896684057639832634271247921538572263389626921342927751757718681583536839938535751092658431596624136867197010308317749181005637423090876543873298238850113918296817041690209369633579425326504751223838947047626606883955090485790288429021610217101252189548742578539077253367329082514118063765427191960206852366367930126992346062168587627226173914689723039724555064028133389228017987680521282524145956765953246086551097796047782148791998851951221419883319817993999053278752506962511065678830257218401748568500747333591882058597483002531463654177181720203177842917132707292556291289892843397045703928170161651798774202385266858024628481292908429107158745626477532254897607152843489836358490936853541807395474017791353789095258403694863885903856428866385139618", + "14.9349616137730772518742205278502213908354666769768829412154208873914099415699826430905240500055519452566108757946045864392050766773281378318859154769239371884763198843033880284347786378856604370045769280031694584512791649322990279975840486835965869228399135416024953621164643532400693170358493033550812154255730604795122027373166382306083361422620489180286334685541856384068029463428651261328445748342560926139564774421725776053820917605563776256951832599871875185183132937072360851486597203051765984337363986545459745401275505488192448731938753525598111844098064910555199796449249197864727749286292996338718305630998619908744286323602224649686053449748987583874785327499948813912602137839272202488683363930706928086605262922617223633664247999608682512707009348695830289960455591428363355858586332036652696876145134314146004076987087103822970399358514255536649174532275760391584685618135079679840634515711782148326692482011033477006288036228152078965813370535741600755067904328039271925962758975702936379448509324264036066209770450856159966672496255612322665295729865499903170425957082810506551820498", + "15.0397696477860030144945917088662715180419204436596298997795414580537619276470518496795750302683435966960598359912232778691979417087604170857471339357968875914806128827487423868239668258781196328158829014067930293905548139764831766780121016782020549430650869364709405736002482509016517499087673550631711895241943655599845471280944381835142662152324894870918009318555850395370785744325805635115612824121714311554984178485987071523130059978461157895518735288230178080488091738471398284150084865371937653513358898631189129088281619129601787714351761094285499474246778785178627730928100052820335178118094485298540301817051152783369081590502589702221805406134858612454692515706806553394570930351722035092384749695378201907117685274122131158052887362415892662849390029026033965056482083854830488981110682784429900915172219306234004099363300333037817894031519149736675537980617386623663320490641182129254906815604059543725669871346028069397621898119057810818736095370601335065657301433376254680794313020349062521396509775307772376959952905436929593487060738018338230316410641798397322476355542860384513542506", + "15.1438523405392099196696941526680757548021305645205291142290551070202545969870806060651771792665589490055461678011089894664863226391200155446121001161264758488222957146306674042780025430540877651260123695207749882929804823786072408198311834035741094722904703994169074927527266054117152533255107532619942528281884626828101541096773239563535294095652383393617113444649817226044992144468812474731988014146393516008194986121551417317503118242518823714684606734325443399645596959933855453707336231367089097896345978026922587762215370241399967794400041904056720435869378522780399983882254234030896553717060098405070969432588607227990450595751600391582489120049548888787130887917656163272514952919890907132626716845497133112466950843147056634292546916486178521992255691504244921986125000809530997425200716615625657674011024011250858696591746091527644535689099940477872177573673286692409322089652390467243801596188075140733650997142370201841877916119994009448748653226635048181819256281784782880874622975340845523108222703652277923638344521781640569055426282343260980758922970221905010015543051560514662433274", + "15.2472245463115253370040636354083283666887786708714985639777668988830176955007183975627913778852644689341469297550544080185597077331715777153346360021007242495125392214774851264280715894226066393672643745253857483137929607374086675166192281961765358804770989187738591443219457532796617012663647789609431774075740567432008038961013943937307134814420860312306044163504297043835283963554752015900991148417739158394289066018572722217110593352847089201745718938357549727957979705487561467680940950578965108092971745951832261598491593612429568718722411875570411732507363965110669584642166670193068764600247928278340651032872526563501469069542627171043818450750969393729921266850657068206236571831577209919077311206015198636883915870987141318717046234082051220681758363352349761727350749598802358775860890853785340760259057433823505166593652654890358333190798767847250596060513312651361844271657521510045055877766996925314299833842766830666961654150747864536564429858555272922415110649733857674682620223561453248275694304210618254529601023775975491296511721889498789622849848564452286751061016082497088131584", + "15.3499006191973273271932743733389729106106465662646172680460393169714387084447557470480954083233770880379685371224630951351727147025497081082089879388337460847605271660715988291396374847634019968015591655332379953553548320591794507974928536313132140565134911057811331918478115692690902657513781466327964390558905925364443191776886267775090535389272723947721917202602879066426608737057083329758491682770994310428321027233749321777436014858585199107035735971395626559257243819405652335029653770591399178721590892921559544649784504159433642408276679973155389005350337656246816993288749049548293503305422189192594259042858274455047560941579251477856306294970704330271186897488785264092623536912370835806446753257171205100681111029503749113972588676479023379074070878101497336800280410356924143787399669535027376058454568125882734662103842745378855390985776613904203513017797747138888437136968088396337069879433887912538591669283312778213455485732955595524676294450606458545443919774430029550468739232908922412573697555394576825425670246864782661192745625121039099283240722841566743449202185347012194036339", + "15.4518944363733046480094895714642432822764116097792743962905968923051434278273216767519678368256147566495033878636454508377334372505840297952460243476345514701393821523863781406748742704716992949704447086972077248061651918445325061731913106414390710999384235658960798983324112234104659780681677057531882860382080238722943298496230509728345363802492358823405567182598267341768167330142056290790935811977359414090689588039875920175969152935770254523050051392422780000072929490482155794529675141588626785387839003076240285297590899692598611212948974143071946012735043590405405711508420740182622735629791811546902131754304158391375976203350556228354908194871652988791982508708646374469749119063201955850224934760173840978540631523245165459130698723874391791535530500096570481656934324227197278855637657017693124057969321411825957010121491871519557762634188278945281706669785161073963143541978342157205033140283815645312514465796297186749713508027712528205500701661239403838639760963454035559115496453338988692441465086270102708432189916595292275910127721552152009058942505984180320198848113154717062637193", + "15.5532194199919290973914478271101509782761473427556110871326128562635425877948922439065276333739001292422317859939226322742544533781551368669476914135913677167870569871992237487074670090250710391585542749455379676350917711973517231870663274531838871780463639607198142971742006771650734656927254936190760891498433170178096075966621078837969943641749478412326387664953246784721461426256026142642356786959544769333983224947181138296945030840334549653119000316260143077956508210419522473362562194412180815212162799927642323378945617932239804210721035735661553698229406968222610664812153679540697776845028123042956550110363507444357710659863250974690713371372128989567244046052322175878868097778138345843971318806979435481065172044184336853266870505659167792988132948583467977404968694959221486656240243417746389624264522689502159242881137811206933660406168854853625265097649099854630342455703384775379760129637369884518317406075014753125436006487026676158299533450354777908097205026564092618416813042451075357865075958584347010560603909401672674530473016380690156057342486458799820056849296157803970758151", + "15.6538885577994285336615322473375966991656095021435737363246099636760165366202196502339470259559417674183944684300887447920118633727001251716571523443596918848444675379732072543560564133448336770198458947224033362634921875944735296488201053135882187385898631210771646381454433721775116899072292857866394011427204808403618078909248941183413487233021402017272788966706121586469579730897499975748868490518551337318808652816220884250194097501134581362589451191335370815112714612837896607752466579681001969484402775834313370422194201064429923758665189369487888128968954146148578820551889951620171166054882708759173934381781451338459291737123198762967272009330015190135251071755806152473036989743744301736751164450587318893784207514998879026913548107957822584996296731105979982593758231329776234669559571495246544966721659816165141685360821041442768655874261766471614879723279695129605131434774277154659938308116466122952625429526707433155213455467498548671879756157972690042396634723002326783535035168700456971324492035298595293576869795744389366846556161860716979752870417581809090754427851499367674362389", + "15.7539144225679246209830112311867562489275000482982979660467978944730262881956936027247186896733459505337734582610770093614470487327551772081823931905589550005108629069012648755348782514228521197088346998693251351381154586496257153314478419466512135062477857636559546187276312380852109985976404783376323163746995587475215213229589580070616867837675337919606283901588189302295510731616001258677000217918798250564696325480908966629389997769717889909303798070409227548291667767301493099723866749466998823232247966469030308331085073105913646005885136696884725098040065704027444469765094470600930146845779530531161938075234915622678545819344667609350674211649145259963974499132458151510972295814587234589477382477724361318542752546281937647008728052174217050786598039517009852677136114528982242252373617954020044735443912957185708403871758652762532215592658585695740093871059422733899587935643096714258513937804831673775551390957596911031295963904326636986587614829199748400378284270489821119258092593559132400132757457303025648114989713809051372859786312670557557455024113430415444733469786577609605818156", + "15.8533091904240440533801150604807321260894390255847791708290322487869548721062866289150967514385361249309622591731814144915462307294258995039790586215006939993383983758776850046561092349884695864980967491417864933460813596552839148807057208618613557599377913061397320925659394501750622861864171880053557935005392499447778008413317995198028835874078756300521482179548125620652788764854972999687177405402042983731431613693788787613752177711793270302761736067574277658658787903363445166365077580601657490510530290835637982971350451510996298804593461238015330599519964118988140999455569019580613714105164866493396051692919035250861649195973033019817282972152713586938088500687115272282682479043225493555090482203878517967251561713092119554643396372535898649907805934878016873123756393954615387951516173102704296387140802792650937087349547235972359933788305229551638870049736359516727540333980757675042737103700554746326399085275428878409792860763156503485547649698802164314596132917707378582313164765977101027311129848967453806648036945112397617833423627052843598016874809261680305673980351252655348374751", + "15.9520846581496442456835073500703066451779451051014841539242701086762015613192896323745559106469019887460414126185431359961253757915198034227258433864250836161583392878779461056493265572605574360603888584134116652015717511381633174846503017116671061672690227704542137628252959797331559476487739925081575856685236012972763809030119081042926665276791590604864556488405316065408861219952886936162336641184918936697605192640548272076353846488495049719651439648905433484003530512876695233728489114894850158179246113864820837838500720026182528991300469647511661287205697325018876335964502449498974863642135604197870197848793495324492868083775898735465533757619639262635723010975848105068325903417106605865046292138037866182138413986125566393404019074389870752413124723753587841540468575699565237256318701348228914889961059600076085302269512336986876298095168455531799946876677717621683146126707236377496395703746431798350019356976580256457555721053870192650781008973533558052075870268801533388874712868860234888763155218624129421405763678812077319239075778407441953464485710013630549293699630738008836738523", + "16.0502522595242423047658196757944506380174575705759839278253230321445250829639481910961471931453116564538738497439478557175108609739886591120839569490500534822875304849736326488209685631259797055597162087990625950864597269364766964393819102203843223113243118426671582284256752979792222658121065967489791739897901556464359571005944335246989093673473307922127953030743811956112527855213800208534921642131401366328104759081292508449281353427532625724955074014554055167375410461346511957866858023371199864971286184642392511378752324547642788064420065819699737323404789938130114304157002506318247766787276624518432056105705328622750000206435275106450682964574301892472715679021266368586162764998585907621481532861299023329709215002403001723015543872591121222930217538067739593739604698257682609428654874555491602494919829715215979019400567591170934142751177256545981785724618392334660345395676518512531709484372866958613593771143352725257746445919068135186009397759278633269127719426191365945433194069995854695522773330552489914970861258642696680947645047295192118341734641074275298677776747132725952692040", + "16.1478230807732358804057911156359975578643269683364195005563293802325983679008984974142648714564442396471730040316476902098875094502600153583773509818474040254222873787323736489817652011370386406266250541511480202000072979598788155627873931210965950356003142252258291831141254744970185472236595284729309004225710563295709356523567610266397233789715267714804425396668330717742603267969954704057766975076430627334443597598422164729733865234176455146920250925398679022857258803104782468690438474584298601058258695871408692587584948563444892617899745726543714797413684357745555329038056593572733989924153298466060559153513812177648291034169614177512283257755959087939669505720323242559668932499003542818847651691092512987952257177634187849222278857431112238824103335198289105119122009380272498965826349738709572199722545419521302521285254070487073289909851344138939360922891594389079867498143873584750623589649101531017564978708138390620735321513779148712154176474583208544330503651654716904907116042682578169464107303714557388993154579350605533888231564568424188460142954331592433579506586890005695885131", + "16.2448078751809998755011217158068981074812938780376907934288365969067715754580651881228837648643879607033855368102601676632453884110903562211987202416395104068878916710125029828020978141971790535060779445467814920211563614823717939714231027215836135944076544647046307691726601906802103714211555626778098815167697410921218478761241829171583291214474448114233960671085832117529951301204663394172136901026541390977184829069626833926547718636187253278592953151429123517742761612159686867396009176772048429857930463378251101441506406781963593404431204027001757834444765502683573406073319506066129116153755917974319966003049503254536949291575688824723118194707260626100046414546696157059690148588275204844439191014730591329648048783886231915330055732155912797736172314922853100014380565619761622410826147387060234237675537903761684317822710064913207299936997924979239151897177602337621202867831218951358431546933181734907743029920468572483019023238760589912132344481868708100201604097725222903686108103206060682150910142819984712770046957870395535067746543225689701565797231792048627718784232710619996958175", + "16.3412170769233839606963694201612486691212128081356542739834914529370956581095536199949227667563196669751881720330847867749383217493562824508538192834810436530795251403748280815986888683090444963568544342830253998350516075153587022434123870840098964485733650438270480924257439534833868943235183119239136909416092084248849001763157362588633568969048428387870886333191418072195613026763062715704979389513606318621766300613512341969898200938319702408657590012474789777007123467808768282135872999150490149110158277006503250724953661837621574840115483372782860303277647284047119064007533593648396594330123081102605014990883472685835045389875767425672113541605338848610128464772662573977617761213414690520480262408650017838431407962017900140324046253143316145470737963355177005851379248147035370433387833420553321888460391167558380062662113254804107448975955978227341116496076743206260952106365143827443135137267145015186532545755133066280336384345677654367847031873202744469936264238113240447117511360963000412145400308169673233984915808549522819952866570114619293558801485679439444177553637843192666077022", + "16.4370608141699779533272474043612773161336096733770488551072483958825670966030102770671692026351162758060426915952129701085867802729318106406251695179863885464546615845148228047143539122431375925160247632834389582278394024330480487104411090951724620355644351152169170545009407362559853715960254174609992367516445002937337915452344034027633137804671869009243012191216273628143810422653645542449220632441502889291380255597379975105906010494299091436098925393391453500383425028779847395212818216089937829167091842984754080301999529208965785570901563511025237838322249140592553123941513540557406487062630678801556860907709013663182736461628834763074768624936750014768974286417533180445348738169351441886657201423938621061945983927061958409374247097943865562851972717122204967234909902165207404812597672553085816768537588350650139595857211821910608937442187518672584714044022382415383735643991420907608195400673486843199910879900829598881279040861315931094524028380978241183376771806462591007552168307790120399348941306657109189741410463773559051033330925696056841916167522766228211393262242421521807262490", + "16.5323489215027158446880825763336276539766654254272088764809875681257710901986514691251337281589597719030480979213983912333851607240138763154510692762929645134059390271108447868644173448984649545846075027064353386413401987057840078259547584916364797582515654545908036217306641693761885158675919161061304000673810487248591975444958643217446048240102727684132123680636339276356809494454912918773518940016680535088516253123764670882202459282812565757616402645579638779334204722728987624467180608880772319027534713555789150175287611585325048568498467487723808179090257348438123807077849594237725002857165318916587733119054901238012585296647106745143265490190013740659650259863719019289349488568359299562334530428982968033376892598005685239623058868742620448370226790430347712128643558758014939672725409586893221245647244200231825250935867451601474997763673733348363862073700502793354719022161931458435920378330557182605440069878979638381549353114629450034341931427150761577849342839121295284737993268351881523490532278330519022627550209271545051013287036978208888323804801374289519895876593198148288412392", + "16.6270909516939193588113275742453455057724907893471837248190052277684021812706093859674562917358464508678944731335671312361111528635211707981851761281905390428651253063365857714873438460026982265332515908134496574598271324405852203598672867489333701087729773656692255479851820749532099278033668844157411253338256984189005214039791624919948530833113525770673128187949311061890698199891708014824055365136849537030748140516534893460775625312948474125099589563910528552797986693601626798750522320704550044628942365910519008770640036921561300268413859502896583956572600382670717293799295760336680708266640050199950546289960758721503030196132687468226676261182256632215649868207453902112403583378942883517958418243203582422082833178466365454545310575197259045841019912565461611247674091038326392812565767346243460064710336769861695873330502452485176311239682300570315470799685242592229377370919807320562394172447148622490939677945521065046574409955795556738838394520031077084414251361076203172937851582781189271677247274081267854212505982365846174249067482121520863646230241374323178103657911564790192184842", + "16.7212961868837069596057427052330107838993265239842708646860851842703326371466460550285293861073853336430183927150625107744808082403658130218547877377223408626609338367841882539006706085525641360251738080907390644127125042595230279880637143368202331046893342048365464875596596339640431519843405480605327189233621288814329341353255673008710460439879747397502025941747471573127868412038250150005699065690619898644879967858901930028888717317423009915633225475656314991246247179300655948036458387420845855288877301555946710757857081888614708196039221016144384209347600898967572348354997689536324424925550167367649124956548098079407104673133738019223267238283865985764961736835718647168600253346670325018729936886914389649147361585260144938350502362779387053821926782839707071611980639055740818753798912061341260095450383120266085280004484309135011098574017285860156410583019562874766816141902023632532127548071497727038984896353454326117060152368514028177470621582059370306418123530554777252590192842881894048535435254976906742189935635359698594705800588739642243011198473083262224352068070947521888133964", + "16.8149736491937860979338473016064026815629713256323497948750601809568501329556639230091530125737561218251440117233688971366626226619494552699934840033236354855838182946899863935935135051148775248339278515431361132281679384204107687790514630925950009428499533762858168486928997467661567186100299191698405789687931448311811106940799338769819016977485112597785266160291200218493515224003641856137869046817349736860084136521100283230752847231380759335075251104980538366249594135868723508770265154137352284134429841268968217533402887160211021542302759108278289630550854043783744185492975265706362843229478657405729545441090741260159076361941917530778082026439317132083178091065099562781527891889439614485685906543894620100854938929972296809305957708892264846534267896729102201515793747667010846289314417299727358358529077708665332354286589063320334666559975273340602615325426971186711002042629355909063066914261841178544815216158892244142405490982903749738628073534048893782956355157093511439186949168195503573717926825734468084712589410442022354120219836575476305852256521675584981012952509686818126145279", + "16.9081321108119800703237241338254436690744863062204119333243683660599775226753565893209713389767766163161342358021127981271381134650847016286405604432987298022336098638563576267935354939301846494369816655337783246226209880075011315863553918585959135040655522896546602388719639509065495093614444330145112109456097752772698468793609700122810958534616000768715917714125275538225625413748533473685169190832331617113246579894504494307284312332165945233891016849490928121382853036960384597592081111721835630475340517447933339362704327966786541965781642013462403621512902647219230788448655730199762241068447349463838875501396349840327689919737332595302012041802495467706531267072999713901403393223067607382639770962103669304655143862584052038284208763832029931753811022041122025100304848953045363327544205876760304756720535938198106981928743202962212743831014622551526319592553193580573329441708624935281603762989949456873712545791427861490109968314910368234559629841124132807220595321318685022115111820471491845170412521830502033004342105561816928208532788908700951934092518100776316736470776442731692226738", + "17.0007801035793936281121338813371428867974374892864315366365045182530749574622712707915241384347920699293353638201192620301921643313046316033287195368236744465600818338279114167561421338713928665140404227014843877263137439279436595462144971591867941134682123131132347610099618581532784272896432738682598070539934802196472265692623169163830620747322703103707706888841879278208903105409506874013233395298896805581080492544955643820269848540883869294533510006353020349957920715014892361843146242577547625252883154835493940087913143008925195857805360140270418585825481983225958905442213791260106363149613040098659673146882019866732435671376309178138376480369335069359192722225011915819361568401764846284323216010823897735267747840800333035036264285169114393598090497354973291064439481840096277008690228063146037619643429834761658442087827165677168899338925740605695619093196708013773454044065476725273474616759775258989343235256991100913196459365908950267021754881564605943770560095242514851607841979245586880208866747279307676303889206098080334141095498113120491826011797819568010033703314385766397392583", + "17.0929259281098732308568909665181706090496358902951216052253094189082758184705768795728909606854105818308409911054301261308877905438819451701225816708775064163858458811220345957117443399486918793485162274149097723524277233813071363121925271943987039923392571390254618731212423397735256468820990712184553680703600120940437674047217109360209678344268629771031575160683542930850707582417669810552350662093148256275597877537621451125081219588556687019419120479317429823172107590283143446497248490970649768152464725806707130059311761908605648006129152794658287289985756220544649174887465478997809837771313116429454050449336877009922282134713999375548742678240072088620118531202157406755008724496781361076606758611169943346574996481406674965729735501106625955985540926899693816341047327437159278090340558983247348348622180363741547423011416478126650485047347378185921229539834418983942666680991963426108094492973587943493986808103947127419030775318104983559336517699874867642430990267257306908318775712545165790980870833770357342634597715966182879292691159156387989718754333799048530940386842225448232251458", + "17.1845776624693504399278552427660121759014355872173486225007203824024372840436910407549731315312720641661312015514244338979423498353490793511266853712442843525886341505446387699669856777170226001440090937353259650728051196433419270760984455065871632331371517893432279015787092579337531691612539497018543844203336945831070057415570861416522661341142055293762783441277787020381532046055783982924019170148071336852167967942723659657524174803803803905087308384416784431284819770363195053820968301578868801810080541678810607866404802296225462621786603189632403039176608470841164659717593262258932759900746120866956926679585397696382726469136456383993490336779413736927110713121992182458332821162549136160976369409523883489900369202140222731089221360463387016825261552399416009215359001253955577936829021948708246676341112942870776695271407974775582902477226815721865733052145151608560413760572173015439460907252134033256691370749495569198954137521453923556632774376333569072404958969821817487022660731421354245851272428708325787898296874181411803997899332362008586913072670711064770984500148015011826261837", + "17.2757431704407540851904450153949790380186687458654220684915230386503275825407063160604517288734546119505644391694970728295669021023983949819859759900830880079629779705059154865670128635551815720536815841099639525614851417689538084914680867424196821634089586241442130192038834512446570011888290802100133594182555986337723487386416534433468263224465623305274641330130540795411919391711267934371941107593205550581646424497484790190474300721785629523248847972136552642048161447129520586107875881613551369904113055686380180469790846706208691893855593511420750973530511165283555627597887745887134627634145517416050748158800890514425554639321377870923909855121500878983383395887478657227223962509627436500904372492098670589675883214674156834456454663362930882283624845127465731275714349781314030602882871329526710766294672136474269162102821374407938659858184740917810129868058466378108500499655709083903249046674366509191153761430075951411439469754773409282874508134728609913829574500910503209081050228705417132900939410588699788540167873020190018123072161219964179184690554184874930100756126982018853834025", + "17.3664301093984238247123510549790984289306134748291022474290958664888369268710974860027907576347723303147126176414184787060588912832469046111702601777464890642632251154060816817161334316918823566501136820770035716334732686181613705402325472307650116606106783477061012163011204623322704865562057283124639475372748468035585007316914646119895238476177895413281264762196817540406728021584836434537388272205662532262621643283471955600594193213418166120727080989351217403325023680868046291273159196135079849504794468566646008463271904849506404907608613825464391989145962661376690126496752549886760192239310656336157879887593855859958823309866860061179406457120429704015243436160532979492144475251743461081570978743884248426983196247351207081556692289758666519927916028959075589074583772201210742744694427687226168211338842746789032366011901448502121835024794286923051973016164255684120993153139149490806320653960702333007936217638703590917692418814222701997158804755501287181232079015044179490661098796848674027302976104705585992281369648433223442373992912484021774309627757116258683761986486802220878937797", + "17.4566459378143413191692225015426086274031136235582935243632385313858201877701704036484032520749642131133778450955342272025602510829158221972777670586061661701347328186526764805212080639525455982292015938346325289124302844332447725669617702921917808500525274187600536620801147819163613587837238728871997225991025080525180442534466864555824862414662339955733621810264862776187374419901285240431490175974449378317927398381519709919509933689563116335690204265534027606560764875449531405967998639356231702870487782798115026659692007825259723146752469612698767331463901780062493519689225278109283378310274389559679038834170680206517259537270404175432248633893701903077868034694197984698018454399995348712691476944938462701653906803877183551688371651410557476681964972950883316889946306025542494264115645449898893118484226513921500673490556592825150254681189771557834158711489644867165103165017573599086205249218767497287654393905135560681295542932352259490763907188060867843701402082704725079265886683176519491584308173914664681606671056250177292407244890772315688524722948557271250549147036005452988137053", + "17.5463979224170035169103569936773167710489071842695682164094650343960555822548938246261708686464008628120698086564271575140642653268871532667049895917630355233940483632068661179612946301911395716185300516412585342889806163058970394576807852912357307669092680925494306692002896260519270415602285809070330544448934264866486383161101778807666439177712377349404344204981825461265916701713439907634881628142000030147481541566984916776985069974871350878105191169601874427236107028216631331508432342933927262432252048403053983936328555651202085666743721276666416053287908582708399019416116728290391041137776899514963685453226344913930595188919687985925439640490668381197141268324607645626999418743675707607782207977941235558303966153142486351061701922818541439990955033863706292565895764497302237144629129915168217734367589190606338115923850388544120876370105674692788127644053617727607207239081379150797391284871402801013281516570366080963892214472234112621858777932368224243266851672272297127593365190407239608295928071192401106453278389676417859068237527688061268702479082098130209555748133337115265799590", + "17.6356931450223847051632626336912129159953047631160231255194263214719736745345056574006334052947783704789851124650942357806440283438448075865374177648755421744889004812088237415174002112721888433569481184443980026560025069439822330036408245659699705607208167409459718244781459151859701286920686791397587316924683661006361446569736280386659169943463243969853737516308403647389899899943288964539074045777396061094245615020794569618969810767286161759163196190210263374998456288778623199988233761901113536316735857956970778148341712538680960137046414511920334125306354736321418705129785669231702905296255118678564162795574424588337165553826200448066730531304621451838136219021244379504974116096097930348202146495020513154705219076501726427281405053157307369058563911985328395372478199002802154489559015174957595775902617263259894306671438880488104887489699278033942889387921168112741333336787578922278486757542524555357598873580646861232908497366240101359399679018683387336026768844320636768908505456317105807294092097672788610628498171867123780698747648210099920520967511623044818811130645542567309932834", + "17.7245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362428257066623615286572442260252509370960278706846203769865310512284992517302895082622893209537926796280017463901535147972051670019018523401858544697449491264031392177552590621640541933250090639840761373347747515343366798978936585183640879545116516173876005906739343179133280985484624818490205465485219561325156164746751504273876105610799612710721006037204448367236529661370809432349883166842421384570960912042042778577806869476657000521830568512541339663694465418151071669388332194292935706226886522442054214994804992075648639887483850593064021821402928581123306497894520362114907896228738940324597819851313487126651250629326004465638210967502681249693059542046156076195221739152507020779275809905433290066222306761446966124818874306997883520506146444385418530797357425717918563595974995995226384924220388910396640644729397284134504300214056423343303926175613417633632001703765416347632066927654181283576249032690450848532013419243598973087119379948293873011126256165881888478597787596376136", + }}; + + T pi = static_cast("3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913152"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = sqrt(pi * k); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 20); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); + // Check up to 1000 multiprecision digits. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_tan.cpp b/test/test_tan.cpp new file mode 100644 index 00000000..341c4fbc --- /dev/null +++ b/test/test_tan.cpp @@ -0,0 +1,611 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT +# define TEST_MPFR_50 + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array, 500> data = + {{ + {{ "0", "0" }}, + {{ "0.03125", "0.03126017650125595642059651621507489147877835880393069701338513042228140662868270178810496567920444849" }}, + {{ "0.0625", "0.06258150756627501465828481747745378814263718044751609194477198396918772026898277636891147279909599223" }}, + {{ "0.09375", "0.09402562724573195576489755283678159034525247904824579838425258406126459673745015890895186868431790389" }}, + {{ "0.125", "0.1256551365751309677926782186297740007586657638922255426688666139272557034809288714758416649081949452" }}, + {{ "0.15625", "0.1575341073252716106852257741724104906661974475121544257009051769486388715993896887955248205741956572" }}, + {{ "0.1875", "0.1897286107180591328910833700730338162710122536010363055257273177325079653665703027537671734777793159" }}, + {{ "0.21875", "0.2223072805534313308722888175879995822319104918387718270273535559005416973923742249393961682186904743" }}, + {{ "0.25", "0.2553419212210362665044822364904736782042016388008226217404756502588831981346542579493165026310550454" }}, + {{ "0.28125", "0.2889081724405147260015884454642448286982056723714186732378896291489603033944207768995735063901118923" }}, + {{ "0.3125", "0.3230862443517455201183006557179619743037036164759656335249943943470835620899848486165999610265179128" }}, + {{ "0.34375", "0.3579617388480169983883959631794471406375375900948760280972554801967920011385682070576100261097824193" }}, + {{ "0.375", "0.3936265759256327582294137871012180981856966444080712949818309739116951585799388015457993878787997269" }}, + {{ "0.40625", "0.4301800474642300490203296054472752679963181652078151755042924196261397876727827800621729454863519218" }}, + {{ "0.4375", "0.467730025452391799921342706961992620413738282701114114727311802060193364671415150855360089743973883" }}, + {{ "0.46875", "0.5063943574962298120708227547071771387085972911587370796115595547436950963394141008177411206688111652" }}, + {{ "0.5", "0.5463024898437905132551794657802853832975517201797912461640913859329075105180258157151806482706562186" }}, + {{ "0.53125", "0.5875973675914432213941588631578976924522062928763012976297627647411436985181631978010052165746790249" }}, + {{ "0.5625", "0.630437673835884766852611429299775209903293946951939898251650513745196222165381994293674222073197888" }}, + {{ "0.59375", "0.6750004851442429076631779494777229128864061685897319107997999948317524157945835559284790797708856594" }}, + {{ "0.625", "0.7214844409909044199895178832795946807605892812145963657590722733756611374332889471678213489198161525" }}, + {{ "0.65625", "0.770113551344208705005983660052773240245517035179766333813336659352553100285016757206110401160028615" }}, + {{ "0.6875", "0.8211418015898941219114239653747117008753716453086877023306268412086961091026737960147423436480371207" }}, + {{ "0.71875", "0.874858760554482349539671907932155532231782257040588572549027780010892786023906162883923961511720127" }}, + {{ "0.75", "0.9315964599440724611652027565739364281886913399722189970823760758473440872606463942290222395451727347" }}, + {{ "0.78125", "0.9917378983632686802568573899299023689572109767948642785884455151680071204845003794305054375396567381" }}, + {{ "0.8125", "1.055727639411919906905928322585893795895648561782414602487481288436493656539800004691156074588329712" }}, + {{ "0.84375", "1.124085134704560944131255965236688143403009777898521429483610660496648114350313475950507899270640935" }}, + {{ "0.875", "1.197421629234347972339226617276609445975806623418086002265951386950959459751336541541255052511392263" }}, + {{ "0.90625", "1.276461828982383445402617843263224436254612963462020761243811395954456362359102470162910199798207331" }}, + {{ "0.9375", "1.362071976376228231137266640571127531383954502011184315622281795551984309995647087587519913956728759" }}, + {{ "0.96875", "1.455296662469072910283351203225910848640458285194500237036240390915811463257413817682188441906818248" }}, + {{ "1", "1.557407724654902230506974807458360173087250772381520038383946605698861397151727289555099965202242984" }}, + {{ "1.03125", "1.669970130353601668362228999287655840466243330137306547430306024592587314737242276409239980979443174" }}, + {{ "1.0625", "1.794932157265411111412512666640647365321540790157497713363548060626019826336277151761592643681562889" }}, + {{ "1.09375", "1.934751011916103924218794082343652203808222523749686394781135509079848569244264225172363092871198012" }}, + {{ "1.125", "2.092571276372179004423733981234886782259941716148720572913991515339894408382371607574079035650497628" }}, + {{ "1.15625", "2.272484060247449371554848155118626331407879143446651944395567708418983252993702557436552564850427597" }}, + {{ "1.1875", "2.479912917556758792437515574454698934001624072586467858166295252178386457324268836053055868956236971" }}, + {{ "1.21875", "2.722205296368710926927932441765877991142333599010908457349133016162381084884183783877142234320889929" }}, + {{ "1.25", "3.009569673862831288157563894386243931391637699606062181047618417194668052548525026087449023543493348" }}, + {{ "1.28125", "3.356619539863437446801254212059537717694035906934171604782430676182834617443082960603002796648697006" }}, + {{ "1.3125", "3.785038166535876194630450975067081020082611278470578710038656250838244608554256510046862645943214168" }}, + {{ "1.34375", "4.328443997051826678273102914917348524900160978527585314859991445919675557868173766988955991311583481" }}, + {{ "1.375", "5.04191525648136332110647205436422898660842030191113551461354742130497045161358084541551547909572374" }}, + {{ "1.40625", "6.02236781523945747670227618692239447637023828129226996489330674807031833318199939459376428890858723" }}, + {{ "1.4375", "7.457597366497314807346683309400119820853357043059007743950216525315136075258562571085388447049580691" }}, + {{ "1.46875", "9.765431722939984318153137075537986427219225446494026346174651506537333303940271000197727980305021618" }}, + {{ "1.5", "14.10141994717171938764608365198775644565954357723586186612326758608969627041415526864870292630944229" }}, + {{ "1.53125", "25.27361509038201021888564593774203447137999639112919943365223977030408052066444435679945642193151117" }}, + {{ "1.5625", "120.5325057225426126499709994255564804478992494692406282802019970839232698437518852292295322760051977" }}, + {{ "1.59375", "-43.55836040673973128976461522014256814059799632626649998645431997677346427573993827534701436489680689" }}, + {{ "1.625", "-18.43086276236962258434966752738448975654856844592479276671012332110139541995382323486170528839748939" }}, + {{ "1.65625", "-11.67374867215481348216513536293945130766869617358776549669176281104274968860961548954064974733991076" }}, + {{ "1.6875", "-8.529773993911653209272999783778324026196719414411590092375294867302897481134537117581472896391856125" }}, + {{ "1.71875", "-6.709482397820695376442251396240149572345307174060614879543507453718786710576833294867753884694537068" }}, + {{ "1.75", "-5.520379922509330168089935698420205500301122430036809938027371836902288281994865833387763391132527793" }}, + {{ "1.78125", "-4.681280325336429567316481395066494078522124421106252324368679821712511116596067067167862140573504461" }}, + {{ "1.8125", "-4.056414052170035671394695838412072312925972547334020477371203912084804008892977770267448199074447777" }}, + {{ "1.84375", "-3.572185661861125859870109039981697499670205624150737204067785923886464814599307447743073100872203818" }}, + {{ "1.875", "-3.185238919501229169914672833591055563068190813252958079987355697225012578404488535638528315769681186" }}, + {{ "1.90625", "-2.868371726567042158384165205507273428429609298347592604875428057959086996590505442480814626239318494" }}, + {{ "1.9375", "-2.603652912010850547260718033703880538638622594696262109914178307203938532760442947667909676035790898" }}, + {{ "1.96875", "-2.378782114044268462754557076702009514149544247914950239975234530609231791907385965883627186285245033" }}, + {{ "2", "-2.185039863261518991643306102313682543432017746227663164562955869966773747209194182319743542104728548" }}, + {{ "2.03125", "-2.016072402071886080344963601799448100479409508905552305715636690184075224937451135890591580854847922" }}, + {{ "2.0625", "-1.86713988123437020407782794323860043132451055327769468817959958079457004467338400013589662215485346" }}, + {{ "2.09375", "-1.734634103946532053863260773540976834775727590591832428183425859927779370855756294581920109583545138" }}, + {{ "2.125", "-1.615759423973460045704218998135983105718634789435135146363364502252797531256854000679335498343468236" }}, + {{ "2.15625", "-1.508315836353881219959349807787957061590021089263168744744644715237923771519750208817662219357365791" }}, + {{ "2.1875", "-1.410548011813148830578875195416796900655621273730614063607851296345238287109255775298602026828637775" }}, + {{ "2.21875", "-1.321038011883972941371242354544773427461451983076687172335288474134737150563349929598365091185906691" }}, + {{ "2.25", "-1.238627616224096475286573358483115818987811679840895892063010057942989763968416082248247538779346115" }}, + {{ "2.28125", "-1.162361144121629479886631062456510653121514437736910570208484412489182649570861593071569298439919991" }}, + {{ "2.3125", "-1.091442725473163592445273166049218471062020679322657236270267019564600575624640388147984118518979059" }}, + {{ "2.34375", "-1.025203931548868392935198625444103909279764848147237361743751176005185409221197679274034521026108332" }}, + {{ "2.375", "-0.9630789471610371325783309326887526239686440615099207880230611368370468000350460791927023591069451265" }}, + {{ "2.40625", "-0.9045853091742213054875350240709441597937968403208608690036487459318455608785453421438664490396695609" }}, + {{ "2.4375", "-0.8493088059488314622450104194218363224080665638942044768228802750401486144919082454646163741529209686" }}, + {{ "2.46875", "-0.7968915235352686521345041809817019192899787435677815043081356746793473472915009329509869865385574704" }}, + {{ "2.5", "-0.747022297238660279355352687825274557904116956883011279066593089700271855760843718388592769933778409" }}, + {{ "2.53125", "-0.699429020084844342139783831016239425344370000759297142831905446726651787263273111657622358057530982" }}, + {{ "2.5625", "-0.653872397910572369605836837404416068498526729423046632151562590225826018439381877458767572737519508" }}, + {{ "2.59375", "-0.6101408409895599924272199138429116429964861640554001463611527892708422318404310839955568952517348978" }}, + {{ "2.625", "-0.5680462555551780726648895974757705443146437970424414412380682777625097984947690751561280498460825515" }}, + {{ "2.65625", "-0.5274205529869757121326571336563206310413652365485599902702063856643631953989601868253259786432770197" }}, + {{ "2.6875", "-0.4881127351190876547388242189029165584838796506348536005759885166591812246270986452391896414818116207" }}, + {{ "2.71875", "-0.4499864448356251166356611982487791354890745233650543094554613558499691453012194865420102877343872536" }}, + {{ "2.75", "-0.412917894484932487763966873261129123736255820362062889934249403216388494265361969753200463293305801" }}, + {{ "2.78125", "-0.3767941025635464453019403649599866905758314392515266200296815335892123350214817069316692446879993786" }}, + {{ "2.8125", "-0.3415113829599005939054709337126887266408130303329754956325710946559071503247227755879401227074384719" }}, + {{ "2.84375", "-0.3069740418053874743538801719778118186539092328300496832334808000582741898558068313989599567333495833" }}, + {{ "2.875", "-0.2730932453907306446782089914481699536905769611886147850801712661656164014954781669815730570254890551" }}, + {{ "2.90625", "-0.2397860292133634315864717364763276794949749917725083450148739709007738169658284872978100162537831057" }}, + {{ "2.9375", "-0.2069744234334290889140606202259876249518274239071734165293810142417092926391409078539182667795178826" }}, + {{ "2.96875", "-0.1745846741378176862031217701953393007964354401947395498383109594878301292911980508212117939922029155" }}, + {{ "3", "-0.1425465430742778052956354105339134932260922849018046476332389766888585952215385380591060583477669114" }}, + {{ "3.03125", "-0.1107926710961848652307179061543482824777047419183290635786540267776792824053626901819122659270065422" }}, + {{ "3.0625", "-0.07925799258597813975964847855303205226643624625818783981886842299834648957527837719024324414633813629" }}, + {{ "3.09375", "-0.04787918970239737242913390208792864526960233706882073548585416320272138422285616307162127608218497512" }}, + {{ "3.125", "-0.01659417649935840190191646601956655481659118246051776036792478758448298530865094236374141834995963483" }}, + {{ "3.15625", "0.01465839615112051363829193218735346545420611046761168233490628016451488745447998876530695315188732072" }}, + {{ "3.1875", "0.04593962329265888212191655478619122278727029224118607262776824432506068644004151566997697327162767079" }}, + {{ "3.21875", "0.07731082437922182842323045510047455560710445548270932232603347976675416898602720984389229982663062937" }}, + {{ "3.25", "0.1088340255133297195139603974000083015109646348076838424061656004036607221464457317348103204356071731" }}, + {{ "3.28125", "0.1405724535178196442425946789234394740490046721659763531803771463602023716095051057689530418533761391" }}, + {{ "3.3125", "0.172591050272744891901962315250310519786980119755314731828011976218754514667360156546007027602360458" }}, + {{ "3.34375", "0.2049570163396922924222670027465798026391019465616329916778651389384367221289434591672530287680469817" }}, + {{ "3.375", "0.237740393762143806988724415397077124401764815151774813277613941354927085310634989951327775643776322" }}, + {{ "3.40625", "0.2710146991120596316784994914008470605846614604634004480958302230976152416477575814862222371539690966" }}, + {{ "3.4375", "0.3048576194048116313509686061976383012732471442214687629070980813100980504220010433668547826451536192" }}, + {{ "3.46875", "0.33935178550149794902043849733017382894738729159656755127388089028458110314950118486374283672385814" }}, + {{ "3.5", "0.3745856401585946663305125799891473884508822842892592306930231225774355972615263725457922224498281269" }}, + {{ "3.53125", "0.4106544211005646795132687105613188412302653916099336518744517138690111552283413041415216571077234329" }}, + {{ "3.5625", "0.447661283553583556404846819303519593092219301719424669894622854440119111664920988209774876249304265" }}, + {{ "3.59375", "0.4857185918149514991806435613800961704649349211376530235980832426061445834319868210377502054789684188" }}, + {{ "3.625", "0.5249494159434426029201266393240939090334746308513972623727472919160131375298663507047002581644827389" }}, + {{ "3.65625", "0.5654892779403682511970427653303379875705726194565986095362182202060326386665976843463927284690694492" }}, + {{ "3.6875", "0.6074882023842700195137806696254362966726637333828709216522375901698082716779542882925451551904376524" }}, + {{ "3.71875", "0.6511131401046877694771154604832169765858772246556092408841970307496747807017677126165226354908150626" }}, + {{ "3.75", "0.6965508511114601330600221624003410002384063251948773727536766307711270568580190864635818668189622464" }}, + {{ "3.78125", "0.7440113559767865266278722337979770721544668975249127911732590346704528413537145792818180362367062195" }}, + {{ "3.8125", "0.7937320950520845038640709755691971987193904745863880210276991068348251595048327258835950484424829585" }}, + {{ "3.84375", "0.8459829748791345210684014414635237310065611239815471815195561711011715779741435605360151278986068963" }}, + {{ "3.875", "0.9010725345768489830226429310383860542057548011724428357500976339946729939388193110037885928433616767" }}, + {{ "3.90625", "0.9593555370605378999830231072930600308342084750238673386763085477722047681353378531697620720257631096" }}, + {{ "3.9375", "1.021242388200347736200680021836703924511025898807046899043703227626470466798902950286611342705663006" }}, + {{ "3.96875", "1.087210922446937924973630130633474302114867753655250594086911814333271884554141747835703519160797518" }}, + {{ "4", "1.157821282349577583137342418267323923119762767367142130084857189358985762063503791325897570132020188" }}, + {{ "4.03125", "1.233734886297294089608083483431716940428204649552146125435266924766182484146724296986257289579785258" }}, + {{ "4.0625", "1.315738861236497278595002752513023767487817470172494220905161864739955592222079472915707284820672627" }}, + {{ "4.09375", "1.404777873409928816791398747372142291632709052730067982243952454765008272213717678329031865335794425" }}, + {{ "4.125", "1.501996112821481350670183703711495663471610930233216088609964712367465201389736354667815373825067405" }}, + {{ "4.15625", "1.608793425833300449400383022559449738336897468383397721431496100147808519893555398680197430417094739" }}, + {{ "4.1875", "1.726901492741173774258474522465444605840834193796631414995320087774658896048364103982815258692096685" }}, + {{ "4.21875", "1.858488933532261262387603943116424040560957193049648082245398381173590809878153982869279424951736518" }}, + {{ "4.25", "2.006309027858059435312199733843025004203991000201116744630971025635743461495678364523854925961565933" }}, + {{ "4.28125", "2.173911671176453464233801926617652208987805422324233358984523813313677124319401603031463553334586795" }}, + {{ "4.3125", "2.365954706436810886261405424430153147538433069393544616996159851851045098884294543485330531184033036" }}, + {{ "4.34375", "2.58867360110912318951821732893635523217217883697807084314676743075156168098379747192932679404932885" }}, + {{ "4.375", "2.850612135014197347464512007371469511624647336547380863597026522958389351638925329325864211361675359" }}, + {{ "4.40625", "3.163800603288976619542297558662099459127776345948257172928079751633780670148333702513937775996967237" }}, + {{ "4.4375", "3.545737656638732611056781822478653525618506322500845353570490033964184425114602742381228738013800916" }}, + {{ "4.46875", "4.022897320897881433471367965265766624497222626661161034375557752511167850308209715183529923181209519" }}, + {{ "4.5", "4.63733205455118446831908669495962673002033167604849908135592490784364853630436659035964429989580423" }}, + {{ "4.53125", "5.460110732358225081268571201584576241967507554680233568022847841671382048904153089722943992228366072" }}, + {{ "4.5625", "6.621566538917184779658822397475662809951450423939232173471067230932326374886115835513736745573657993" }}, + {{ "4.59375", "8.389349373172668043480112406855801804399985563752529469857319424831372393351619823015010870227400011" }}, + {{ "4.625", "11.41394586984414667039249686700424655784704375419079662399301751232175345550471908433956600220150528" }}, + {{ "4.65625", "17.794217921195291872116110930917322871062931030345133311457707064544221956249568351463091932558272" }}, + {{ "4.6875", "40.17012705640036449304190879290789586501901676251470634007061519017512737181345480527620292167336129" }}, + {{ "4.71875", "-157.2053810419425516610333761767147984621064081691004376958977511691902151494982722512124394464246881" }}, + {{ "4.75", "-26.57541423100021444925624133456621507049828719711987551420375127874685894467704404079281767156965171" }}, + {{ "4.78125", "-14.49904303397407169401387138739025359024482851876427547784737429808056788404653273313794074954104547" }}, + {{ "4.8125", "-9.955517692663199659497301146983549868138803040917546840671025802878897403111578981570237166977305366" }}, + {{ "4.84375", "-7.568770928466597669950125714728032038595443682400782384350047230172533622281584347829485301888539665" }}, + {{ "4.875", "-6.095345265174791895543529207308251915058396610943153120402963827367536675687235397631104150517714925" }}, + {{ "4.90625", "-5.093551747761417849838605582864480592041118085930024194611183352044275362666663197560756285563557591" }}, + {{ "4.9375", "-4.366960809832423113382187614785174399552256061595826665894310062349100292377458713017173941901099366" }}, + {{ "4.96875", "-3.814918596744426621193354615307784649480559936141816068738250826073519922812423391628708426424484949" }}, + {{ "5", "-3.380515006246585636982705879447343908709569208285459877176820980918346010201206056831791856009410428" }}, + {{ "5.03125", "-3.029148102302771164961521436423971160566131129828714146460894246137584114582867735365596418294127015" }}, + {{ "5.0625", "-2.73856823245603647865430226656274757425295307326689315789016177502179223572750955725123296691662252" }}, + {{ "5.09375", "-2.493817050876063510228483889992811590654110757263765873027034424090589388194896708294715609776449821" }}, + {{ "5.125", "-2.284466361999853132376034939699606124682746442696980078901017290742647881722505799438755300967817548" }}, + {{ "5.15625", "-2.103023353734157432798966856819893312894278382156270431204069828145019096032929826221618815522735662" }}, + {{ "5.1875", "-1.94396519241478443283285298645374010314101176847753574637302261542129293949555826361500398886874374" }}, + {{ "5.21875", "-1.803131092461690600361529359360266463729989122374270260332052248390551413451160551386405337128358437" }}, + {{ "5.25", "-1.677326406624389127684834446781355734878514221167662440011355600468562011653802826535309338734910053" }}, + {{ "5.28125", "-1.564057206075927617852462348582481289639348906743456817576975327632362277790709160010002260498590699" }}, + {{ "5.3125", "-1.461347784441303570775301256747389266430752496556055422309798378517676612642129660840051802732712867" }}, + {{ "5.34375", "-1.36761235448791393113713404156603997628029078648313063442112198771680848353561063900933679869893461" }}, + {{ "5.375", "-1.281563046345464215429873432637423222317866003116950751512613373376845314748305445490135781753417754" }}, + {{ "5.40625", "-1.202142762311081825673780483344209940977316276937937096782702116019344314429792428912212274465011549" }}, + {{ "5.4375", "-1.128475389186388730418668294914420100814289081230956940736485357975544285270667364906582995184004442" }}, + {{ "5.46875", "-1.059828347715565927266867602143137996921061876523369816266086983272908895834550263458873978282357056" }}, + {{ "5.5", "-0.9955840522138850177019161740702867286905993509040201421089147368547994233084178348523042915084083077" }}, + {{ "5.53125", "-0.9352178996735373313249149491276249977722839556692437323635652451207536878974422360418217978053551773" }}, + {{ "5.5625", "-0.8782811077026627420028846442823333510762218192932291958379466783448865095622083395150126065512344446" }}, + {{ "5.59375", "-0.8243871973186229222115460053416379931615277523370335469512772188350449840600638037662602397836368723" }}, + {{ "5.625", "-0.7732012463758734614771474685457909254527078194270700631060606366411896649393019485319264721701600447" }}, + {{ "5.65625", "-0.7244312708999757737148502388902211557937330882505616499576249426224616653330080051888518816616123148" }}, + {{ "5.6875", "-0.6778212563139696041943536024958433042316769928076303165171422834039846729764625273526488517789737417" }}, + {{ "5.71875", "-0.6331454792161440424929262529011204753164261484247750443857435235991899745283883164285814469564729784" }}, + {{ "5.75", "-0.5902038468644901054170195032663081108054249240846444267071062035473153343668376567479794165486184472" }}, + {{ "5.78125", "-0.5488180452487470465583585186996023704202388711137425402809495353782052794835324270116435144444853907" }}, + {{ "5.8125", "-0.5088283340526268433264568968479225952416460593340160732760808861658301198202358775409378607410253813" }}, + {{ "5.84375", "-0.4700908624280941936361204610007198415053847982327139590868905985009927783431252538270334618349713453" }}, + {{ "5.875", "-0.4324754064907757695440115128522408464584984965503283137576460100497915888775090560945910034482914049" }}, + {{ "5.90625", "-0.3958634500577715728387322802090283590444850041488349012771936138475077409268246305105488709941047507" }}, + {{ "5.9375", "-0.3601465460097104261765989532960199175446047549989388477273964911510226366930877544365028188123550406" }}, + {{ "5.96875", "-0.3252249079465421281971924062604461228563045080514509080291865924060718896122952297947720584304400305" }}, + {{ "6", "-0.2910061913847491570536995888681755428311555709123391316088271933046559131122021519996248059475229616" }}, + {{ "6.03125", "-0.2574044312501190948926553260844066507272665964422420930835303888833069876363053415593229084989769505" }}, + {{ "6.0625", "-0.2243391083295019990486082083153394557139168759436924449745473819036543999446390847474833972561431122" }}, + {{ "6.09375", "-0.1917343220126000636733861789852210342976612418141698349764104452472624060435608559813294673409175422" }}, + {{ "6.125", "-0.1595180503486741129487427411798597329274963598657430717585348638114328150730071113710855848882228728" }}, + {{ "6.15625", "-0.1276214813658537291522157530092700353508309312306960197241502999632222071779029887930485312029959035" }}, + {{ "6.1875", "-0.09597840190639155007190320592294119000151190572960121328263061886000450929267149036536453259308092125" }}, + {{ "6.21875", "-0.06452463203653075216342354397349405171379838323909874171208799994716724111404978040328803565744248937" }}, + {{ "6.25", "-0.03319749448301144438419631194317525127766038457693080701966081495473675499225984399367237591921526005" }}, + {{ "6.28125", "-0.001935309595765553843691829525274435788517976054625627169224279956186864996201309127614969112751901202" }}, + {{ "6.3125", "0.02932309291350979792274199376680897224174579057648744678958323756547521586508413864276599103614351545" }}, + {{ "6.34375", "0.06063885372047505801221326406404454670246033034497805406862823133882341608599003383282431176702261307" }}, + {{ "6.375", "0.09207356314350050835492397132807778236841887606137324897895572241559097713132233298612222140840431269" }}, + {{ "6.40625", "0.1236897479096077296070838372979705928368188283231838414804934929274025398571452124588393065510099759" }}, + {{ "6.4375", "0.1555513736514298191439929689618245053471522825437403514671018199418895089031472964835239198291348668" }}, + {{ "6.46875", "0.1877243718114725376401948692378642961122451437059168414418744613043681130520375192781612678122611322" }}, + {{ "6.5", "0.220277200345896811825735903245910395013134783433298671312565971040207859095962733489570927809983752" }}, + {{ "6.53125", "0.253281448628424489171015810263074415662213222146436493340123226398154356922736152388141063544543841" }}, + {{ "6.5625", "0.2868124983022992902396435016696204994189572656467726352599962917225918966603261177449285587256173481" }}, + {{ "6.59375", "0.3209502535782458942725336084114371332732723992168430541003499245591367871623197594684565991267905584" }}, + {{ "6.625", "0.3557799567143647005420612267605866339037398845912245431900523492992941964222774204935357299525662811" }}, + {{ "6.65625", "0.3913931072527633586303310805574337028074307951034635414359349547707586122479246892158861767238081689" }}, + {{ "6.6875", "0.4278885071761893999613016206982314187458164558702387841850210320754507932238151571774989545334487634" }}, + {{ "6.71875", "0.4653734586819128141559933341200671578345456984030117446615279672146457039797505409854792515433603876" }}, + {{ "6.75", "0.5039651470083475548132524571742890116543823430974166616625221219450482100216791892806202009417424483" }}, + {{ "6.78125", "0.5437922480355643338730870787135605883829637094412174029296025101763018004204025974330398781596165429" }}, + {{ "6.8125", "0.5849968096716556782374159174641655681779685895667304240747256104820508784969531169383146463204412289" }}, + {{ "6.84375", "0.6277364679474334892591612082171255002710958195004825881252644517358490289176441185242244713866378973" }}, + {{ "6.875", "0.6721870741034611638659173114401257239025537597591200195749563598359978601937626091399638175089362186" }}, + {{ "6.90625", "0.7185458288995548400076077740862700950460682676000352992576300205153430366069275776925317595307700138" }}, + {{ "6.9375", "0.7670350464671162556530262845461572442649216262010355745804068537455730294466119988902478588983034749" }}, + {{ "6.96875", "0.8179067044246350052260597321820256016080683284701549230268748786223049718597359248253027839270497755" }}, + {{ "7", "0.8714479827243187364564508896003135663222034245984200644480154523301674476556679351044748556811165168" }}, + {{ "7.03125", "0.927988055100702558366453168987743089267307369461721117972360539733706484657902890137954063374826404" }}, + {{ "7.0625", "0.9879064802291251594676053789880311203133455080943572829265181459625625927973428370265184881799942024" }}, + {{ "7.09375", "1.0516436537462216418830263449985522705286903110788757629051396054699693751826899237943523838887297" }}, + {{ "7.125", "1.119713940340697920929231941973033073135897434271449197914919579212768620587877263960959541708252549" }}, + {{ "7.15625", "1.192722326901007588684149485242155872646533354464514409876904886587006629927655098723914331692457874" }}, + {{ "7.1875", "1.271385753083766195102512866837447084316821755807112034055075019301218550802923593730276046614253933" }}, + {{ "7.21875", "1.356560730687106090381626490498188582130942795512557181635747233593968595718598671759051546605979157" }}, + {{ "7.25", "1.449279530126825400966804908182545262594041927922324311633865090981669827371184783228521282728877249" }}, + {{ "7.28125", "1.550798206734497978345598394969907597227586253061565831974177990152095709794984147425013361851865459" }}, + {{ "7.3125", "1.662661250535958572647253880444919849918733690439628459569418630367100238120581497993662350014826086" }}, + {{ "7.34375", "1.78678998697496418766617671089138013384203233815466866101103271149031802024685694556034074365409757" }}, + {{ "7.375", "1.925605576103531021088436315604614476223254075602410795428544750301783382496712246458936951616523844" }}, + {{ "7.40625", "2.082203514638078116771326575602059859463528643293617740928645387731580498162533103205305011512631601" }}, + {{ "7.4375", "2.26060669237264261355866723509904048590096081733761353611694012356866351200745710198451308329107618" }}, + {{ "7.46875", "2.466141609729379985621243345839389610788373993111041429799962056660510586368685947727836988290301937" }}, + {{ "7.5", "2.706013866772690776762802272387995008883446304522264964682388787620940583840910641036913840080466461" }}, + {{ "7.53125", "2.990217991868365275378986251269668199642886675694545360724616292050097614350992705530127905271866877" }}, + {{ "7.5625", "3.333032524336291185691514966848310245587002670642998146766838315216031204958906362527023258344720302" }}, + {{ "7.59375", "3.755592314437586774843968169016218401146579356484719112952387050721790775719524338750656820475167322" }}, + {{ "7.625", "4.290567124941375634141691032410770755182292184491365711713765284134592087921445364428118108025228059" }}, + {{ "7.65625", "4.991276730757292357917427430609014256293569739250152073504758948209194194425629988371488577185989884" }}, + {{ "7.6875", "5.9510718925579227833281678276540391546652969268664831508775318977823975271243707799244732578159289" }}, + {{ "7.71875", "7.349587230185289251288167334999299680627536804325241700547934306594013397091284138506685042660382893" }}, + {{ "7.75", "9.582397403456211211397313849974932847186773522851876679318331037683816539880381009086487008735246101" }}, + {{ "7.78125", "13.72492306901017608779850845108579464520662673186624419937919970195919428249551440291202224739747059" }}, + {{ "7.8125", "24.09322543772519084215097143980037097594901385135011887012038200799428585198794379628997732285582328" }}, + {{ "7.84375", "97.73268930511967729279698949083284985794762903146492273796908122393941623833579266193628175149777252" }}, + {{ "7.875", "-47.57043136522765090736927872199715977332175052521738553413789183297556632881030788665564177584345509" }}, + {{ "7.90625", "-19.11460505409424788533123395282424237931209756369617281068252559403871558997768678144456749005346186" }}, + {{ "7.9375", "-11.94556191307435573940630678240021478719574633441063345522218692801937432207824662871635357235633214" }}, + {{ "7.96875", "-8.674912622365588398920385347547421582720453172032529527100491584226967033946983107374195473719464544" }}, + {{ "8", "-6.799711455220378699925262759608633364881412661473712848121891484119304982720857546088989511220313601" }}, + {{ "8.03125", "-5.581950808689684669549294209348398629337304002995630540331278821921778288507014685935916701606576575" }}, + {{ "8.0625", "-4.726032195156837427410372612416284237028321048638455837876262548466898310633589798461547191163836986" }}, + {{ "8.09375", "-4.090461187975555242897409987452358342061343516721018283559611963305885456193756951211377465919516297" }}, + {{ "8.125", "-3.599001897974260972151248247566727216299014591900000335282979733754229851045581086180509810930082767" }}, + {{ "8.15625", "-3.206943184854794792051938572955176223102804950834430935020353335808782541779058955201736266932317623" }}, + {{ "8.1875", "-2.886329592416760158849088002905458575851623094189615497250550481681316568867901585210424096370674517" }}, + {{ "8.21875", "-2.618783945156319374614290552008768448544289531418583013216952580114253625700948540561589098351543348" }}, + {{ "8.25", "-2.391728174447109499408796092049518207948088283366738019362364536579358984891061627461448588900266354" }}, + {{ "8.28125", "-2.196262571237231366422169733787602194377870425422442983742466664711276453593062387209663908411122531" }}, + {{ "8.3125", "-2.025912262702788461190762240682190168816613310552683831653429045356666462021227127736084042613847923" }}, + {{ "8.34375", "-1.875853575963005310284960792984729880727224645450131943927210730483841090952411053279594957173517387" }}, + {{ "8.375", "-1.74241880761627240539700340437602803932808901813845968268891377391077356174950266498464542879686652" }}, + {{ "8.40625", "-1.622769124048113033597644536164719722449235338830292053581380926565132897863391794369515824501033615" }}, + {{ "8.4375", "-1.514672563181530134110926429438194143845293739750523302549165608155316405124742878421871789886842147" }}, + {{ "8.46875", "-1.416349739641873214089748540260482127074454913435673678582846741597865860350934848935327297727726336" }}, + {{ "8.5", "-1.326364327785606923837177509628989183019847616858933039728626565320594601352898256466729337047543442" }}, + {{ "8.53125", "-1.243543859514378322699255610900405730249411506966951588519354941299030591219071989214839064576899506" }}, + {{ "8.5625", "-1.166921477042600182902656425322990210134485019242760863805503078706720819497128002394896106356209544" }}, + {{ "8.59375", "-1.095692443843841888393214442111438580869887527193049760552789795233066505667689248095554577112371625" }}, + {{ "8.625", "-1.029181226242794530622671562005776602295969084821805226400002870767989174122034536280082461534287795" }}, + {{ "8.65625", "-0.9668162629797675117200288525867759956705289684684092618655305272884560415249588622588640534660859208" }}, + {{ "8.6875", "-0.9081104046373177832576347663891532295331575111187881417687389316634049160994876797510769206182893432" }}, + {{ "8.71875", "-0.8526455881926773939956486059670750827771160223765816890633669305249823793389660138647216198961396045" }}, + {{ "8.75", "-0.8000607122131663748996935033554250873516322431753295881939448427095672520914736920285067785494755945" }}, + {{ "8.78125", "-0.7500419570576314664068876238355166376078921127752475362685197014336164568978380363973382424380027378" }}, + {{ "8.8125", "-0.7023149914660190721137439943663886714896255005161995584377885528996116609571672651781263426423264383" }}, + {{ "8.84375", "-0.6566386479456336287953742502996364274330999062289317807304964691314686325574451710087769117377447232" }}, + {{ "8.875", "-0.6127997515327654285376783646363991279819055057055158641281938301880811035156798875165049539694804864" }}, + {{ "8.90625", "-0.5706088613603129182915651449940477497513792905530365057563881633464714239146849295760180740616051507" }}, + {{ "8.9375", "-0.529896739873168003806242065594283411489762262385879653776325422716635759568492302090915293632301029" }}, + {{ "8.96875", "-0.4905114059515517049978410600006085544703557897386518199219966407731976599471950962402695227799723485" }}, + {{ "9", "-0.4523156594418098405903708757987855343087169256619843288072463344895615552699928891423222740611696987" }}, + {{ "9.03125", "-0.4151849883541607117552210974950947708368354992200219503945689498048994961045141832240492234717107402" }}, + {{ "9.0625", "-0.3790057881989822857530457874776947516302198077664862408128815699029163107706671425087481058924528226" }}, + {{ "9.09375", "-0.3436738369929040836550521796260295565231979408984456062837271050291411394204206333260572683795806063" }}, + {{ "9.125", "-0.3090929803907614767471346771315481283472474354946281905565967857578879461207205702332049986857635056" }}, + {{ "9.15625", "-0.2751739899376987485248300510983424723605373451217689431344224438486165931202115441514245211478398115" }}, + {{ "9.1875", "-0.2418335641420615678638155264698574025131647248333694816193249713183100110082265076470052022707012095" }}, + {{ "9.21875", "-0.2089934473583106794872121428783074116994340488341375724854578952783525682316496422613143306038638671" }}, + {{ "9.25", "-0.1765796456511299761112751840598406521389487242985432214413528930195762314982591148356765022144220392" }}, + {{ "9.28125", "-0.144521722122150591814619269577170465800891448238859437753351534510505894724788264050561053752147101" }}, + {{ "9.3125", "-0.1127521567973819422597203631074129348120757432615503831725905368424112610292538623181492998345439551" }}, + {{ "9.34375", "-0.08120575823178342176032872038448411443172784451696952348584885928982452335749552547386985037617069992" }}, + {{ "9.375", "-0.0498191155899860392003104787951054631853528180570175470879940653716436714322811615959161544657494618" }}, + {{ "9.40625", "-0.01853008118625405320915271202115144102822290582324439033642733950763784110773883754760179758258022532" }}, + {{ "9.4375", "0.01272272563027105977935573889462983744829956962204063464126832673322950722546841176709360279348538747" }}, + {{ "9.46875", "0.04400040173584953885682440835958114627885199630660893827828903912727543614728912707303196060753625141" }}, + {{ "9.5", "0.07536423875739405740654014205323665789342966267450384287846707728875924157814476147945907817392192786" }}, + {{ "9.53125", "0.1068762048461025163674352287858142449224256724379234993543813605972685100190359293029737215855453465" }}, + {{ "9.5625", "0.1385994377761661718602480104778901941178589868631124656851160671189176086579048746331765092114253163" }}, + {{ "9.59375", "0.1705987577719601866335639057437200427987763331813918550294340474134857881430332967127222805799022305" }}, + {{ "9.625", "0.2029412090417411123603662227278784038776298381618810811646084653751029723759416476460088872408054991" }}, + {{ "9.65625", "0.2356966398441474632357392833080328068352054698543206659897268100728097017667724684606559049124154157" }}, + {{ "9.6875", "0.268938332074403309291166325486527607211725274017137932139784676368590535825858340593417854926297648" }}, + {{ "9.71875", "0.3027436928841933821970886411755473788376234496119460628913545818204169198969541686968930178216130025" }}, + {{ "9.75", "0.3371950228159297335621484819773554194812863370480952763499236064163820830033268339692324715894157813" }}, + {{ "9.78125", "0.3723803774359345699506506000690612357176932379964207743390433297005778841484733220050565284302113607" }}, + {{ "9.8125", "0.4083945426204256871181400863951603330453056915705065091908373104020696107020950522244595815242992" }}, + {{ "9.84375", "0.4453401476523343154827952361952568691359033281221121303793343966901885521315031273219697042193257942" }}, + {{ "9.875", "0.4833289453490298299990038076226424305503958067355696981733291906588949898848660168661363237230401676" }}, + {{ "9.90625", "0.5224832948561672053074357426518017813969502851835052528668887798173320745102979706674984553747785107" }}, + {{ "9.9375", "0.5629378909036186388354128640753191217895638800506841967942363059454826038558876839732857927717227769" }}, + {{ "9.96875", "0.6048417937509008993401606503437317082375426212574423350794174057182764889826011397690814642006452007" }}, + {{ "10", "0.6483608274590866712591249330098086768168743429837249756336279673958556003746239008717172062971522862" }}, + {{ "10.03125", "0.6936804314743542712398847790886887683057558913351293442530262309817850224201884209136086813403394689" }}, + {{ "10.0625", "0.7410090731101333158449425961247175839017373828496178608167740610459452518219259199024083200316084101" }}, + {{ "10.09375", "0.7905823581871925973468103245168030277845433796367670128316098222165598426689171297882306893568062531" }}, + {{ "10.125", "0.8426680163689236497241316220032744251657095955743734411730267063148126128540903336099720150350195161" }}, + {{ "10.15625", "0.8975719901861101829801016952033465293839624897512338971033212391126217276476390113488747550991133784" }}, + {{ "10.1875", "0.9556459274758633915064588099748061258315512098776637126437164255246444193412583209025710708854064641" }}, + {{ "10.21875", "1.017296473311965646505591388794303117791831049823203228782533350726187433458132860834038283268836837" }}, + {{ "10.25", "1.082996890215945275135930985916637983213229101767681562664207604721345006616414244816945101012068962" }}, + {{ "10.28125", "1.153301720414501166084164165377670663086784905305525053523750216145961391216299317767459210812275763" }}, + {{ "10.3125", "1.228865465058231603544476514726969780448778330773071834149679410133713041325810373844792660869193974" }}, + {{ "10.34375", "1.310466629156747359552320115718026861262813059499884349607868463460206624928464716803324337065850131" }}, + {{ "10.375", "1.399039024262115717131604647733708995170160567832938194238903453989697561972061091597355404503662754" }}, + {{ "10.40625", "1.49571302349195916111981867105861656396166182988283681852423319036111614206596318006249059781485835" }}, + {{ "10.4375", "1.601870670512520509271426433671643695090231605946938642547694243879213679699085414650549829075718711" }}, + {{ "10.46875", "1.719220395521651499721208794808194478968865549194510942718291121399341439043920644901884496910696737" }}, + {{ "10.5", "1.849899993421927279907583573513910565419553685959044018741794327382830123593588324994882461965573398" }}, + {{ "10.53125", "1.996621179417850643664093294309064624983038139124591902589207528735600835709855269195187933895652101" }}, + {{ "10.5625", "2.162876723677546330469959787105963848827689014945066557592989408260164364548287694286197662196239537" }}, + {{ "10.59375", "2.3532442330793790868766441879841993750130572630209439743618231460831573709883106394866434440837641" }}, + {{ "10.625", "2.573843631271674362526537866893410697197766596999920083319154750577002457483161716337803596844925106" }}, + {{ "10.65625", "2.833047421190427952095570132770964879184235914846751261896726812931990128759669900544999535061769791" }}, + {{ "10.6875", "3.142623220176844496098570587446827716363816198180813628746017544330426339542323699691642256030772053" }}, + {{ "10.71875", "3.519650155321593637030342256680131753850278370827948246193900683195030354927519452141570420409057437" }}, + {{ "10.75", "3.989898450288877172272878730129464264004901452428968181149190336688176169073686050444717716156454253" }}, + {{ "10.78125", "4.594165609870243515783279467995060486532380531283432068617070247011706442921648714627407953983920726" }}, + {{ "10.8125", "5.401101953070107889048337369479695723086844105989269027204537226522869955593746957868263836003479647" }}, + {{ "10.84375", "6.535875415517406207251199308597767679104658091064327476058394143828942638073632382427758536504917985" }}, + {{ "10.875", "8.253411766339305537723460693388679535974907155823982004597806731192500887738499761977958603336992426" }}, + {{ "10.90625", "11.16537284500979684723686544686940420453225367789354062936636940962591367864691678374577954865828186" }}, + {{ "10.9375", "17.1999620041711094734838984205883317149769089588687370821690524219299315809266573264745104659869829" }}, + {{ "10.96875", "37.27070620721793879698276661020742630154681506539144657714408230209752760393928366701053772541231071" }}, + {{ "11", "-225.9508464541951420257954832034531539516575098851311946310945881123661134104031654779989090875181672" }}, + {{ "11.03125", "-28.01838123473997016830887833476199550560697066011986939559933525309909705318537405182199378012840027" }}, + {{ "11.0625", "-14.91962506867234581945151895985710289930225918712794589354339983163930894702818997439864076091931126" }}, + {{ "11.09375", "-10.15307233756673521728139815893864848321827456537331024001764086854554203725293661816927668294489745" }}, + {{ "11.125", "-7.683249828520493578856827081745572284486853920128557099054138395954224416767780846216824234128741871" }}, + {{ "11.15625", "-6.170065007339837672004969274368706522165797321914087418607341946608032746141308987068347258026539261" }}, + {{ "11.1875", "-5.146216397928971013498356330072590228022047015189051411856482418633925739244947714746552179251733944" }}, + {{ "11.21875", "-4.406134215367990783634732996136714284665546485639321948525683144032506137127272195504713779988841399" }}, + {{ "11.25", "-3.845243526046256589195292015214843119217023542577367989034898325348687250589462590349993156554307721" }}, + {{ "11.28125", "-3.404725196340913894767892653680241020178288686778598191582702368768260415894176917496336011269246961" }}, + {{ "11.3125", "-3.048957435167265586183006322737827462691340358802500561060757089057213237102895081676386924312658609" }}, + {{ "11.34375", "-2.755105539085522466956356685286240136460553349428076133380205505661678601069631697225730693586354901" }}, + {{ "11.375", "-2.507856046343293846165268336837981024254374791359792671451310995149841786950224129840033693800933455" }}, + {{ "11.40625", "-2.296555085357014688557714000971300925194148838031073606034513705752180239656706450912207637184212202" }}, + {{ "11.4375", "-2.113560858723099424307258719446955475134681339177645144130883477669849838830392714536871823793018366" }}, + {{ "11.46875", "-1.953248965442351814769641861822757418968218808226145477990020040801933787597505710461744957513141637" }}, + {{ "11.5", "-1.811387450326824859772397320474032833639713335926721521705076560469479148263546424971811321096648723" }}, + {{ "11.53125", "-1.684730597525019137697751820797269016453098562968854704274935631922618587469362028272636692210544871" }}, + {{ "11.5625", "-1.570747064811472615228088301480862011854346986220267355439332676174065617757164643849543074172144195" }}, + {{ "11.59375", "-1.467433230574720919411941987695161181959171583863783447843463212366085434611122065381627004242638947" }}, + {{ "11.625", "-1.373182138457896453349468046455100980035443259553659899722906361390876088856423969181083376455705666" }}, + {{ "11.65625", "-1.286689630920366616376314221177221139006716016538511655589760746532540573609680625603641074608188434" }}, + {{ "11.6875", "-1.206885914221201720054271911345572193315238450358663840449617121968073512366326525649980278803416278" }}, + {{ "11.71875", "-1.132884861825656481798873135046969210301345541577298019300751660619960162890235612177970957925478595" }}, + {{ "11.75", "-1.063945912486004409710559363045985530861938320222047288703751234746510874929602501339045816423036172" }}, + {{ "11.78125", "-0.9994450559333915167440624304322053019403928948191033206551515159313846021422418864273459645373449009" }}, + {{ "11.8125", "-0.9388524723222944773205643428254523492068640072627707382490811032852295370278108292005146916272238994" }}, + {{ "11.84375", "-0.881715108900528303919177723946502416645736801861050134491985441499235913287446780705353461545417442" }}, + {{ "11.875", "-0.8276429652929236471146892695710241706925495072977152657326004944101623406458452837545349486881138268" }}, + {{ "11.90625", "-0.7762981960095720820932228114020179373213795483270746275212139165301756520252573166217954465331159458" }}, + {{ "11.9375", "-0.7273863753138267917778418153001732955258816548283145725251801363629114248343367970028832122142992284" }}, + {{ "11.96875", "-0.6806494377457210277597470928336025589584620324058462321470850608946457200573674297093242265437051282" }}, + {{ "12", "-0.6358599286615807924609379429390076061509587586686860914514606814656551214484123291399643068894751555" }}, + {{ "12.03125", "-0.5928162873294508906897144974924364212100987037074180867630829726623330818215300743873013630492129075" }}, + {{ "12.0625", "-0.5513389500434250704976885869765975030435162971228425993732710884431519725994082993307502135366704687" }}, + {{ "12.09375", "-0.5112671090040856778211886692327830312529713244160725823950417285454010972749346501560988873183882094" }}, + {{ "12.125", "-0.472455998959126666328373026314261347130558625459848565935809588092219192527888607849005967299526205" }}, + {{ "12.15625", "-0.4347746110466813389220145482909141465629503223075144609806539759358566301078783883593960376790796208" }}, + {{ "12.1875", "-0.3981037542382981122358374348325646108510087325306228562334315140437947730049798142715674391074029588" }}, + {{ "12.21875", "-0.3623344008952777173267729097645609415931859827734307762367947830110639831467043405387353622176899024" }}, + {{ "12.25", "-0.3273662654331959909797507119051924955282853934206185144087221653583658953364484322496982215172064596" }}, + {{ "12.28125", "-0.2931065748149348906573126400315634011327627839945547849105543140713203189089283254450491988430709458" }}, + {{ "12.3125", "-0.2594689972120933396662267471796226223140842016040887149108653318448105627021634377488137220685751418" }}, + {{ "12.34375", "-0.2263727011714726746425617255174464360665584672063083345910005855017649693977414015628137560181413471" }}, + {{ "12.375", "-0.1937415223592955920421472499371716132396126974936842056246045191659136204224066400221303821918510103" }}, + {{ "12.40625", "-0.1615032187034938758288345646836288312549849485871893783750506125037934982810946747034471565118071181" }}, + {{ "12.4375", "-0.1295887977200466002615144930375243133915724779506460096421464176334192279649808190617654665646655393" }}, + {{ "12.46875", "-0.09793190214949804406939767223801097423536917158984066549241688209747906679339832186909184479038423885" }}, + {{ "12.5", "-0.06646824186327419610199266949441387194390610792357612079517505380578030434009894147743014400122005453" }}, + {{ "12.53125", "-0.03513506141616282076636047393093268566965509833708523530838721391339373252314877573835767237228949322" }}, + {{ "12.5625", "-0.003870633688692445796420680716701608075985971581256241161345780831826430572573689071744247468488929075" }}, + {{ "12.59375", "0.02738622916941998236655243276631287278486472025157424329703232697741123275406245628528750156873296529" }}, + {{ "12.625", "0.05869665578128338112635128913606850911677921227526205464651894469274626817414600063862113806671147531" }}, + {{ "12.65625", "0.09012219459725165729474121609816933257302657281344601700769732387220992191083677289387048548334265912" }}, + {{ "12.6875", "0.1217252999603408610668897042413571531127645503736599822403036205555496676066474076056000689949341066" }}, + {{ "12.71875", "0.1535698333828775342772949638706552097777256705040011551078273258533143177119249497623834514512966756" }}, + {{ "12.75", "0.1857215886751401902594186441708939448272141506734588329272148156845153012668419405756499880982943312" }}, + {{ "12.78125", "0.2182488502657797346752690950871572837813792443000041521932413723748578742375061893600646885986149118" }}, + {{ "12.8125", "0.2512229950428828425999138094132092852018197118941615412720196242900796512859843472371170313836583775" }}, + {{ "12.84375", "0.2847191493692259054394416502657415422614131291273802036428533121457701035912610846112501083132620008" }}, + {{ "12.875", "0.3188169146481101964165914224483354040480603343474688683709071564169780696806924149291320418944830542" }}, + {{ "12.90625", "0.3536011770209831976646321735648611242564793780159081807119024532891168112397727872069370118132852613" }}, + {{ "12.9375", "0.389163019575800390066324389631248715515481435421443727622672043630746566664120384677948936473787333" }}, + {{ "12.96875", "0.4256007589819842824595519481972026675555296385735056063290277948532474177383987445148843331908874667" }}, + {{ "13", "0.4630211329364895955117902835081206683532120959519440470950206693928302579327807145125758116501924079" }}, + {{ "13.03125", "0.5015406704601738993466207755375547536965260852964643732753893793547109382261801451895601761930463122" }}, + {{ "13.0625", "0.5412872842615681585626378992160244527886510964571032692368478641312818490839188830849928560962861538" }}, + {{ "13.09375", "0.5824021335357886328662589223215248727421699777193264549116653046243519880397055116969487363618353957" }}, + {{ "13.125", "0.6250418172930577232327055575810817395750497037126950514585195397519699819130820731538599564259401139" }}, + {{ "13.15625", "0.6693809734298055686754246761212833674742679018564325405072602539903766997859347462285344333571366362" }}, + {{ "13.1875", "0.7156153783773706463324211230116191534127258818669295732823217991324981875804470761472072117982861964" }}, + {{ "13.21875", "0.7639656678174816067986696149135126827704120185065555912507382354963651332883430075609034401555571502" }}, + {{ "13.25", "0.8146818327614344736464451806034453710444224291621571573625236805118070729970340362557654528804594448" }}, + {{ "13.28125", "0.8680486902251570873258425734584921956065820604675624643643164481487468794096033758920520511975882962" }}, + {{ "13.3125", "0.9243925880092635749600582006440809362226783655074073519865821148035556209179629462013383469424274175" }}, + {{ "13.34375", "0.984089684751991735962930471741445607987192320278600727525448404432994693600540790050738561865588772" }}, + {{ "13.375", "1.04757625822842897028900134354672689006793126569323519874122370449523706721491998653522405351511" }}, + {{ "13.40625", "1.115361649708918497565229580465214098442269312226313131576538895853120727413355048723361997440716611" }}, + {{ "13.4375", "1.188044669282090096413968423531415025467187597047077575491037309801518019505454161493737933958668965" }}, + {{ "13.46875", "1.266334595496805761839284321117713547689424188079416196364317291844437171872585239983180116380091394" }}, + {{ "13.5", "1.351078347287010480371085577712699470101212829099407611657174914155576868564657173832374341089513584" }}, + {{ "13.53125", "1.443296057137394170028536177718664041051292527024487177527337760724543655637891131854085251072201818" }}, + {{ "13.5625", "1.544228244055125768572769325179666059641117940456933228593668266762756226316757718141030898582889678" }}, + {{ "13.59375", "1.65539925635608625536146268504299540984757874423396346584219270902415141849546774423536235044651061" }}, + {{ "13.625", "1.778703933748487611100295794480392286774372855795510955005500225382241572963111907877924106343034439" }}, + {{ "13.65625", "1.916528050760659646742064707886848214342582893475968412683323141359371632373241621750396872855231387" }}, + {{ "13.6875", "2.071918975654530318165994049833557729201414960634819277207514404216213840009455116234485076356302166" }}, + {{ "13.71875", "2.248832798150414958768559692131859458258869348641929756045263587943996112471489439485863476093034658" }}, + {{ "13.75", "2.452501131436276534259505261160229408535827308333544989748716942417182101185885609613251793631088723" }}, + {{ "13.78125", "2.689991141885544485574819071146851902487462547699495662222675009146133600868249015967786252574495347" }}, + {{ "13.8125", "2.971088997454883061146937345921981294715821069297105784485484470539822403438727250351950923586461683" }}, + {{ "13.84375", "3.309747852278236334086030022253642441335045150382837946015733966046635972988597769925369044448793434" }}, + {{ "13.875", "3.726571412380592611642200928513525816649689030739311675986112325390668863787780356510815096395312152" }}, + {{ "13.90625", "4.253314099623669334835259848593744934346239237141072606237802004691075608138259425654524049734148683" }}, + {{ "13.9375", "4.941607147834976432334070015221138910450692007921150173618524899066416996751652602822476062787651509" }}, + {{ "13.96875", "5.881399525150031955799636707531603412059246766703476508448423108137501182284498677930575806202198028" }}, + {{ "14", "7.244606616094805116868776904419943839744730261240134752545587919443539234559937291680749763590851956" }}, + {{ "14.03125", "9.406028188605279696133223875198323737712453281000019998207973537233195589286463672078393783342949057" }}, + {{ "14.0625", "13.36790967265482265511197119971831749461310263946778620293662813338523575832270133240885318460296722" }}, + {{ "14.09375", "23.0180098105772480411418077991835591801343058014965291845911306402355660736744079654039102037142972" }}, + {{ "14.125", "82.18587088008837479889498738727608856213126524631858084352266182200806013924238364295643998983071042" }}, + {{ "14.15625", "-52.39613928846073424250555787725052081495348867793023995281290229927733884543365803704289494278819236" }}, + {{ "14.1875", "-19.85087749437963381473636677142019044036915990708056158011806608744982156130940528545579140382954901" }}, + {{ "14.21875", "-12.23024032878110918179097238079573616977352169397336130087278904329232109578073694396971060087189843" }}, + {{ "14.25", "-8.825007825823643194479070661167279551172813025945214108644920017576189426949178857879125100439566237" }}, + {{ "14.28125", "-6.892346926954325909059194856822673062063097995636142714599547668355292064875194893124728097012275365" }}, + {{ "14.3125", "-5.644866498825540128381929944705578552248933555730964244899773528736917184084590171390597212873718595" }}, + {{ "14.34375", "-4.771610252795610046024685797665514766422880378783577882983742818079026166693261845053770481989424557" }}, + {{ "14.375", "-4.125051680440956814255997242162117938555651270642110578618995113301257483035180159821309310658332941" }}, + {{ "14.40625", "-3.626194314229776036712561256911661725676439848577743170654748551410882288678506147976699754338337632" }}, + {{ "14.4375", "-3.228918544653384166822369480885301355908586468628448310353628937744136710166892378083809771029038072" }}, + {{ "14.46875", "-2.904489208401961365438740405970863838028715766433251544998958231462070708355920879083964796103033733" }}, + {{ "14.5", "-2.634069132503832833409607035052858278935807513368801311481801280408668028920599740332367971681453643" }}, + {{ "14.53125", "-2.404794639925577553244012746285864594559572350297129379452932406519481483010765023196033751578709703" }}, + {{ "14.5625", "-2.207581089523679545128355853946391835592464237094323506839360879131859583353800754571132350944473674" }}, + {{ "14.59375", "-2.035829586659772321235017007716845648434117124540496962900856683971781311984497273615528750368081422" }}, + {{ "14.625", "-1.884630768865435904935595378906947231717012177189752377379403964925875302521199447518722408719775981" }}, + {{ "14.65625", "-1.750256190835124208623312849116061326812165846025415986783560739453729962659158203940996884358758139" }}, + {{ "14.6875", "-1.629822991609989147184189043054819627629510818289435539398133590083260226275976603564527843030512624" }}, + {{ "14.71875", "-1.521066667289361457373930052890176846963182405346389200320517277799503677666772192617687500257521097" }}, + {{ "14.75", "-1.42218336083774197380789085745137021789867848279597800468450871698744869740438289092755542692570482" }}, + {{ "14.78125", "-1.331718058572613129017722401996663023341875099157808098995252549045562547044521935057437210333349552" }}, + {{ "14.8125", "-1.248483823169844883793467308858957913772012915051151771810074084965259104516379708093866536649015936" }}, + {{ "14.84375", "-1.171502454280969620050113939757468091964527953537892858826299161314598145955301346129774398985079725" }}, + {{ "14.875", "-1.09996022360423379094065298284739111500559223495806048377446355428125902586706149601540328954397664" }}, + {{ "14.90625", "-1.033174396383465269461739738697259215672589493553897443441659340076220701053186730617856132398548093" }}, + {{ "14.9375", "-0.9705675907155131163149460322607739770705545946870992276893226926978460501228871025636381103213358614" }}, + {{ "14.96875", "-0.9116479124475490508064737825953723368462225788875404013990634500526165327350899245784037598875471869" }}, + {{ "15", "-0.8559934009085187640261927782380296049897864414742962979687446281783012594486541122545103129259226012" }}, + {{ "15.03125", "-0.8032397302332296612432159755337281904284459733163994877022298441144059785603187789136637043263789466" }}, + {{ "15.0625", "-0.7530703960754939484978446924032015414437125508200990314934869704250553438069278960228507610120908637" }}, + {{ "15.09375", "-0.7052088187318415299725928408540094093554358958059088325375638362095004704432693353838375709463129551" }}, + {{ "15.125", "-0.659411937622644225218300893404169827076548649885412227383887901950221923526355502978543776575055119" }}, + {{ "15.15625", "-0.6154649762727536414801474029122625793755198617269250343988631456453788448149731706979351529235579577" }}, + {{ "15.1875", "-0.5731771332183040948793178896118867037269598773610412277642977614409075169432893108977656087532808068" }}, + {{ "15.21875", "-0.5323780107028691176788965668440942781647156607765742951342412648358988559400799809724920990286528734" }}, + {{ "15.25", "-0.4929146351866012621666401573415074523464609163340854530825224584649245974424596583470196176643838565" }}, + {{ "15.28125", "-0.4546489554738299415350063572461193751006928326854122963028434583535719327916356408447934270192962049" }}, + {{ "15.3125", "-0.4174557284251085623680148206370333657407709127949181945517726979253617292255491330234726669774559159" }}, + {{ "15.34375", "-0.3812207207302419203446046603506711987787377766806738457878506795815713138223264722913354548269137032" }}, + {{ "15.375", "-0.3458391695028422582485004568448026536356203654713446806415710694635885346246660520826948870993463705" }}, + {{ "15.40625", "-0.311214455551825073642663079591570618837743590849903018274057606911872122304533000910107606645650336" }}, + {{ "15.4375", "-0.2772569518534830079599506190692912755868921271423525814120233867695893487373304945292237740353757468" }}, + {{ "15.46875", "-0.2438830165543173054192587099181568413614402066070223778896735213919894343566763962867244846621486138" }}, + {{ "15.5", "-0.2110141052012553133863173741408514435037061655011970687100846880180438182550528565062101594891245018" }}, + {{ "15.53125", "-0.1785759811388596991279739233477573236616687666102227187311862264495771634608666297275574790232136991" }}, + {{ "15.5625", "-0.1464980063716879847555275878278898667317766571375499828106145375100216949704230935552550931052323183" }}, + {{ "15.59375", "-0.1147124978452713735943481847220917786442201384229215777788278473922030662630912256721375261600875605" }}, + }}; + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + T val = tan(T(data[k][0])); + T e = relative_error(val, T(data[k][1])); + unsigned err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + val = tan(-T(data[k][0])); + e = relative_error(val, T(-T(data[k][1]))); + err = e.template convert_to(); + if(err > max_err) + { + max_err = err; + } + } + std::cout << "Max error was: " << max_err << std::endl; +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); + // Check low multiprecision digit counts. + test > >(); + test > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_tanh.cpp b/test/test_tanh.cpp new file mode 100644 index 00000000..04d49f0a --- /dev/null +++ b/test/test_tanh.cpp @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2002 - 2011. +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ +// +// This work is based on an earlier work: +// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", +// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "test.hpp" + +#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) +# define TEST_MPF_50 +//# define TEST_MPF +# define TEST_BACKEND +# define TEST_CPP_DEC_FLOAT + +#ifdef _MSC_VER +#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") +#endif +#ifdef __GNUC__ +#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" +#endif + +#endif + +#if defined(TEST_MPF_50) +#include +#endif +#if defined(TEST_MPFR_50) +#include +#endif +#ifdef TEST_BACKEND +#include +#endif +#ifdef TEST_CPP_DEC_FLOAT +#include +#endif + +template +void test() +{ + std::cout << "Testing type: " << typeid(T).name() << std::endl; + static const boost::array data = + {{ + "0.32137338579537729992840434899278935725496267444911714908205287462634251052210833615032073534299473485492692600156322137421801432333125051088723502425037485776412801577568405892077585206768190530859883094571475323319480739773193974206966728764224286661945738178210577326172938196062277314761537881936346874075881338768208490193827960565412814349738654540520356903367084438822830345189856017860672463017", + "0.98628073997374759901559180515206275902189609982907214282364143439537215491113710345866034807991101303183938339561499559327886956280789743287824488269072297413440935381715378233031399015496124706604318545539544610760151756970229801074280545428642122005982857974921606264103186878499260552388713716032507770319550435738767597150644370033277228635793175246197730488375240713357827246166262087899961098648", + "0.99999659728082161113542951278514830809677661658635225532792520501703544628367875293677270218317428676793098034276042396396797568103263882451732810190507733063467333056356770774002596898762991629653041854653269824642873291146068535300466473399592751219449187768646625229500705182676930009096545254478199838990703077597971823456671241141900968900216742636822174010867343154474773040184900973368250708724", + "0.9999999999846483268200051609594321550129159997920576480976206867496512752486590660437091205989616108531910897733432934135954788151766561209164605337537937873588006552145390152387235783207736999759875845070169747521389728857476525437483543080651125798739562649414879487621858466223255239845627205850217328574865852922872737234283038190096982410137471391847466112651349436875974689271288261759782261321", + "0.9999999999999999987314527242099750648171958211319474558707792311593804963057878814487720997303512134007272111464990650500302215773762906820778949397525329109311974741708703536680512747226155618703318739024344621256722269608969415280035337052044425138281821760268269187377517243951584969175035549994883451471918693502477485385682884154959809285569290940740978684264145737164182111806308430952867505356", + "0.9999999999999999999999999980800953069847308586840237590563929855339557065536765765234844240789584487443451033349994294426525006157530320529970966048109743850154174651033567146346966529198814047607015842020039899630884318521543225160212193994911746894335846264878066530266737005606770102869237101848445559941638381625615207320468184414917265299980278164193202897754476112968080358662232635784904263624", + "0.9999999999999999999999999999999999999467800140220866754762922747687784133233134010432889959570821554455247528344437918197518545105332713456859236726383195243056599177018396579766073961540714510399202497404647103138524118065391185503678895059096790300665805648569647351935897874460587855127436472608470703384261586158923066272124216158518232588330799027603391275039552776308636189531809031683723259525", + "0.9999999999999999999999999999999999999999999999999729795912960133359928587562229512337339217831178574875626619226954752643039860388090399659478676726654102118545764943682017611574275691203710439707807193180604656837503862242700430179591666329131728631752773789406064618682879167351725013888294859467540832310795515139677375807407622028485242969471516812171475098378942187864794497220152019202351747432", + "0.9999999999999999999999999999999999999999999999999999999999999997487354938310440650220692519525261552411539996830587326435051159231522052011310872619940247463640019105467860778515384738650636054646551611609757125760437266415865214306396520500343113189907306851418957620080971645943305760132385139924583154317156560414548076370893360020924960120441059315311380109752919823616149973862196846266297710225", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999572050575304159358359221596743379014313563214857593401545331495211888415913558896516895286943572966865708195832339959764445194449615969154689769557903166971249521898883489362426386924297872088925852892350150865941427355319827260914834268754732102528105919811851193667193380541054520023003326858641189063542651960743457613", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998665016733514821204959171836698281165918083005790816030823236096080522860514417075411055633676502699904415882389102672678124683084429720879962355892225321369091298491658349178472270952759208443767848312111069127329160464884932271685986610697222434145553035947750809388321614695213754318979469071722942883", + "0.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999992372516628147584832950728021842198359205201519966391076994594773600474674435473005118571751514446148292787696117866094991476340344341061706866751156257825144909115117822189019766805825304055482958970512463798453229341693148012213183553546720540880444569824125592343803193018989122964", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999920180539244323143459416025663362517256166793900312667214543096238752838226369161775531456005541374878274529461511286842988937830155704737448202558382612829022464635400289328916240002670783433827234852858267621807568393874737879853500598862298495727481132883728328", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998470116425957155787153557938061034698436461173594805292722874130433614266475136267606498346730583487791266503943659174886554170377537630914770998114573340081594827150737005158607830579000912020838690230498119348251553312722575955142752845289", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999462931048083476382670449719737943481963930626760625326765703815392249622625483433043363664396638162612437367800102332819699131841317348173451308570776544874933173719394861336636728378134900422312720743996219523365098", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996546783689748726752364896615532860288057097437452774779386074906915819380531729493071959232887620213723607155628959529584572083388979892309086717786559916703004365603135284141639480887703759", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999593332381019647939423999969519583099837564321056588766269967853479478603122899456262904869063959564274215899007623362296377022418464303752396325625838280378647335", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999122842714667567128203355585346559126606029196080721845292399104475997315344844970601651757832506169948906646054332493537761143729664", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999965347272050374435790597917065458623422102880662825928396981295898014081371503733411536311258910851858", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999974926240515037403282500845454464621558236030794140169313830052413917", + "0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999667705192725716176070161727364499", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + "1.", + }}; + + T eg = static_cast("5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1"); + + unsigned max_err = 0; + for(unsigned k = 0; k < data.size(); k++) + { + const T x = eg + k; + T val = boost::multiprecision::tanh(x * x); + T e = relative_error(val, T(data[k])); + unsigned err = e.template convert_to(); + if(err > max_err) + max_err = err; + } + std::cout << "Max error was: " << max_err << std::endl; + BOOST_TEST(max_err < 100); +} + + +int main() +{ +#ifdef TEST_BACKEND + test >(); +#endif +#ifdef TEST_MPF_50 + test(); + test(); +#endif +#ifdef TEST_MPFR_50 + test(); + test(); +#endif +#ifdef TEST_CPP_DEC_FLOAT + test(); + test(); + // Some "peculiar" digit counts which stress our code: + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > >(); + test > > >(); + test > > >(); +#endif + return boost::report_errors(); +} + + + diff --git a/test/test_test.cpp b/test/test_test.cpp new file mode 100644 index 00000000..68a277f4 --- /dev/null +++ b/test/test_test.cpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ + +#ifdef _MSC_VER +# define _SCL_SECURE_NO_WARNINGS +#endif + +#include "test.hpp" +#include + +void proc_that_throws() +{ + throw std::runtime_error(""); +} + +int main() +{ + boost::multiprecision::cpp_dec_float_50 a1(1), a2(1), b(3), c(-2); + + BOOST_WARN(a1); + BOOST_WARN(a1 == b); + BOOST_CHECK(a1); + BOOST_CHECK(a1 == b); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + boost::multiprecision::cpp_dec_float_50 a_tol = a1 + a1 * 100 * std::numeric_limits::epsilon(); + boost::multiprecision::cpp_dec_float_50 tol = 100 * std::numeric_limits::epsilon(); + + BOOST_CHECK_CLOSE(a1, a_tol, tol * 102); // Passes + BOOST_WARN_CLOSE(a1, a_tol, tol * 98); // fails + BOOST_CHECK_CLOSE(a1, a_tol, tol * 98); // fails + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_CLOSE_FRACTION(a1, a_tol, tol * 1.02); // Passes + BOOST_WARN_CLOSE_FRACTION(a1, a_tol, tol * 0.98); // fails + BOOST_CHECK_CLOSE_FRACTION(a1, a_tol, tol * 0.98); // fails + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_EQUAL(a1, a2); + BOOST_WARN_EQUAL(a1, b); + BOOST_CHECK_EQUAL(a1, b); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_NE(a1, b); + BOOST_WARN_NE(a1, a2); + BOOST_CHECK_NE(a1, a2); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_GT(a1, c); + BOOST_WARN_GT(a1, a2); + BOOST_CHECK_GT(a1, a2); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_LT(a1, b); + BOOST_WARN_LT(a1, a2); + BOOST_CHECK_LT(a1, a2); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_GE(a1, a2); + BOOST_CHECK_GE(a1, c); + BOOST_WARN_GE(a1, b); + BOOST_CHECK_GE(a1, b); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_LE(a1, a2); + BOOST_CHECK_LE(a1, b); + BOOST_WARN_LE(a1, c); + BOOST_CHECK_LE(a1, c); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + BOOST_CHECK_THROW(proc_that_throws(), std::runtime_error); + BOOST_CHECK_THROW(a1+b+c, std::runtime_error); + BOOST_CHECK(boost::detail::test_errors() == 1); + --boost::detail::test_errors(); + + return boost::report_errors(); +} + diff --git a/test/ublas_interop/common/init.hpp b/test/ublas_interop/common/init.hpp new file mode 100644 index 00000000..a9691b4e --- /dev/null +++ b/test/ublas_interop/common/init.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2004 Michael Stevens + * Use, modification and distribution are subject to the + * Boost Software License, Version 1.0. (See accompanying file + * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +/* + * Default construct test when possible + */ + +template +struct default_construct +{ + static void test() {} +}; +template +struct default_construct > +{ + static void test () + { + VC default_constuct; + initialize_vector (default_constuct); + std::cout << "default construct = " << default_constuct << std::endl; + } +}; +template +struct default_construct > +{ + static void test () + { + MC default_constuct; + initialize_vector (default_constuct); + std::cout << "default construct = " << default_constuct << std::endl; + } +}; + +/* + * Initialise test values in vector/matrix + */ + +template +void initialize_vector (V &v) { + typename V::size_type size = v.size (); + for (typename V::size_type i = 0; i < size; ++ i) + v [i] = typename V::value_type ( i + 1.f ); +} + +template +void initialize_matrix_impl (M &m, ublas::packed_proxy_tag) { + typename M::size_type size1 = m.size1 (); +#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION + for (typename M::iterator1 i = m.begin1(); i != m.end1(); ++ i) + for (typename M::iterator2 j = i.begin(); j != i.end(); ++ j) + *j = typename M::value_type ( i.index1() * size1 + j.index2() + 1.f ); +#else + for (typename M::iterator1 i = m.begin1(); i != m.end1(); ++ i) + for (typename M::iterator2 j = ublas::begin (i, ublas::iterator1_tag ()); j != ublas::end (i, ublas::iterator1_tag ()); ++ j) + *j = typename M::value_type ( i.index1() * size1 + j.index2() + 1.f ); +#endif +} + +template +void initialize_matrix_impl (M &m, ublas::sparse_proxy_tag) { + typename M::size_type size1 = m.size1 (); + typename M::size_type size2 = m.size2 (); + for (typename M::size_type i = 0; i < size1; ++ i) + for (typename M::size_type j = 0; j < size2; ++ j) + m (i, j) = typename M::value_type (i * size1 + j + 1.f); +} + +template +void initialize_matrix (M &m) { + initialize_matrix_impl (m, typename M::storage_category()); +} + +template +void initialize_matrix (M &m, ublas::lower_tag) { + typename M::size_type size1 = m.size1 (); + typename M::size_type size2 = m.size2 (); + for (typename M::size_type i = 0; i < size1; ++ i) { + typename M::size_type j = 0; + for (; j <= i; ++ j) + m (i, j) = i * size1 + j + 1.f; + for (; j < size2; ++ j) + m (i, j) = 0.f; + } +} +template +void initialize_matrix (M &m, ublas::upper_tag) { + typename M::size_type size1 = m.size1 (); + typename M::size_type size2 = m.size2 (); + for (typename M::size_type i = 0; i < size1; ++ i) { + typename M::size_type j = 0; + for (; j < i; ++ j) + m (i, j) = 0.f; + for (; j < size2; ++ j) + m (i, j) = i * size1 + j + 1.f; + } +} diff --git a/test/ublas_interop/common/testhelper.hpp b/test/ublas_interop/common/testhelper.hpp new file mode 100644 index 00000000..4fbf9c4d --- /dev/null +++ b/test/ublas_interop/common/testhelper.hpp @@ -0,0 +1,74 @@ +// Copyright 2008 Gunter Winkler +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef _HPP_TESTHELPER_ +#define _HPP_TESTHELPER_ + +#include + +static unsigned _success_counter = 0; +static unsigned _fail_counter = 0; + +static inline +void assertTrue(const char* message, bool condition) { +#ifndef NOMESSAGES + std::cout << message; +#endif + if ( condition ) { + ++ _success_counter; + std::cout << "1\n"; // success + } else { + ++ _fail_counter; + std::cout << "0\n"; // failed + } +} + +template < class T > +void assertEquals(const char* message, T expected, T actual) { +#ifndef NOMESSAGES + std::cout << message; +#endif + if ( expected == actual ) { + ++ _success_counter; + std::cout << "1\n"; // success + } else { + #ifndef NOMESSAGES + std::cout << " expected " << expected << " actual " << actual << " "; + #endif + ++ _fail_counter; + std::cout << "0\n"; // failed + } +} + +static +std::pair getResults() { + return std::make_pair(_success_counter, _fail_counter); +} + +template < class M1, class M2 > +bool compare( const boost::numeric::ublas::matrix_expression & m1, + const boost::numeric::ublas::matrix_expression & m2 ) { + size_t size1 = (std::min)(m1().size1(), m2().size1()); + size_t size2 = (std::min)(m1().size2(), m2().size2()); + for (size_t i=0; i < size1; ++i) { + for (size_t j=0; j < size2; ++j) { + if ( m1()(i,j) != m2()(i,j) ) return false; + } + } + return true; +} + +template < class M1, class M2 > +bool compare( const boost::numeric::ublas::vector_expression & m1, + const boost::numeric::ublas::vector_expression & m2 ) { + size_t size = (std::min)(m1().size(), m2().size()); + for (size_t i=0; i < size; ++i) { + if ( m1()(i) != m2()(i) ) return false; + } + return true; +} + +#endif diff --git a/test/ublas_interop/test1.cpp b/test/ublas_interop/test1.cpp new file mode 100644 index 00000000..53de7901 --- /dev/null +++ b/test/ublas_interop/test1.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test1.hpp" + +int main () { + test_vector (); + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test1.hpp b/test/ublas_interop/test1.hpp new file mode 100644 index 00000000..b732c66e --- /dev/null +++ b/test/ublas_interop/test1.hpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST1_H +#define TEST1_H + +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +void test_vector (); +void test_matrix_vector (); +void test_matrix (); + + +#endif diff --git a/test/ublas_interop/test11.cpp b/test/ublas_interop/test11.cpp new file mode 100644 index 00000000..e874d65e --- /dev/null +++ b/test/ublas_interop/test11.cpp @@ -0,0 +1,265 @@ +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. + +#include "test1.hpp" + +// Test vector expression templates +template +struct test_my_vector { + typedef typename V::value_type value_type; + typedef typename V::size_type size_type; + typedef typename ublas::type_traits::real_type real_type; + + template + void test_container_with (VP &v1) const { + // Container type tests in addition to expression types + // Insert and erase + v1.insert_element (0, 55); + v1.erase_element (1); + v1.clear (); + } + + template + void test_expression_with (VP &v1, VP &v2, VP &v3) const { + // Expression type tests + value_type t; + size_type i; + real_type n; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_vector (v1); + initialize_vector (v2); + v1 = v2; + std::cout << "v1 = v2 = " << v1 << std::endl; + v1.assign_temporary (v2); + std::cout << "v1.assign_temporary (v2) = " << v1 << std::endl; + v1.swap (v2); + std::cout << "v1.swap (v2) = " << v1 << " " << v2 << std::endl; + + // Zero assignment + v1 = ublas::zero_vector<> (v1.size ()); + std::cout << "v1.zero_vector = " << v1 << std::endl; + v1 = v2; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + // Project range and slice + initialize_vector (v1); + initialize_vector (v2); + project (v1, ublas::range(0,1)) = project (v2, ublas::range(0,1)); + project (v1, ublas::range(0,1)) = project (v2, ublas::slice(0,1,1)); + project (v1, ublas::slice(2,-1,2)) = project (v2, ublas::slice(0,1,2)); + project (v1, ublas::slice(2,-1,2)) = project (v2, ublas::range(0,2)); + std::cout << "v1 = range/slice " << v1 << std::endl; +#endif + + // Unary vector operations resulting in a vector + initialize_vector (v1); + v2 = - v1; + std::cout << "- v1 = " << v2 << std::endl; + v2 = ublas::conj (v1); + std::cout << "conj (v1) = " << v2 << std::endl; + + // Binary vector operations resulting in a vector + initialize_vector (v1); + initialize_vector (v2); + v3 = v1 + v2; + std::cout << "v1 + v2 = " << v3 << std::endl; + v3 = v1 - v2; + std::cout << "v1 - v2 = " << v3 << std::endl; + v3 = ublas::element_prod (v1, v2); + std::cout << "element_prod (v1, v2) = " << v3 << std::endl; + + // Scaling a vector + t = N; + initialize_vector (v1); + v2 = value_type (1.) * v1; + std::cout << "1. * v1 = " << v2 << std::endl; + v2 = t * v1; + std::cout << "N * v1 = " << v2 << std::endl; + initialize_vector (v1); + v2 = v1 * value_type (1.); + std::cout << "v1 * 1. = " << v2 << std::endl; + v2 = v1 * t; + std::cout << "v1 * value_type(N) = " << v2 << std::endl; + // test interop with integer + v2 = v1 * N; + + std::cout << "v1 * N = " << v2 << std::endl; + + // Some assignments + initialize_vector (v1); + initialize_vector (v2); + v2 += v1; + std::cout << "v2 += v1 = " << v2 << std::endl; + v2 -= v1; + std::cout << "v2 -= v1 = " << v2 << std::endl; + v2 = v2 + v1; + std::cout << "v2 = v2 + v1 = " << v2 << std::endl; + v2 = v2 - v1; + std::cout << "v2 = v2 - v1 = " << v2 << std::endl; + v1 *= value_type (1.); + std::cout << "v1 *= 1. = " << v1 << std::endl; + v1 *= t; + std::cout << "v1 *= value_type(N) = " << v1 << std::endl; + // test interop with integer + v1 *= N; + std::cout << "v1 *= N = " << v1 << std::endl; + + // Unary vector operations resulting in a scalar + initialize_vector (v1); + t = ublas::sum (v1); + std::cout << "sum (v1) = " << t << std::endl; + n = ublas::norm_1 (v1); + std::cout << "norm_1 (v1) = " << n << std::endl; + n = ublas::norm_2 (v1); + std::cout << "norm_2 (v1) = " << n << std::endl; + n = ublas::norm_inf (v1); + std::cout << "norm_inf (v1) = " << n << std::endl; + + i = ublas::index_norm_inf (v1); + std::cout << "index_norm_inf (v1) = " << i << std::endl; + + // Binary vector operations resulting in a scalar + initialize_vector (v1); + initialize_vector (v2); + t = ublas::inner_prod (v1, v2); + std::cout << "inner_prod (v1, v2) = " << t << std::endl; + + // Scalar and Binary vector expression resulting in a vector + initialize_vector (v1); + initialize_vector (v2); + v1 = v1 * ublas::inner_prod (v1, v2); + std::cout << "v1 * inner_prod (v1, v2) = " << v1 << std::endl; + } + + void operator () () const { + V v1 (N), v2 (N), v3 (N); + test_expression_with (v1, v2, v3); + test_container_with (v1); + +#ifdef USE_RANGE + ublas::vector_range vr1 (v1, ublas::range (0, N)), + vr2 (v2, ublas::range (0, N)), + vr3 (v3, ublas::range (0, N)); + test_expression_with (vr1, vr2, vr3); +#endif + +#ifdef USE_SLICE + ublas::vector_slice vs1 (v1, ublas::slice (0, 1, N)), + vs2 (v2, ublas::slice (0, 1, N)), + vs3 (v3, ublas::slice (0, 1, N)); + test_expression_with (vs1, vs2, vs3); +#endif + } +}; + +// Test vector +void test_vector () { + std::cout << "test_vector" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_vector, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_vector, std::vector > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_BOUNDED_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded" << std::endl; + test_my_vector, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded" << std::endl; + test_my_vector, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded" << std::endl; + test_my_vector, 3>, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded" << std::endl; + test_my_vector, 3>, 3> () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test12.cpp b/test/ublas_interop/test12.cpp new file mode 100644 index 00000000..7059fb9e --- /dev/null +++ b/test/ublas_interop/test12.cpp @@ -0,0 +1,277 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test1.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v1 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v1 << std::endl; + v1 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v1 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; + } + } + void operator () () const { + { + V v1 (N), v2 (N); + M m1 (N, N); + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, 0), mr2 (m1, 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 0), mc2 (m1, 1); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_MATRIX +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::matrix, ublas::row_major, std::vector > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::matrix, ublas::row_major, std::vector > >, 3> () (); +#endif +#endif +#endif +#endif + +#ifdef USE_BOUNDED_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded" << std::endl; + test_my_matrix_vector, + ublas::bounded_matrix, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded" << std::endl; + test_my_matrix_vector, + ublas::bounded_matrix, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded" << std::endl; + test_my_matrix_vector, 3>, + ublas::bounded_matrix, 3, 3>, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded" << std::endl; + test_my_matrix_vector, 3>, + ublas::bounded_matrix, 3, 3>, 3> () (); +#endif +#endif +#endif + +#ifdef USE_VECTOR_OF_VECTOR +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector > >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::vector_of_vector > >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); +#endif +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test13.cpp b/test/ublas_interop/test13.cpp new file mode 100644 index 00000000..d2f80377 --- /dev/null +++ b/test/ublas_interop/test13.cpp @@ -0,0 +1,321 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test1.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_container_with (VP &v1) const { + // Container type tests in addition to expression types + // Insert and erase + v1.insert_element (0,0, 55); + v1.erase_element (1,1); + v1.clear (); + } + + template + void test_expression_with (MP &m1, MP &m2, MP &m3) const { + value_type t; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + // Project range and slice + initialize_matrix (m1); + initialize_matrix (m2); + project (m1, ublas::range(0,1),ublas::range(0,1)) = project (m2, ublas::range(0,1),ublas::range(0,1)); + project (m1, ublas::range(0,1),ublas::range(0,1)) = project (m2, ublas::slice(0,1,1),ublas::slice(0,1,1)); + project (m1, ublas::slice(2,-1,2),ublas::slice(2,-1,2)) = project (m2, ublas::slice(0,1,2),ublas::slice(0,1,2)); + project (m1, ublas::slice(2,-1,2),ublas::slice(2,-1,2)) = project (m2, ublas::range(0,2),ublas::range(0,2)); + std::cout << "m1 = range/slice " << m1 << std::endl; +#endif + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + m3 = ublas::element_prod (m1, m2); + std::cout << "element_prod (m1, m2) = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m2 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + m2 = ublas::trans (m1); + std::cout << "trans (m1) = " << m2 << std::endl; + + // Hermitean + initialize_matrix (m1); + m2 = ublas::herm (m1); + std::cout << "herm (m1) = " << m2 << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + m3 = ublas::prod (m1, m2); + std::cout << "prod (m1, m2) = " << m3 << std::endl; + } + + void operator () () const { + M m1 (N, N), m2 (N, N), m3 (N, N); + test_expression_with (m1, m2, m3); + test_container_with (m1); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_expression_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_expression_with (ms1, ms2, ms3); +#endif + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_MATRIX +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3> () (); +#endif +#endif +#endif +#endif + +#ifdef USE_BOUNDED_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded" << std::endl; + test_my_matrix, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded" << std::endl; + test_my_matrix, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded" << std::endl; + test_my_matrix, 3, 3>, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded" << std::endl; + test_my_matrix, 3, 3>, 3> () (); +#endif +#endif +#endif + +#ifdef USE_VECTOR_OF_VECTOR +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix > >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix > >, 3> () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > > >, 3> () (); +#endif +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test2.cpp b/test/ublas_interop/test2.cpp new file mode 100644 index 00000000..0550dc80 --- /dev/null +++ b/test/ublas_interop/test2.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test2.hpp" + +int main () { +#ifdef USE_FLOAT + std::cout << "mp_test_type" << std::endl; + test_blas_1, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_blas_1, 3> ().test (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_blas_1 >, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex" << std::endl; + test_blas_1 >, 3> ().test (); +#endif +#endif + + std::cout << "test_blas_2" << std::endl; + +#ifdef USE_FLOAT + std::cout << "mp_test_type" << std::endl; + test_blas_2, ublas::matrix, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_blas_2, ublas::matrix, 3> ().test (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_blas_2 >, ublas::matrix >, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex" << std::endl; + test_blas_2 >, ublas::matrix >, 3> ().test (); +#endif +#endif + + std::cout << "test_blas_3" << std::endl; + +#ifdef USE_FLOAT + std::cout << "mp_test_type" << std::endl; + test_blas_3, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double" << std::endl; + test_blas_3, 3> ().test (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex" << std::endl; + test_blas_3 >, 3> ().test (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex" << std::endl; + test_blas_3 >, 3> ().test (); +#endif +#endif + + return 0; +} diff --git a/test/ublas_interop/test2.hpp b/test/ublas_interop/test2.hpp new file mode 100644 index 00000000..232b7e2c --- /dev/null +++ b/test/ublas_interop/test2.hpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST2_H +#define TEST2_H +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +template +struct test_blas_1 { + typedef typename V::value_type value_type; + typedef typename ublas::type_traits::real_type real_type; + + void test (); +}; + +template +struct test_blas_2 { + typedef typename V::value_type value_type; + + void test (); +}; + +template +struct test_blas_3 { + typedef typename M::value_type value_type; + + void test (); +}; + + +#endif diff --git a/test/ublas_interop/test21.cpp b/test/ublas_interop/test21.cpp new file mode 100644 index 00000000..252d1f1c --- /dev/null +++ b/test/ublas_interop/test21.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test2.hpp" + +template +void test_blas_1::test () { + { + value_type t; + real_type n; + V v1 (N), v2 (N); + + // _asum + initialize_vector (v1); + n = ublas::blas_1::asum (v1); + std::cout << "asum (v1) = " << n << std::endl; + + // _amax + initialize_vector (v1); + n = ublas::blas_1::amax (v1); + std::cout << "amax (v1) = " << n << std::endl; + + // _nrm2 + initialize_vector (v1); + n = ublas::blas_1::nrm2 (v1); + std::cout << "nrm2 (v1) = " << n << std::endl; + + // _dot + // _dotu + // _dotc + initialize_vector (v1); + initialize_vector (v2); + t = ublas::blas_1::dot (v1, v2); + std::cout << "dot (v1, v2) = " << t << std::endl; + t = ublas::blas_1::dot (ublas::conj (v1), v2); + std::cout << "dot (conj (v1), v2) = " << t << std::endl; + + // _copy + initialize_vector (v2); + ublas::blas_1::copy (v1, v2); + std::cout << "copy (v1, v2) = " << v1 << std::endl; + + // _swap + initialize_vector (v1); + initialize_vector (v2); + ublas::blas_1::swap (v1, v2); + std::cout << "swap (v1, v2) = " << v1 << " " << v2 << std::endl; + + // _scal + // csscal + // zdscal + initialize_vector (v1); + ublas::blas_1::scal (v1, value_type (1)); + std::cout << "scal (v1, 1) = " << v1 << std::endl; + + // _axpy + initialize_vector (v1); + initialize_vector (v2); + ublas::blas_1::axpy (v1, value_type (1), v2); + std::cout << "axpy (v1, 1, v2) = " << v1 << std::endl; + + // _rot + initialize_vector (v1); + initialize_vector (v2); + ublas::blas_1::rot (value_type (1), v1, value_type (1), v2); + std::cout << "rot (1, v1, 1, v2) = " << v1 << " " << v2 << std::endl; + } +} + +#ifdef USE_FLOAT +template struct test_blas_1, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_1, 3>; +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT +template struct test_blas_1 >, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_1 >, 3>; +#endif +#endif diff --git a/test/ublas_interop/test22.cpp b/test/ublas_interop/test22.cpp new file mode 100644 index 00000000..297bb06a --- /dev/null +++ b/test/ublas_interop/test22.cpp @@ -0,0 +1,147 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test2.hpp" + +template +void test_blas_2::test () { + { + V v1 (N), v2 (N); + M m (N, N); + + // _t_mv + initialize_vector (v1); + initialize_matrix (m); + ublas::blas_2::tmv (v1, m); + std::cout << "tmv (v1, m) = " << v1 << std::endl; + initialize_vector (v1); + initialize_matrix (m); + ublas::blas_2::tmv (v1, ublas::trans (m)); + std::cout << "tmv (v1, trans (m)) = " << v1 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_vector (v1); + initialize_matrix (m); + ublas::blas_2::tmv (v1, ublas::herm (m)); + std::cout << "tmv (v1, herm (m)) = " << v1 << std::endl; +#endif + + // _t_sv + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::lower_tag ()); + ublas::blas_2::tsv (v1, m, ublas::lower_tag ()); + std::cout << "tsv (v1, m) = " << v1 << " " << ublas::prod (m, v1) - v2 << std::endl; + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::upper_tag ()); + ublas::blas_2::tsv (v1, ublas::trans (m), ublas::lower_tag ()); + std::cout << "tsv (v1, trans (m)) = " << v1 << " " << ublas::prod (ublas::trans (m), v1) - v2 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::upper_tag ()); + ublas::blas_2::tsv (v1, ublas::herm (m), ublas::lower_tag ()); + std::cout << "tsv (v1, herm (m)) = " << v1 << " " << ublas::prod (ublas::herm (m), v1) - v2 << std::endl; +#endif + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::upper_tag ()); + ublas::blas_2::tsv (v1, m, ublas::upper_tag ()); + std::cout << "tsv (v1, m) = " << v1 << " " << ublas::prod (m, v1) - v2 << std::endl; + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::lower_tag ()); + ublas::blas_2::tsv (v1, ublas::trans (m), ublas::upper_tag ()); + std::cout << "tsv (v1, trans (m)) = " << v1 << " " << ublas::prod (ublas::trans (m), v1) - v2 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m, ublas::lower_tag ()); + ublas::blas_2::tsv (v1, ublas::herm (m), ublas::upper_tag ()); + std::cout << "tsv (v1, herm (m)) = " << v1 << " " << ublas::prod (ublas::herm (m), v1) - v2 << std::endl; +#endif + + // _g_mv + // _s_mv + // _h_mv + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m); + ublas::blas_2::gmv (v1, value_type (1), value_type (1), m, v2); + std::cout << "gmv (v1, 1, 1, m, v2) = " << v1 << std::endl; + ublas::blas_2::gmv (v1, value_type (1), value_type (1), ublas::trans (m), v2); + std::cout << "gmv (v1, 1, 1, trans (m), v2) = " << v1 << std::endl; +#ifdef USE_STD_COMPLEX + ublas::blas_2::gmv (v1, value_type (1), value_type (1), ublas::herm (m), v2); + std::cout << "gmv (v1, 1, 1, herm (m), v2) = " << v1 << std::endl; +#endif + + // _g_r + // _g_ru + // _g_rc + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m); + ublas::blas_2::gr (m, value_type (1), v1, v2); + std::cout << "gr (m, 1, v1, v2) = " << m << std::endl; + ublas::blas_2::gr (m, value_type (1), v1, ublas::conj (v2)); + std::cout << "gr (m, 1, v1, conj (v2)) = " << m << std::endl; + + // _s_r + initialize_vector (v1); + initialize_matrix (m); + ublas::blas_2::sr (m, value_type (1), v1); + std::cout << "sr (m, 1, v1) = " << m << std::endl; + +#ifdef USE_STD_COMPLEX + // _h_r + initialize_vector (v1); + initialize_matrix (m); + ublas::blas_2::hr (m, value_type (1), v1); + std::cout << "hr (m, 1, v1) = " << m << std::endl; +#endif + + // _s_r2 + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m); + ublas::blas_2::sr2 (m, value_type (1), v1, v2); + std::cout << "sr2 (m, 1, v1, v2) = " << m << std::endl; + +#ifdef USE_STD_COMPLEX + // _h_r2 + initialize_vector (v1); + initialize_vector (v2); + initialize_matrix (m); + ublas::blas_2::hr2 (m, value_type (1), v1, v2); + std::cout << "hr2 (m, 1, v1, v2) = " << m << std::endl; +#endif + } +} + +#ifdef USE_FLOAT +template struct test_blas_2, ublas::matrix, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_2, ublas::matrix, 3>; +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT +template struct test_blas_2 >, ublas::matrix >, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_2 >, ublas::matrix >, 3>; +#endif +#endif diff --git a/test/ublas_interop/test23.cpp b/test/ublas_interop/test23.cpp new file mode 100644 index 00000000..d56771c2 --- /dev/null +++ b/test/ublas_interop/test23.cpp @@ -0,0 +1,208 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test2.hpp" + +template +void test_blas_3::test () { + { + M m1 (N, N), m2 (N, N), m3 (N, N); + + // _t_mm + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), m2, m1); + std::cout << "tmm (m1, 1, m2, m1) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), m2, ublas::trans (m1)); + std::cout << "tmm (m1, 1, m2, trans (m1)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::trans (m2), m1); + std::cout << "tmm (m1, 1, trans (m2), m1) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::trans (m2), ublas::trans (m1)); + std::cout << "tmm (m1, 1, trans (m2), trans (m1)) = " << m1 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), m2, ublas::herm (m1)); + std::cout << "tmm (m1, 1, m2, herm (m1)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::herm (m2), m1); + std::cout << "tmm (m1, 1, herm (m2), m1) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::trans (m2), ublas::herm (m1)); + std::cout << "tmm (m1, 1, trans (m2), herm (m1)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::herm (m2), ublas::trans (m1)); + std::cout << "tmm (m1, 1, herm (m2), trans (m1)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::tmm (m1, value_type (1), ublas::herm (m2), ublas::herm (m1)); + std::cout << "tmm (m1, 1, herm (m2), herm (m1)) = " << m1 << std::endl; +#endif + + // _t_sm + initialize_matrix (m1); + initialize_matrix (m2, ublas::lower_tag ()); + initialize_matrix (m3); + ublas::blas_3::tsm (m1, value_type (1), m2, ublas::lower_tag ()); + std::cout << "tsm (m1, 1, m2) = " << m1 << " " << ublas::prod (m2, m1) - value_type (1) * m3 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2, ublas::upper_tag ()); + ublas::blas_3::tsm (m1, value_type (1), ublas::trans (m2), ublas::lower_tag ()); + std::cout << "tsm (m1, 1, trans (m2)) = " << m1 << " " << ublas::prod (ublas::trans (m2), m1) - value_type (1) * m3 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_matrix (m1); + initialize_matrix (m2, ublas::upper_tag ()); + ublas::blas_3::tsm (m1, value_type (1), ublas::herm (m2), ublas::lower_tag ()); + std::cout << "tsm (m1, 1, herm (m2)) = " << m1 << " " << ublas::prod (ublas::herm (m2), m1) - value_type (1) * m3 << std::endl; +#endif + initialize_matrix (m1); + initialize_matrix (m2, ublas::upper_tag ()); + ublas::blas_3::tsm (m1, value_type (1), m2, ublas::upper_tag ()); + std::cout << "tsm (m1, 1, m2) = " << m1 << " " << ublas::prod (m2, m1) - value_type (1) * m3 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2, ublas::lower_tag ()); + ublas::blas_3::tsm (m1, value_type (1), ublas::trans (m2), ublas::upper_tag ()); + std::cout << "tsm (m1, 1, trans (m2)) = " << m1 << " " << ublas::prod (ublas::trans (m2), m1) - value_type (1) * m3 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_matrix (m1); + initialize_matrix (m2, ublas::lower_tag ()); + ublas::blas_3::tsm (m1, value_type (1), ublas::herm (m2), ublas::upper_tag ()); + std::cout << "tsm (m1, 1, herm (m2)) = " << m1 << " " << ublas::prod (ublas::herm (m2), m1) - value_type (1) * m3 << std::endl; +#endif + + // _g_mm + // _s_mm + // _h_mm + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), m2, m3); + std::cout << "gmm (m1, 1, 1, m2, m3) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::trans (m2), m3); + std::cout << "gmm (m1, 1, 1, trans (m2), m3) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), m2, ublas::trans (m3)); + std::cout << "gmm (m1, 1, 1, m2, trans (m3)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::trans (m2), ublas::trans (m3)); + std::cout << "gmm (m1, 1, 1, trans (m2), trans (m3)) = " << m1 << std::endl; +#ifdef USE_STD_COMPLEX + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::herm (m2), m3); + std::cout << "gmm (m1, 1, 1, herm (m2), m3) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), m2, ublas::herm (m3)); + std::cout << "gmm (m1, 1, 1, m2, herm (m3)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::herm (m2), ublas::trans (m3)); + std::cout << "gmm (m1, 1, 1, herm (m2), trans (m3)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::trans (m2), ublas::herm (m3)); + std::cout << "gmm (m1, 1, 1, trans (m2), herm (m3)) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::gmm (m1, value_type (1), value_type (1), ublas::herm (m2), ublas::herm (m3)); + std::cout << "gmm (m1, 1, 1, herm (m2), herm (m3)) = " << m1 << std::endl; +#endif + + // s_rk + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::srk (m1, value_type (1), value_type (1), m2); + std::cout << "srk (m1, 1, 1, m2) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::srk (m1, value_type (1), value_type (1), ublas::trans (m2)); + std::cout << "srk (m1, 1, 1, trans (m2)) = " << m1 << std::endl; + +#ifdef USE_STD_COMPLEX + // h_rk + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::hrk (m1, value_type (1), value_type (1), m2); + std::cout << "hrk (m1, 1, 1, m2) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + ublas::blas_3::hrk (m1, value_type (1), value_type (1), ublas::herm (m2)); + std::cout << "hrk (m1, 1, 1, herm (m2)) = " << m1 << std::endl; +#endif + + // s_r2k + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::sr2k (m1, value_type (1), value_type (1), m2, m3); + std::cout << "sr2k (m1, 1, 1, m2, m3) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::sr2k (m1, value_type (1), value_type (1), ublas::trans (m2), ublas::trans (m3)); + std::cout << "sr2k (m1, 1, 1, trans (m2), trans (m3)) = " << m1 << std::endl; + +#ifdef USE_STD_COMPLEX + // h_r2k + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::hr2k (m1, value_type (1), value_type (1), m2, m3); + std::cout << "hr2k (m1, 1, 1, m2, m3) = " << m1 << std::endl; + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + ublas::blas_3::hr2k (m1, value_type (1), value_type (1), ublas::herm (m2), ublas::herm (m3)); + std::cout << "hr2k (m1, 1, 1, herm (m2), herm (m3)) = " << m1 << std::endl; +#endif + } +} + +#ifdef USE_FLOAT +template struct test_blas_3, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_3, 3>; +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT +template struct test_blas_3 >, 3>; +#endif + +#ifdef USE_DOUBLE +template struct test_blas_3 >, 3>; +#endif +#endif diff --git a/test/ublas_interop/test3.cpp b/test/ublas_interop/test3.cpp new file mode 100644 index 00000000..fb2b94da --- /dev/null +++ b/test/ublas_interop/test3.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test3.hpp" + +int main () { + test_vector (); + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test3.hpp b/test/ublas_interop/test3.hpp new file mode 100644 index 00000000..97becba0 --- /dev/null +++ b/test/ublas_interop/test3.hpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST3_H +#define TEST3_H + +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_GENERALIZED_VECTOR_OF_VECTOR +#include +#endif +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +void test_vector (); +void test_matrix_vector (); +void test_matrix (); + +#endif diff --git a/test/ublas_interop/test31.cpp b/test/ublas_interop/test31.cpp new file mode 100644 index 00000000..a1484cfd --- /dev/null +++ b/test/ublas_interop/test31.cpp @@ -0,0 +1,248 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test3.hpp" + +// Test vector expression templates +template +struct test_my_vector { + typedef typename V::value_type value_type; + typedef typename V::size_type size_type; + typedef typename ublas::type_traits::real_type real_type; + + template + void test_with (VP &v1, VP &v2, VP &v3) const { + { + value_type t; + size_type i; + real_type n; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_vector (v1); + initialize_vector (v2); + v1 = v2; + std::cout << "v1 = v2 = " << v1 << std::endl; + v1.assign_temporary (v2); + std::cout << "v1.assign_temporary (v2) = " << v1 << std::endl; + v1.swap (v2); + std::cout << "v1.swap (v2) = " << v1 << " " << v2 << std::endl; + + // Zero assignment + v1 = ublas::zero_vector<> (v1.size ()); + std::cout << "v1.zero_vector = " << v1 << std::endl; + v1 = v2; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + // Project range and slice + initialize_vector (v1); + initialize_vector (v2); + project (v1, ublas::range(0,1)) = project (v2, ublas::range(0,1)); + project (v1, ublas::range(0,1)) = project (v2, ublas::slice(0,1,1)); + project (v1, ublas::slice(2,-1,2)) = project (v2, ublas::slice(0,1,2)); + project (v1, ublas::slice(2,-1,2)) = project (v2, ublas::range(0,2)); + std::cout << "v1 = range/slice " << v1 << std::endl; +#endif + + // Unary vector operations resulting in a vector + initialize_vector (v1); + v2 = - v1; + std::cout << "- v1 = " << v2 << std::endl; + v2 = ublas::conj (v1); + std::cout << "conj (v1) = " << v2 << std::endl; + + // Binary vector operations resulting in a vector + initialize_vector (v1); + initialize_vector (v2); + initialize_vector (v3); + v3 = v1 + v2; + std::cout << "v1 + v2 = " << v3 << std::endl; + + v3 = v1 - v2; + std::cout << "v1 - v2 = " << v3 << std::endl; + + // Scaling a vector + t = N; + initialize_vector (v1); + v2 = value_type (1.) * v1; + std::cout << "1. * v1 = " << v2 << std::endl; + v2 = t * v1; + std::cout << "N * v1 = " << v2 << std::endl; + initialize_vector (v1); + v2 = v1 * value_type (1.); + std::cout << "v1 * 1. = " << v2 << std::endl; + v2 = v1 * t; + std::cout << "v1 * N = " << v2 << std::endl; + + // Some assignments + initialize_vector (v1); + initialize_vector (v2); + v2 += v1; + std::cout << "v2 += v1 = " << v2 << std::endl; + v2 -= v1; + std::cout << "v2 -= v1 = " << v2 << std::endl; + v2 = v2 + v1; + std::cout << "v2 = v2 + v1 = " << v2 << std::endl; + v2 = v2 - v1; + std::cout << "v2 = v2 - v1 = " << v2 << std::endl; + v1 *= value_type (1.); + std::cout << "v1 *= 1. = " << v1 << std::endl; + v1 *= t; + std::cout << "v1 *= N = " << v1 << std::endl; + + // Unary vector operations resulting in a scalar + initialize_vector (v1); + t = ublas::sum (v1); + std::cout << "sum (v1) = " << t << std::endl; + n = ublas::norm_1 (v1); + std::cout << "norm_1 (v1) = " << n << std::endl; + n = ublas::norm_2 (v1); + std::cout << "norm_2 (v1) = " << n << std::endl; + n = ublas::norm_inf (v1); + std::cout << "norm_inf (v1) = " << n << std::endl; + + i = ublas::index_norm_inf (v1); + std::cout << "index_norm_inf (v1) = " << i << std::endl; + + // Binary vector operations resulting in a scalar + initialize_vector (v1); + initialize_vector (v2); + t = ublas::inner_prod (v1, v2); + std::cout << "inner_prod (v1, v2) = " << t << std::endl; + } + } + void operator () () const { + { + V v1 (N, N), v2 (N, N), v3 (N, N); + test_with (v1, v2, v3); + +#ifdef USE_RANGE + ublas::vector_range vr1 (v1, ublas::range (0, N)), + vr2 (v2, ublas::range (0, N)), + vr3 (v3, ublas::range (0, N)); + test_with (vr1, vr2, vr3); +#endif + +#ifdef USE_SLICE + ublas::vector_slice vs1 (v1, ublas::slice (0, 1, N)), + vs2 (v2, ublas::slice (0, 1, N)), + vs3 (v3, ublas::slice (0, 1, N)); + test_with (vs1, vs2, vs3); +#endif + } + } +}; + +// Test vector +void test_vector () { + std::cout << "test_vector" << std::endl; + +#ifdef USE_SPARSE_VECTOR +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, map_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, map_array" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, map_array" << std::endl; + test_my_vector, ublas::map_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, map_array" << std::endl; + test_my_vector, ublas::map_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::map" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::map" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::map" << std::endl; + test_my_vector, std::map > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::map" << std::endl; + test_my_vector, std::map > > , 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_COMPRESSED_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type compressed" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double compressed" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex compressed" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex compressed" << std::endl; + test_my_vector >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_COORDINATE_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type coordinate" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double coordinate" << std::endl; + test_my_vector, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex coordinate" << std::endl; + test_my_vector >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex coordinate" << std::endl; + test_my_vector >, 3 > () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test32.cpp b/test/ublas_interop/test32.cpp new file mode 100644 index 00000000..7240b4ce --- /dev/null +++ b/test/ublas_interop/test32.cpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test3.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v1 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v1 << std::endl; + v1 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v1 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; + } + } + void operator () () const { + { + V v1 (N, N), v2 (N, N); + M m1 (N, N, N * N); + + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, 0), mr2 (m1, N - 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 0), mc2 (m1, N - 1); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_SPARSE_MATRIX +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, map_array" << std::endl; + test_my_matrix_vector >, + ublas::mapped_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, map_array" << std::endl; + test_my_matrix_vector >, + ublas::mapped_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::mapped_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::mapped_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::map" << std::endl; + test_my_matrix_vector >, + ublas::mapped_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::map" << std::endl; + test_my_matrix_vector >, + ublas::mapped_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::mapped_matrix, ublas::row_major, std::map > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::mapped_matrix, ublas::row_major, std::map > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_SPARSE_VECTOR_OF_SPARSE_VECTOR +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_vector map_array" << std::endl; + test_my_matrix_vector >, + ublas::mapped_vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_vector map_array" << std::endl; + test_my_matrix_vector >, + ublas::mapped_vector > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_vector map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::mapped_vector, ublas::row_major, ublas::map_array > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex,mapped_vector map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::mapped_vector, ublas::row_major, ublas::map_array > > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_vector std::map" << std::endl; + test_my_matrix_vector >, + ublas::mapped_vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_vector std::map" << std::endl; + test_my_matrix_vector >, + ublas::mapped_vector > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_vector std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::mapped_vector, ublas::row_major, std::map > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, mapped_vector std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::mapped_vector, ublas::row_major, std::map > > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_GENERALIZED_VECTOR_OF_VECTOR +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix_vector >, + ublas::generalized_vector_of_vector > > >, 3 > () (); + test_my_matrix_vector >, + ublas::generalized_vector_of_vector >, ublas::map_array > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix_vector >, + ublas::generalized_vector_of_vector > > >, 3 > () (); + test_my_matrix_vector >, + ublas::generalized_vector_of_vector >, ublas::map_array > > > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::vector, ublas::map_array > > > >, 3 > () (); + test_my_matrix_vector, ublas::map_array > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::mapped_vector, ublas::map_array > >, ublas::map_array, ublas::map_array > > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix_vector, ublas::map_array > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::vector, ublas::map_array > > > >, 3 > () (); + test_my_matrix_vector, ublas::map_array > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::mapped_vector, ublas::map_array > >, ublas::map_array, ublas::map_array > > > > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix_vector >, + ublas::generalized_vector_of_vector > > >, 3 > () (); + test_my_matrix_vector >, + ublas::generalized_vector_of_vector >, std::map > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix_vector >, + ublas::generalized_vector_of_vector > > >, 3 > () (); + test_my_matrix_vector >, + ublas::generalized_vector_of_vector >, std::map > > > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::vector, std::map > > > >, 3 > () (); + test_my_matrix_vector, std::map > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::mapped_vector, std::map > >, std::map, std::map > > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix_vector, std::map > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::vector, std::map > > > >, 3 > () (); + test_my_matrix_vector, std::map > >, + ublas::generalized_vector_of_vector, ublas::row_major, ublas::mapped_vector, std::map > >, std::map, std::map > > > > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_COMPRESSED_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type compressed" << std::endl; + test_my_matrix_vector, + ublas::compressed_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double compressed" << std::endl; + test_my_matrix_vector, + ublas::compressed_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex compressed" << std::endl; + test_my_matrix_vector >, + ublas::compressed_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex compressed" << std::endl; + test_my_matrix_vector >, + ublas::compressed_matrix >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_COORDINATE_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type coordinate" << std::endl; + test_my_matrix_vector, + ublas::coordinate_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double coordinate" << std::endl; + test_my_matrix_vector, + ublas::coordinate_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex coordinate" << std::endl; + test_my_matrix_vector >, + ublas::coordinate_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex coordinate" << std::endl; + test_my_matrix_vector >, + ublas::coordinate_matrix >, 3 > () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test33.cpp b/test/ublas_interop/test33.cpp new file mode 100644 index 00000000..46d73519 --- /dev/null +++ b/test/ublas_interop/test33.cpp @@ -0,0 +1,347 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test3.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_with (MP &m1, MP &m2, MP &m3) const { + { + value_type t; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + // Project range and slice + initialize_matrix (m1); + initialize_matrix (m2); + project (m1, ublas::range(0,1),ublas::range(0,1)) = project (m2, ublas::range(0,1),ublas::range(0,1)); + project (m1, ublas::range(0,1),ublas::range(0,1)) = project (m2, ublas::slice(0,1,1),ublas::slice(0,1,1)); + project (m1, ublas::slice(2,-1,2),ublas::slice(2,-1,2)) = project (m2, ublas::slice(0,1,2),ublas::slice(0,1,2)); + project (m1, ublas::slice(2,-1,2),ublas::slice(2,-1,2)) = project (m2, ublas::range(0,2),ublas::range(0,2)); + std::cout << "m1 = range/slice " << m1 << std::endl; +#endif + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + initialize_matrix (m3); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m2 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + m2 = ublas::trans (m1); + std::cout << "trans (m1) = " << m2 << std::endl; + + // Hermitean + initialize_matrix (m1); + m2 = ublas::herm (m1); + std::cout << "herm (m1) = " << m2 << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + m3 = ublas::prod (m1, m2); + std::cout << "prod (m1, m2) = " << m3 << std::endl; + } + } + void operator () () const { + { + M m1 (N, N, N * N), m2 (N, N, N * N), m3 (N, N, N * N); + test_with (m1, m2, m3); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_SPARSE_MATRIX +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_matrix map_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_matrix map_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_matrix map_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, mapped_matrix map_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::map_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_matrix std::map" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_matrix std::map" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_matrix std::map" << std::endl; + test_my_matrix, ublas::row_major, std::map > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, mapped_matrix std::map" << std::endl; + test_my_matrix, ublas::row_major, std::map > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_SPARSE_VECTOR_OF_SPARSE_VECTOR +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_vector_of_mapped_vector map_array" << std::endl; + test_my_matrix > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_vector_of_mapped_vector map_array" << std::endl; + test_my_matrix > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_vector_of_mapped_vector map_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::map_array > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, mapped_vector_of_mapped_vectormap_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::map_array > > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, mapped_vector_of_mapped_vector std::map" << std::endl; + test_my_matrix > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, mapped_vector_of_mapped_vector std::map" << std::endl; + test_my_matrix > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, mapped_vector_of_mapped_vector std::map" << std::endl; + test_my_matrix, ublas::row_major, std::map > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, mapped_vector_of_mapped_vector std::map" << std::endl; + test_my_matrix, ublas::row_major, std::map > > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_GENERALIZED_VECTOR_OF_VECTOR +#ifdef USE_MAP_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type,generalized_vector_of_vector map_array" << std::endl; + test_my_matrix > > >, 3 > () (); + test_my_matrix >, ublas::map_array > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix > > >, 3 > () (); + test_my_matrix >, ublas::map_array > > > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::vector, ublas::map_array > > > >, 3 > () (); + test_my_matrix, ublas::row_major, ublas::mapped_vector, ublas::map_array > >, ublas::map_array, ublas::map_array > > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, generalized_vector_of_vector map_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::vector, ublas::map_array > > > >, 3 > () (); + test_my_matrix, ublas::row_major, ublas::mapped_vector, ublas::map_array > >, ublas::map_array, ublas::map_array > > > > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_MAP +#ifdef USE_FLOAT + std::cout << "mp_test_type, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix > > >, 3 > () (); + test_my_matrix >, std::map > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix > > >, 3 > () (); + test_my_matrix >, std::map > > > >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix, ublas::row_major, ublas::vector, std::map > > > >, 3 > () (); + test_my_matrix, ublas::row_major, ublas::mapped_vector, std::map > >, std::map, std::map > > > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, generalized_vector_of_vector std::map" << std::endl; + test_my_matrix, ublas::row_major, ublas::vector, std::map > > > >, 3 > () (); + test_my_matrix, ublas::row_major, ublas::mapped_vector, std::map > >, std::map, std::map > > > > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_COMPRESSED_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type compressed_matrix" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double compressed_matrix" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex compressed_matrix" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex compressed_matrix" << std::endl; + test_my_matrix >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_COORDINATE_MATRIX +#ifdef USE_FLOAT + std::cout << "mp_test_type coordinate_matrix" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double coordinate_matrix" << std::endl; + test_my_matrix, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex coordinate_matrix" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex coordinate_matrix" << std::endl; + test_my_matrix >, 3 > () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test4.cpp b/test/ublas_interop/test4.cpp new file mode 100644 index 00000000..bf5816f5 --- /dev/null +++ b/test/ublas_interop/test4.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test4.hpp" + +int main () { + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test4.hpp b/test/ublas_interop/test4.hpp new file mode 100644 index 00000000..c5ed3eba --- /dev/null +++ b/test/ublas_interop/test4.hpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST4_H +#define TEST4_H + +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +//#define USE_BANDED +#define USE_DIAGONAL + + +void test_matrix_vector (); +void test_matrix (); + + +// FIXME slice are failing in assignment to zero elements +#undef USE_SLICE + +#endif diff --git a/test/ublas_interop/test42.cpp b/test/ublas_interop/test42.cpp new file mode 100644 index 00000000..325d8094 --- /dev/null +++ b/test/ublas_interop/test42.cpp @@ -0,0 +1,361 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test4.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { +#ifndef USE_DIAGONAL + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v2 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v2 << std::endl; + v2 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v2 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + v1 (0) = 0; + v1 (N - 1) = 0; + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; +#endif + } + } + void operator () () const { + { + V v1 (N), v2 (N); +#ifdef USE_BANDED + M m1 (N, N, 1, 1); +#endif +#ifdef USE_DIAGONAL + M m1 (N, N); +#endif + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, 1), mr2 (m1, 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 1), mc2 (m1, 1); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } + + void operator () (int) const { +#ifdef USE_ADAPTOR + { +#ifdef USE_BANDED + V v1 (N), v2 (N); + M m1 (N, N, 1, 1); + ublas::banded_adaptor bam1 (m1, 1, 1); + test_with (v1, v2, bam1); + + ublas::matrix_row > mr1 (bam1, 1), mr2 (bam1, 1); + test_with (mr1, mr2, bam1); + + ublas::matrix_column > mc1 (bam1, 1), mc2 (bam1, 1); + test_with (mc1, mc2, bam1); + +#ifdef USE_RANGE + ublas::matrix_vector_range > mvr1 (bam1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (bam1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, bam1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice > mvs1 (bam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (bam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, bam1); +#endif +#endif +#ifdef USE_DIAGONAL + V v1 (N), v2 (N); + M m1 (N, N); + ublas::diagonal_adaptor dam1 (m1); + test_with (v1, v2, dam1); + + ublas::matrix_row > mr1 (dam1, 1), mr2 (dam1, 1); + test_with (mr1, mr2, dam1); + + ublas::matrix_column > mc1 (dam1, 1), mc2 (dam1, 1); + test_with (mc1, mc2, dam1); + +#ifdef USE_RANGE + ublas::matrix_vector_range > mvr1 (dam1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (dam1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, dam1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice > mvs1 (dam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (dam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, dam1); +#endif +#endif + } +#endif + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_BANDED +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::banded_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::banded_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::banded_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::banded_matrix, ublas::row_major, std::vector > >, 3> () (0); +#endif +#endif +#endif +#endif + +#ifdef USE_DIAGONAL +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::diagonal_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::diagonal_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::diagonal_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::diagonal_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::diagonal_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::diagonal_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::diagonal_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::diagonal_matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::diagonal_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::diagonal_matrix, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::diagonal_matrix, ublas::row_major, std::vector > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::diagonal_matrix, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::diagonal_matrix, ublas::row_major, std::vector > >, 3> () (0); +#endif +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test43.cpp b/test/ublas_interop/test43.cpp new file mode 100644 index 00000000..82682c97 --- /dev/null +++ b/test/ublas_interop/test43.cpp @@ -0,0 +1,326 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test4.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_with (MP &m1, MP &m2, MP &m3) const { + { + value_type t; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m2 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + m2 = ublas::trans (m1); + std::cout << "trans (m1) = " << m2 << std::endl; + + // Hermitean + initialize_matrix (m1); + m2 = ublas::herm (m1); + std::cout << "herm (m1) = " << m2 << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + // Banded times banded isn't banded + std::cout << "prod (m1, m2) = " << ublas::prod (m1, m2) << std::endl; + } + } + void operator () () const { + { +#ifdef USE_BANDED + M m1 (N, N, 1, 1), m2 (N, N, 1, 1), m3 (N, N, 1, 1); +#endif +#ifdef USE_DIAGONAL + M m1 (N, N), m2 (N, N), m3 (N, N); +#endif + test_with (m1, m2, m3); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } + +#ifdef USE_ADAPTOR + { +#ifdef USE_BANDED + M m1 (N, N, 1, 1), m2 (N, N, 1, 1), m3 (N, N, 1, 1); + ublas::banded_adaptor bam1 (m1, 1, 1), bam2 (m2, 1, 1), bam3 (m3, 1, 1); + test_with (bam1, bam2, bam3); + +#ifdef USE_RANGE + ublas::matrix_range > mr1 (bam1, ublas::range (0, N), ublas::range (0, N)), + mr2 (bam2, ublas::range (0, N), ublas::range (0, N)), + mr3 (bam3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice > ms1 (bam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (bam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (bam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif +#endif +#ifdef USE_DIAGONAL + M m1 (N, N), m2 (N, N), m3 (N, N); + ublas::diagonal_adaptor dam1 (m1), dam2 (m2), dam3 (m3); + test_with (dam1, dam2, dam3); + +#ifdef USE_RANGE + ublas::matrix_range > mr1 (dam1, ublas::range (0, N), ublas::range (0, N)), + mr2 (dam2, ublas::range (0, N), ublas::range (0, N)), + mr3 (dam3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice > ms1 (dam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (dam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (dam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif +#endif + } +#endif + + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_BANDED +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif +#endif +#endif +#endif + +#ifdef USE_DIAGONAL +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test5.cpp b/test/ublas_interop/test5.cpp new file mode 100644 index 00000000..548cd603 --- /dev/null +++ b/test/ublas_interop/test5.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test5.hpp" + +int main () { + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test5.hpp b/test/ublas_interop/test5.hpp new file mode 100644 index 00000000..dc345198 --- /dev/null +++ b/test/ublas_interop/test5.hpp @@ -0,0 +1,60 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST5_H +#define TEST5_H + +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +void test_matrix_vector (); +void test_matrix (); + + +// FIXME slice are failing in assignment to zero elements +#undef USE_SLICE + +#endif diff --git a/test/ublas_interop/test52.cpp b/test/ublas_interop/test52.cpp new file mode 100644 index 00000000..9e13dfde --- /dev/null +++ b/test/ublas_interop/test52.cpp @@ -0,0 +1,214 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test5.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v2 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v2 << std::endl; + v2 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v2 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + v1 (0) = 0; + v2 (N - 1) = 0; + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; + } + } + void operator () () const { + { + V v1 (N), v2 (N); + M m1 (N, N); + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, N - 1), mr2 (m1, N - 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 0), mc2 (m1, 0); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } + + void operator () (int) const { +#ifdef USE_ADAPTOR + { + V v1 (N), v2 (N); + M m1 (N, N); + ublas::triangular_adaptor tam1 (m1); + test_with (v1, v2, tam1); + + ublas::matrix_row > mr1 (tam1, N - 1), mr2 (tam1, N - 1); + test_with (mr1, mr2, tam1); + + ublas::matrix_column > mc1 (tam1, 0), mc2 (tam1, 0); + test_with (mc1, mc2, tam1); + +#ifdef USE_RANGE + ublas::matrix_vector_range > mvr1 (tam1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (tam1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, tam1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice > mvs1 (tam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (tam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, tam1); +#endif + } +#endif + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::triangular_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); + + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::triangular_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test53.cpp b/test/ublas_interop/test53.cpp new file mode 100644 index 00000000..041be1f5 --- /dev/null +++ b/test/ublas_interop/test53.cpp @@ -0,0 +1,223 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test5.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_with (MP &m1, MP &m2, MP &m3) const { + { + value_type t; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m2 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + // Transpose of a triangular isn't triangular of the same kind + std::cout << "trans (m1) = " << ublas::trans (m1) << std::endl; + + // Hermitian + initialize_matrix (m1); + // Hermitian of a triangular isn't hermitian of the same kind + std::cout << "herm (m1) = " << ublas::herm (m1) << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + m3 = ublas::prod (m1, m2); + std::cout << "prod (m1, m2) = " << m3 << std::endl; + } + } + void operator () () const { + { + M m1 (N, N), m2 (N, N), m3 (N, N); + test_with (m1, m2, m3); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } + +#ifdef USE_ADAPTOR + { + M m1 (N, N), m2 (N, N), m3 (N, N); + ublas::triangular_adaptor tam1 (m1), tam2 (m2), tam3 (m3); + test_with (tam1, tam2, tam3); + +#ifdef USE_RANGE + ublas::matrix_range > mr1 (tam1, ublas::range (0, N), ublas::range (0, N)), + mr2 (tam2, ublas::range (0, N), ublas::range (0, N)), + mr3 (tam3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice > ms1 (tam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (tam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (tam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } +#endif + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE +std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test6.cpp b/test/ublas_interop/test6.cpp new file mode 100644 index 00000000..61a5c310 --- /dev/null +++ b/test/ublas_interop/test6.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test6.hpp" + +int main () { + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test6.hpp b/test/ublas_interop/test6.hpp new file mode 100644 index 00000000..766d6b92 --- /dev/null +++ b/test/ublas_interop/test6.hpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST6_H +#define TEST6_H + +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +void test_matrix_vector (); +void test_matrix (); + + +#endif diff --git a/test/ublas_interop/test62.cpp b/test/ublas_interop/test62.cpp new file mode 100644 index 00000000..a7529d29 --- /dev/null +++ b/test/ublas_interop/test62.cpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test6.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v2 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v2 << std::endl; + v2 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v2 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + v1 (0) = 0; + v1 (N - 1) = 0; + v2 (0) = 0; + v2 (N - 1) = 0; + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; + } + } + void operator () () const { + { + V v1 (N), v2 (N); + M m1 (N, N); + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, N - 1), mr2 (m1, N - 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 0), mc2 (m1, 0); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } + + void operator () (int) const { +#ifdef USE_ADAPTOR + { + V v1 (N), v2 (N); + M m1 (N, N); + ublas::symmetric_adaptor tam1 (m1); + test_with (v1, v2, tam1); + + ublas::matrix_row > mr1 (tam1, N - 1), mr2 (tam1, N - 1); + test_with (mr1, mr2, tam1); + + ublas::matrix_column > mc1 (tam1, 0), mc2 (tam1, 0); + test_with (mc1, mc2, tam1); + +#ifdef USE_RANGE + ublas::matrix_vector_range > mvr1 (tam1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (tam1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, tam1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice > mvs1 (tam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (tam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, tam1); +#endif + } +#endif + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (); + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3> () (0); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (); + test_my_matrix_vector >, + ublas::symmetric_matrix >, 3> () (0); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (); + test_my_matrix_vector, std::vector > >, + ublas::symmetric_matrix, ublas::lower, ublas::row_major, std::vector > >, 3> () (0); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test63.cpp b/test/ublas_interop/test63.cpp new file mode 100644 index 00000000..d36f09c1 --- /dev/null +++ b/test/ublas_interop/test63.cpp @@ -0,0 +1,223 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test6.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_with (MP &m1, MP &m2, MP &m3) const { + { + value_type t; + + // Default Construct + default_construct::test (); + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m1 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + m2 = ublas::trans (m1); + std::cout << "trans (m1) = " << m2 << std::endl; + + // Hermitean + initialize_matrix (m1); + m2 = ublas::herm (m1); + std::cout << "herm (m1) = " << m2 << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + m3 = ublas::prod (m1, m2); + std::cout << "prod (m1, m2) = " << m3 << std::endl; + } + } + void operator () () const { + { + M m1 (N, N), m2 (N, N), m3 (N, N); + test_with (m1, m2, m3); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } + +#ifdef USE_ADAPTOR + { + M m1 (N, N), m2 (N, N), m3 (N, N); + ublas::symmetric_adaptor sam1 (m1), sam2 (m2), sam3 (m3); + test_with (sam1, sam2, sam3); + +#ifdef USE_RANGE + ublas::matrix_range > mr1 (sam1, ublas::range (0, N), ublas::range (0, N)), + mr2 (sam2, ublas::range (0, N), ublas::range (0, N)), + mr3 (sam3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice > ms1 (sam1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (sam2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (sam3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } +#endif + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, bounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, bounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "mp_test_type, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, unbounded_array" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, unbounded_array" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "mp_test_type, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "double, std::vector" << std::endl; + test_my_matrix >, 3 > () (); +#endif + +#ifdef USE_STD_COMPLEX +#ifdef USE_FLOAT + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "std::complex, std::vector" << std::endl; + test_my_matrix, ublas::lower, ublas::row_major, std::vector > >, 3 > () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test7.cpp b/test/ublas_interop/test7.cpp new file mode 100644 index 00000000..f564031c --- /dev/null +++ b/test/ublas_interop/test7.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include + +#include +#include + +#include +#include +#include + +#include "test7.hpp" + +// this testcase requires fix of task #2473 + +int main () { + test_vector (); + test_matrix_vector (); + test_matrix (); + return 0; +} diff --git a/test/ublas_interop/test7.hpp b/test/ublas_interop/test7.hpp new file mode 100644 index 00000000..ad990859 --- /dev/null +++ b/test/ublas_interop/test7.hpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef TEST7_H +#define TEST7_H + +#ifdef _MSC_VER +# pragma warning(disable:4800 4996) +#endif + +#include + +typedef boost::multiprecision::number, boost::multiprecision::et_off> mp_test_type; +//typedef double mp_test_type; + +#define USE_RANGE +#define USE_SLICE +#define USE_FLOAT +#define USE_UNBOUNDED_ARRAY +#define USE_STD_VECTOR +#define USE_BOUNDED_VECTOR USE_MATRIX +#define USE_UNBOUNDED_ARRAY +#define USE_MAP_ARRAY +#define USE_STD_MAP +#define USE_MAPPED_VECTOR +#define USE_COMPRESSED_VECTOR +#define USE_COORDINATE_VECTOR +#define USE_MAPPED_MATRIX +#define USE_COMPRESSED_MATRIX +#define USE_COORDINATE_MATRIX + +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace ublas = boost::numeric::ublas; + +#include "common/init.hpp" + +void test_vector (); +void test_matrix_vector (); +void test_matrix (); + + +#endif diff --git a/test/ublas_interop/test71.cpp b/test/ublas_interop/test71.cpp new file mode 100644 index 00000000..4639b139 --- /dev/null +++ b/test/ublas_interop/test71.cpp @@ -0,0 +1,170 @@ +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test7.hpp" + +// Test vector expression templates +template +struct test_my_vector { + typedef typename V::value_type value_type; + typedef typename V::size_type size_type; + typedef typename ublas::type_traits::real_type real_type; + + template + void test_with (VP &v1, VP &v2, VP &v3) const { + { + value_type t; + size_type i; + real_type n; + + // Copy and swap + initialize_vector (v1); + initialize_vector (v2); + v1 = v2; + std::cout << "v1 = v2 = " << v1 << std::endl; + v1.assign_temporary (v2); + std::cout << "v1.assign_temporary (v2) = " << v1 << std::endl; + v1.swap (v2); + std::cout << "v1.swap (v2) = " << v1 << " " << v2 << std::endl; + + // Zero assignment + v1 = ublas::zero_vector (v1.size ()); + std::cout << "v1.zero_vector = " << v1 << std::endl; + v1 = v2; + + // Unary vector operations resulting in a vector + initialize_vector (v1); + v2 = - v1; + std::cout << "- v1 = " << v2 << std::endl; + v2 = ublas::conj (v1); + std::cout << "conj (v1) = " << v2 << std::endl; + + // Binary vector operations resulting in a vector + initialize_vector (v1); + initialize_vector (v2); + v3 = v1 + v2; + std::cout << "v1 + v2 = " << v3 << std::endl; + + v3 = v1 - v2; + std::cout << "v1 - v2 = " << v3 << std::endl; + + // Scaling a vector + t = value_type (N); + initialize_vector (v1); + v2 = value_type (1.) * v1; + std::cout << "1. * v1 = " << v2 << std::endl; +// v2 = t * v1; + std::cout << "N * v1 = " << v2 << std::endl; + initialize_vector (v1); +// v2 = v1 * value_type (1.); + std::cout << "v1 * 1. = " << v2 << std::endl; +// v2 = v1 * t; + std::cout << "v1 * N = " << v2 << std::endl; + + // Some assignments + initialize_vector (v1); + initialize_vector (v2); + v2 += v1; + std::cout << "v2 += v1 = " << v2 << std::endl; + v2 -= v1; + std::cout << "v2 -= v1 = " << v2 << std::endl; + v2 = v2 + v1; + std::cout << "v2 = v2 + v1 = " << v2 << std::endl; + v2 = v2 - v1; + std::cout << "v2 = v2 - v1 = " << v2 << std::endl; + v1 *= value_type (1.); + std::cout << "v1 *= 1. = " << v1 << std::endl; + v1 *= t; + std::cout << "v1 *= N = " << v1 << std::endl; + + // Unary vector operations resulting in a scalar + initialize_vector (v1); + t = ublas::sum (v1); + std::cout << "sum (v1) = " << t << std::endl; + n = ublas::norm_1 (v1); + std::cout << "norm_1 (v1) = " << n << std::endl; + n = ublas::norm_2 (v1); + std::cout << "norm_2 (v1) = " << n << std::endl; + n = ublas::norm_inf (v1); + std::cout << "norm_inf (v1) = " << n << std::endl; + + i = ublas::index_norm_inf (v1); + std::cout << "index_norm_inf (v1) = " << i << std::endl; + + // Binary vector operations resulting in a scalar + initialize_vector (v1); + initialize_vector (v2); + t = ublas::inner_prod (v1, v2); + std::cout << "inner_prod (v1, v2) = " << t << std::endl; + } + } + void operator () () const { + { + V v1 (N), v2 (N), v3 (N); + test_with (v1, v2, v3); + +#ifdef USE_RANGE + ublas::vector_range vr1 (v1, ublas::range (0, N)), + vr2 (v2, ublas::range (0, N)), + vr3 (v3, ublas::range (0, N)); + test_with (vr1, vr2, vr3); +#endif + +#ifdef USE_SLICE + ublas::vector_slice vs1 (v1, ublas::slice (0, 1, N)), + vs2 (v2, ublas::slice (0, 1, N)), + vs3 (v3, ublas::slice (0, 1, N)); + test_with (vs1, vs2, vs3); +#endif + } + } +}; + +// Test vector +void test_vector () { + std::cout << "test_vector" << std::endl; + +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_vector, ublas::bounded_array, 3> >, 3 > () (); +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_vector, ublas::unbounded_array > >, 3 > () (); +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_vector, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_vector, std::vector > >, 3 > () (); +#endif +#endif +} diff --git a/test/ublas_interop/test72.cpp b/test/ublas_interop/test72.cpp new file mode 100644 index 00000000..07b1d8a0 --- /dev/null +++ b/test/ublas_interop/test72.cpp @@ -0,0 +1,165 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test7.hpp" + +// Test matrix & vector expression templates +template +struct test_my_matrix_vector { + typedef typename V::value_type value_type; + + template + void test_with (VP &v1, VP &v2, MP &m1) const { + { + // Rows and columns + initialize_matrix (m1); + for (int i = 0; i < N; ++ i) { + v1 = ublas::row (m1, i); + std::cout << "row (m, " << i << ") = " << v1 << std::endl; + v1 = ublas::column (m1, i); + std::cout << "column (m, " << i << ") = " << v1 << std::endl; + } + + // Outer product + initialize_vector (v1); + initialize_vector (v2); + m1 = ublas::outer_prod (v1, v2); + std::cout << "outer_prod (v1, v2) = " << m1 << std::endl; + + // Matrix vector product + initialize_matrix (m1); + initialize_vector (v1); + v2 = ublas::prod (m1, v1); + std::cout << "prod (m1, v1) = " << v2 << std::endl; + v2 = ublas::prod (v1, m1); + std::cout << "prod (v1, m1) = " << v2 << std::endl; + } + } + void operator () () const { + { + V v1 (N), v2 (N); + M m1 (N, N); + test_with (v1, v2, m1); + + ublas::matrix_row mr1 (m1, 0), mr2 (m1, 1); + test_with (mr1, mr2, m1); + + ublas::matrix_column mc1 (m1, 0), mc2 (m1, 1); + test_with (mc1, mc2, m1); + +#ifdef USE_RANGE + ublas::matrix_vector_range mvr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mvr2 (m1, ublas::range (0, N), ublas::range (0, N)); + test_with (mvr1, mvr2, m1); +#endif + +#ifdef USE_SLICE + ublas::matrix_vector_slice mvs1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + mvs2 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (mvs1, mvs2, m1); +#endif + } + } +}; + +// Test matrix & vector +void test_matrix_vector () { + std::cout << "test_matrix_vector" << std::endl; + +#ifdef USE_MATRIX +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3> () (); +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::matrix, ublas::row_major, ublas::unbounded_array > >, 3> () (); +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::matrix, ublas::row_major, std::vector > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::matrix, ublas::row_major, std::vector > >, 3> () (); +#endif +#endif +#endif + +#ifdef USE_VECTOR_OF_VECTOR +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix_vector, ublas::bounded_array, 3> >, + ublas::vector_of_vector, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3> () (); +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix_vector, ublas::unbounded_array > >, + ublas::vector_of_vector, ublas::row_major, ublas::unbounded_array > > >, 3> () (); +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix_vector, std::vector > >, + ublas::vector_of_vector, ublas::row_major, std::vector > > >, 3> () (); +#endif +#endif +#endif +} diff --git a/test/ublas_interop/test73.cpp b/test/ublas_interop/test73.cpp new file mode 100644 index 00000000..60b10bb7 --- /dev/null +++ b/test/ublas_interop/test73.cpp @@ -0,0 +1,202 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#include "test7.hpp" + +// Test matrix expression templates +template +struct test_my_matrix { + typedef typename M::value_type value_type; + + template + void test_with (MP &m1, MP &m2, MP &m3) const { + { + value_type t; + + // Copy and swap + initialize_matrix (m1); + initialize_matrix (m2); + m1 = m2; + std::cout << "m1 = m2 = " << m1 << std::endl; + m1.assign_temporary (m2); + std::cout << "m1.assign_temporary (m2) = " << m1 << std::endl; + m1.swap (m2); + std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; + + // Zero assignment + m1 = ublas::zero_matrix (m1.size1 (), m1.size2 ()); + std::cout << "m1.zero_matrix = " << m1 << std::endl; + m1 = m2; + + // Unary matrix operations resulting in a matrix + initialize_matrix (m1); + m2 = - m1; + std::cout << "- m1 = " << m2 << std::endl; + m2 = ublas::conj (m1); + std::cout << "conj (m1) = " << m2 << std::endl; + + // Binary matrix operations resulting in a matrix + initialize_matrix (m1); + initialize_matrix (m2); + m3 = m1 + m2; + std::cout << "m1 + m2 = " << m3 << std::endl; + m3 = m1 - m2; + std::cout << "m1 - m2 = " << m3 << std::endl; + + // Scaling a matrix + t = N; + initialize_matrix (m1); + m2 = value_type (1.) * m1; + std::cout << "1. * m1 = " << m2 << std::endl; + m2 = t * m1; + std::cout << "N * m1 = " << m2 << std::endl; + initialize_matrix (m1); + m2 = m1 * value_type (1.); + std::cout << "m1 * 1. = " << m2 << std::endl; + m2 = m1 * t; + std::cout << "m1 * N = " << m2 << std::endl; + + // Some assignments + initialize_matrix (m1); + initialize_matrix (m2); + m2 += m1; + std::cout << "m2 += m1 = " << m2 << std::endl; + m2 -= m1; + std::cout << "m2 -= m1 = " << m2 << std::endl; + m2 = m2 + m1; + std::cout << "m2 = m2 + m1 = " << m2 << std::endl; + m2 = m2 - m1; + std::cout << "m2 = m1 - m1 = " << m2 << std::endl; + m1 *= value_type (1.); + std::cout << "m1 *= 1. = " << m1 << std::endl; + m1 *= t; + std::cout << "m1 *= N = " << m1 << std::endl; + + // Transpose + initialize_matrix (m1); + m2 = ublas::trans (m1); + std::cout << "trans (m1) = " << m2 << std::endl; + + // Hermitean + initialize_matrix (m1); + m2 = ublas::herm (m1); + std::cout << "herm (m1) = " << m2 << std::endl; + + // Matrix multiplication + initialize_matrix (m1); + initialize_matrix (m2); + m3 = ublas::prod (m1, m2); + std::cout << "prod (m1, m2) = " << m3 << std::endl; + } + } + void operator () () const { + { + M m1 (N, N), m2 (N, N), m3 (N, N); + test_with (m1, m2, m3); + +#ifdef USE_RANGE + ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), + mr2 (m2, ublas::range (0, N), ublas::range (0, N)), + mr3 (m3, ublas::range (0, N), ublas::range (0, N)); + test_with (mr1, mr2, mr3); +#endif + +#ifdef USE_SLICE + ublas::matrix_slice ms1 (m1, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms2 (m2, ublas::slice (0, 1, N), ublas::slice (0, 1, N)), + ms3 (m3, ublas::slice (0, 1, N), ublas::slice (0, 1, N)); + test_with (ms1, ms2, ms3); +#endif + } + } +}; + +// Test matrix +void test_matrix () { + std::cout << "test_matrix" << std::endl; + +#ifdef USE_MATRIX +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3 * 3> >, 3 > () (); +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > >, 3 > () (); +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > >, 3 > () (); +#endif +#endif +#endif + +#ifdef USE_VECTOR_OF_VECTOR +#ifdef USE_BOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, bounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::bounded_array, 3>, 3 + 1> >, 3 > () (); +#endif +#endif + +#ifdef USE_UNBOUNDED_ARRAY +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, unbounded_array" << std::endl; + test_my_matrix, ublas::row_major, ublas::unbounded_array > > >, 3 > () (); +#endif +#endif + +#ifdef USE_STD_VECTOR +#ifdef USE_FLOAT + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > > >, 3 > () (); +#endif + +#ifdef USE_DOUBLE + std::cout << "boost::numeric::interval, std::vector" << std::endl; + test_my_matrix, ublas::row_major, std::vector > > >, 3 > () (); +#endif +#endif +#endif +}