diff --git a/doc/debugger1.png b/doc/debugger1.png new file mode 100644 index 00000000..2b195697 Binary files /dev/null and b/doc/debugger1.png differ diff --git a/doc/debugger2.png b/doc/debugger2.png new file mode 100644 index 00000000..f85a7ba0 Binary files /dev/null and b/doc/debugger2.png differ diff --git a/doc/debugger3.png b/doc/debugger3.png new file mode 100644 index 00000000..c0f6d034 Binary files /dev/null and b/doc/debugger3.png differ diff --git a/doc/debugger4.png b/doc/debugger4.png new file mode 100644 index 00000000..6db2b3c2 Binary files /dev/null and b/doc/debugger4.png differ diff --git a/doc/debugger5.png b/doc/debugger5.png new file mode 100644 index 00000000..59870fcf Binary files /dev/null and b/doc/debugger5.png differ diff --git a/doc/debugger6.png b/doc/debugger6.png new file mode 100644 index 00000000..2bab4f7b Binary files /dev/null and b/doc/debugger6.png differ diff --git a/doc/html/boost_multiprecision/indexes/s01.html b/doc/html/boost_multiprecision/indexes/s01.html index 7976d235..d179b255 100644 --- a/doc/html/boost_multiprecision/indexes/s01.html +++ b/doc/html/boost_multiprecision/indexes/s01.html @@ -22,9 +22,9 @@
PrevUpHomeNext
-
+

-Function Index

+Function Index

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

diff --git a/doc/html/boost_multiprecision/indexes/s02.html b/doc/html/boost_multiprecision/indexes/s02.html index faff321b..99ee188f 100644 --- a/doc/html/boost_multiprecision/indexes/s02.html +++ b/doc/html/boost_multiprecision/indexes/s02.html @@ -22,10 +22,10 @@
PrevUpHomeNext
-
+

-Class Index

-

C E G I L M N T

+Class Index
+

C D E G I L M N T

C @@ -42,6 +42,10 @@
+D +
+
+
E

C I L M S T U

diff --git a/doc/html/boost_multiprecision/indexes/s04.html b/doc/html/boost_multiprecision/indexes/s04.html index ce564814..5eb4a30d 100644 --- a/doc/html/boost_multiprecision/indexes/s04.html +++ b/doc/html/boost_multiprecision/indexes/s04.html @@ -21,9 +21,9 @@
PrevUpHome
-
+

-Index

+Index

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

@@ -237,6 +237,7 @@
  • mpfr_float

  • +
  • debug_adaptor

  • default_precision

    diff --git a/doc/html/boost_multiprecision/tut.html b/doc/html/boost_multiprecision/tut.html index a4a310e0..a526dc29 100644 --- a/doc/html/boost_multiprecision/tut.html +++ b/doc/html/boost_multiprecision/tut.html @@ -68,7 +68,12 @@
    rational_adaptor
  • Miscellaneous Number Types.
    -
    logged_adaptor
    +
    +
    logged_adaptor
    +
    debug_adaptor
    +
    Visual C++ + Debugger Visualizers
    +
    Constructing and Interconverting Between Number Types
    Generating Random Numbers
    diff --git a/doc/html/boost_multiprecision/tut/conversions.html b/doc/html/boost_multiprecision/tut/conversions.html index 1b7654b4..b799bbb9 100644 --- a/doc/html/boost_multiprecision/tut/conversions.html +++ b/doc/html/boost_multiprecision/tut/conversions.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -171,7 +171,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_multiprecision/tut/misc.html b/doc/html/boost_multiprecision/tut/misc.html index 8e0fd297..9ec1fa15 100644 --- a/doc/html/boost_multiprecision/tut/misc.html +++ b/doc/html/boost_multiprecision/tut/misc.html @@ -26,7 +26,12 @@ - +

    Backend types listed in this section are predominantly designed to aid debugging.

    diff --git a/doc/html/boost_multiprecision/tut/misc/debug_adaptor.html b/doc/html/boost_multiprecision/tut/misc/debug_adaptor.html new file mode 100644 index 00000000..2c9f71e9 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/misc/debug_adaptor.html @@ -0,0 +1,99 @@ + + + +debug_adaptor + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

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

    +
    namespace boost{ namespace multiprecision{
    +
    +template <Backend>
    +class debug_adaptor;
    +
    +}} // namespaces
    +
    +

    + The debug_adaptor type + is used in conjunction with number + and some other backend type: it acts as a thin wrapper around some other + backend to class number + and intercepts all operations on that object storing the result as a string + within itself. +

    +

    + This type provides numeric_limits + support whenever the template argument Backend does so. +

    +

    + This type is particularly useful when your debugger provides a good view + of std::string: when this is the case multiprecision + values can easily be inspected in the debugger by looking at the debug_value member of debug_adapter. + The down side of this approach is that runtimes are much slower when using + this type. Set against that it can make debugging very much easier, certainly + much easier than sprinkling code with printf + statements. +

    +

    + When used in conjunction with the Visual C++ debugger visualisers, the + value of a multiprecision type that uses this backend is displayed in the + debugger just a builtin value would be, here we're inspecting a value of + type number<debug_adapter<cpp_dec_float<50> > + >: +

    +

    + debugger1 +

    +

    + Otherwise you will need to expand out the view and look at the "debug_value" + member: +

    +

    + debugger2 +

    +

    + It works for all the backend types equally too, here it is inspecting a + number<debug_adapter<gmp_rational> + >: +

    +

    + debugger3 +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_multiprecision/tut/misc/logged_adaptor.html b/doc/html/boost_multiprecision/tut/misc/logged_adaptor.html index 91b44abd..c2e00142 100644 --- a/doc/html/boost_multiprecision/tut/misc/logged_adaptor.html +++ b/doc/html/boost_multiprecision/tut/misc/logged_adaptor.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -217,7 +217,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_multiprecision/tut/misc/visualizers.html b/doc/html/boost_multiprecision/tut/misc/visualizers.html new file mode 100644 index 00000000..afbdee13 --- /dev/null +++ b/doc/html/boost_multiprecision/tut/misc/visualizers.html @@ -0,0 +1,198 @@ + + + +Visual C++ Debugger Visualizers + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + Let's face it debugger multiprecision numbers is hard - simply because + we can't easily inspect the value of the numbers. Visual C++ provides a + partial solution in the shape of "visualizers" which provide + improved views of complex data structures, these visualizers need to be + added to the [Visualizer] section of autoexp.dat + located in the Common7\Packages\Debugger + directory of your Visual Studio installation. +

    +
    + + + + + +
    [Note]Note

    + These visualizers have only been tested with VC10, also given the ability + of buggy visualizers to crash your Visual C++ debugger, make sure you + back up autoexp.dat file before using these!! +

    +

    + This visualizer provides improved views of debug_adaptor: +

    +
    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<>,>{
    +   preview(
    +      #(
    +          $e.m_backend.debug_value
    +      )
    +   )
    +}
    +
    +

    + The next visualizer provides improved views of cpp_int: small numbers are + displayed as actual values, while larger numbers are displayed as an array + of hexadecimal parts, with the most significant part first. +

    +

    + Here's what it looks like for small values: +

    +

    + debugger4 +

    +

    + And for larger values: +

    +

    + debugger5 +

    +

    + There is also a ~raw + child member that lets you see the actual members of the class: +

    +

    + debugger6 +

    +

    + Here's the visualizer code: +

    +
    boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<,,1,,void>,>{
    +   preview(
    +      #if($e.m_backend.m_limbs == 1) (
    +         #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_wrapper.m_data[0]) ) #else ($e.m_backend.m_wrapper.m_data[0])
    +      )
    +      #elif(($e.m_backend.m_limbs == 2) && ($e.m_backend.m_wrapper.m_data[1] < 0x80000000)) (
    +         #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_wrapper.m_data[0] | ((__int64)$e.m_backend.m_wrapper.m_data[1] << 32)) ) #else ($e.m_backend.m_wrapper.m_data[0] | ((__int64)$e.m_backend.m_wrapper.m_data[1] << 32))
    +      ) #else (
    +         #( "signbit = ", $e.m_backend.m_sign, " data = ", #array ( expr: $e.m_backend.m_wrapper.m_data[$e.m_backend.m_limbs - $i - 1], size: $e.m_backend.m_limbs ) : [$e,x] )
    +      )
    +   )
    +
    +   children (
    +      #(
    +         ~raw: [$c,!],
    +         sign bit: $e.m_backend.m_sign,
    +         #array (
    +               expr: $e.m_backend.m_wrapper.m_data[$e.m_backend.m_limbs - $i - 1],
    +               size: $e.m_backend.m_limbs
    +         ) : [$e,x]
    +      )
    +   )
    +}
    +
    +boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<,,0,,void>,>{
    +   preview(
    +      #if($e.m_backend.m_limbs == 1) (
    +         $e.m_backend.m_wrapper.m_data[0]
    +      )
    +      #elif($e.m_backend.m_limbs == 2) (
    +         $e.m_backend.m_wrapper.m_data[0] | ((__int64)$e.m_backend.m_wrapper.m_data[1] << 32)
    +      ) #else (
    +         #array ( expr: $e.m_backend.m_wrapper.m_data[$e.m_backend.m_limbs - $i - 1], size: $e.m_backend.m_limbs ) : [$e,x]
    +      )
    +   )
    +
    +   children (
    +      #(
    +         ~raw: [$c,!],
    +         #array (
    +               expr: $e.m_backend.m_wrapper.m_data[$e.m_backend.m_limbs - $i - 1],
    +               size: $e.m_backend.m_limbs
    +         ) : [$e,x]
    +      )
    +   )
    +}
    +
    +boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0,0,1,,>,*>{
    +   preview(
    +      #if ($e.m_backend.m_internal) (
    +        #if($e.m_backend.m_limbs == 1) (
    +            #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_data.first) ) #else($e.m_backend.m_data.first)
    +        ) #elif(($e.m_backend.m_limbs == 2) && ($e.m_backend.m_data.la[1] < 0x80000000)) (
    +            #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_data.double_first) ) #else($e.m_backend.m_data.double_first)
    +        ) #else(
    +           #( "signbit = ", $e.m_backend.m_sign, " data = ", #array ( expr: $e.m_backend.m_data.la[$e.m_backend.m_limbs - $i - 1], size: $e.m_backend.m_limbs ) : [$e,x] )
    +        )
    +      ) #else(
    +        #if($e.m_backend.m_limbs == 1) (
    +            #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_data.ld.data[0]) ) #else($e.m_backend.m_data.ld.data[0])
    +        ) #elif(($e.m_backend.m_limbs == 2) && ($e.m_backend.m_data.ld.data[1] < 0x80000000)) (
    +            #if($e.m_backend.m_sign) ( -1 * (__int64)($e.m_backend.m_data.ld.data[0] | ((__int64)$e.m_backend.m_data.ld.data[1] << 32)) ) #else($e.m_backend.m_data.ld.data[0] | ((__int64)$e.m_backend.m_data.ld.data[1] << 32))
    +        ) #else(
    +            #( "signbit = ", $e.m_backend.m_sign, " data = ", #array ( expr: $e.m_backend.m_data.ld.data[$e.m_backend.m_limbs - $i - 1], size: $e.m_backend.m_limbs ) : [$e,x] )
    +        )
    +      )
    +   )
    +
    +   children (
    +      #if ($e.m_backend.m_internal) (
    +        #if($e.m_backend.m_limbs == 1) (
    +            #(value: $e.m_backend.m_data.first)
    +         ) #elif($e.m_backend.m_limbs == 1) (
    +            #(value: $e.m_backend.m_data.double_first)
    +         ) #else (
    +            #(
    +            sign bit: $e.m_backend.m_sign,
    +            #array (
    +                expr: $e.m_backend.m_data.la[$e.m_backend.m_limbs - $i - 1],
    +                size: $e.m_backend.m_limbs
    +            ) : [$e,x]
    +            )
    +         )
    +      ) #else (
    +        #(
    +            ~raw: [$c,!],
    +            sign bit: $e.m_backend.m_sign,
    +            #array (
    +                expr: $e.m_backend.m_data.ld.data[$e.m_backend.m_limbs - $i - 1],
    +                size: $e.m_backend.m_limbs
    +            ) : [$e,x]
    +         )
    +      )
    +   )
    +}
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/index.html b/doc/html/index.html index 20c5e129..0ef82590 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -83,7 +83,12 @@
    rational_adaptor
    Miscellaneous Number Types.
    -
    logged_adaptor
    +
    +
    logged_adaptor
    +
    debug_adaptor
    +
    Visual C++ + Debugger Visualizers
    +
    Constructing and Interconverting Between Number Types
    Generating Random Numbers
    @@ -140,7 +145,7 @@

    - +

    Last revised: January 15, 2013 at 11:39:36 GMT

    Last revised: January 17, 2013 at 12:12:57 GMT


    diff --git a/doc/multiprecision.qbk b/doc/multiprecision.qbk index b9c8bd07..92455b74 100644 --- a/doc/multiprecision.qbk +++ b/doc/multiprecision.qbk @@ -1254,6 +1254,184 @@ When we examine program output we can clearly see that the diameter of the inter [endsect] +[section:debug_adaptor debug_adaptor] + +`#include ` + + namespace boost{ namespace multiprecision{ + + template + class debug_adaptor; + + }} // namespaces + +The `debug_adaptor` type is used in conjunction with `number` and some other backend type: it acts as a thin wrapper around +some other backend to class `number` and intercepts all operations on that object storing the result as a string within itself. + +This type provides `numeric_limits` support whenever the template argument Backend does so. + +This type is particularly useful when your debugger provides a good view of `std::string`: when this is the case +multiprecision values can easily be inspected in the debugger by looking at the `debug_value` member of `debug_adapter`. +The down side of this approach is that runtimes are much slower when using this type. Set against that it can make +debugging very much easier, certainly much easier than sprinkling code with `printf` statements. + +When used in conjunction with the Visual C++ debugger visualisers, the value of a multiprecision type that uses this +backend is displayed in the debugger just a builtin value would be, here we're inspecting a value of type +`number > >`: + +[$../debugger1.png] + +Otherwise you will need to expand out the view and look at the "debug_value" member: + +[$../debugger2.png] + +It works for all the backend types equally too, here it is inspecting a `number >`: + +[$../debugger3.png] + + +[endsect] + +[section:visualizers Visual C++ Debugger Visualizers] + +Let's face it debugger multiprecision numbers is hard - simply because we can't easily inspect the value of the numbers. +Visual C++ provides a partial solution in the shape of "visualizers" which provide improved views of complex data structures, +these visualizers need to be added to the `[Visualizer]` section of `autoexp.dat` located in the `Common7\Packages\Debugger` +directory of your Visual Studio installation. + +[note These visualizers have only been tested with VC10, also given the ability of buggy visualizers to crash your Visual C++ +debugger, make sure you back up `autoexp.dat` file before using these!!] + +This visualizer provides improved views of `debug_adaptor`: + +[pre +boost::multiprecision::number,*>{ + preview( + \#( + \$e.m_backend.debug_value + ) + ) +} +] + +The next visualizer provides improved views of cpp_int: small numbers are displayed as actual values, while larger numbers are +displayed as an array of hexadecimal parts, with the most significant part first. + +Here's what it looks like for small values: + +[$../debugger4.png] + +And for larger values: + +[$../debugger5.png] + +There is also a `~raw` child member that +lets you see the actual members of the class: + +[$../debugger6.png] + +Here's the visualizer code: + +[pre +boost::multiprecision::number,*>{ + preview( + \#if(\$e.m_backend.m_limbs == 1) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_wrapper.m_data\[0\]) ) \#else (\$e.m_backend.m_wrapper.m_data\[0\]) + ) + \#elif((\$e.m_backend.m_limbs == 2) && (\$e.m_backend.m_wrapper.m_data\[1\] < 0x80000000)) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_wrapper.m_data\[0\] | ((__int64)\$e.m_backend.m_wrapper.m_data\[1\] << 32)) ) \#else (\$e.m_backend.m_wrapper.m_data\[0\] | ((__int64)\$e.m_backend.m_wrapper.m_data\[1\] << 32)) + ) \#else ( + \#( "signbit = ", \$e.m_backend.m_sign, " data = ", \#array ( expr: \$e.m_backend.m_wrapper.m_data\[\$e.m_backend.m_limbs - \$i - 1\], size: \$e.m_backend.m_limbs ) : \[\$e,x\] ) + ) + ) + + children ( + \#( + \~raw: \[\$c,!\], + sign bit: \$e.m_backend.m_sign, + \#array ( + expr: \$e.m_backend.m_wrapper.m_data\[\$e.m_backend.m_limbs - \$i - 1\], + size: \$e.m_backend.m_limbs + ) : \[\$e,x\] + ) + ) +} + +boost::multiprecision::number,*>{ + preview( + \#if(\$e.m_backend.m_limbs == 1) ( + \$e.m_backend.m_wrapper.m_data\[0\] + ) + \#elif(\$e.m_backend.m_limbs == 2) ( + \$e.m_backend.m_wrapper.m_data\[0\] | ((__int64)\$e.m_backend.m_wrapper.m_data\[1\] << 32) + ) \#else ( + \#array ( expr: \$e.m_backend.m_wrapper.m_data\[\$e.m_backend.m_limbs - \$i - 1\], size: \$e.m_backend.m_limbs ) : \[\$e,x\] + ) + ) + + children ( + \#( + \~raw: \[\$c,!\], + \#array ( + expr: \$e.m_backend.m_wrapper.m_data\[\$e.m_backend.m_limbs - \$i - 1\], + size: \$e.m_backend.m_limbs + ) : \[\$e,x\] + ) + ) +} + +boost::multiprecision::number,*>{ + preview( + \#if (\$e.m_backend.m_internal) ( + \#if(\$e.m_backend.m_limbs == 1) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_data.first) ) \#else(\$e.m_backend.m_data.first) + ) \#elif((\$e.m_backend.m_limbs == 2) && (\$e.m_backend.m_data.la\[1\] < 0x80000000)) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_data.double_first) ) \#else(\$e.m_backend.m_data.double_first) + ) \#else( + \#( "signbit = ", \$e.m_backend.m_sign, " data = ", \#array ( expr: \$e.m_backend.m_data.la\[\$e.m_backend.m_limbs - \$i - 1\], size: \$e.m_backend.m_limbs ) : \[\$e,x\] ) + ) + ) \#else( + \#if(\$e.m_backend.m_limbs == 1) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_data.ld.data\[0\]) ) \#else(\$e.m_backend.m_data.ld.data\[0\]) + ) \#elif((\$e.m_backend.m_limbs == 2) && (\$e.m_backend.m_data.ld.data\[1\] < 0x80000000)) ( + \#if(\$e.m_backend.m_sign) ( -1 * (__int64)(\$e.m_backend.m_data.ld.data\[0\] | ((__int64)\$e.m_backend.m_data.ld.data\[1\] << 32)) ) \#else(\$e.m_backend.m_data.ld.data\[0\] | ((__int64)\$e.m_backend.m_data.ld.data\[1\] << 32)) + ) \#else( + \#( "signbit = ", \$e.m_backend.m_sign, " data = ", \#array ( expr: \$e.m_backend.m_data.ld.data\[\$e.m_backend.m_limbs - \$i - 1\], size: \$e.m_backend.m_limbs ) : \[\$e,x\] ) + ) + ) + ) + + children ( + \#if (\$e.m_backend.m_internal) ( + \#if(\$e.m_backend.m_limbs == 1) ( + \#(value: \$e.m_backend.m_data.first) + ) \#elif(\$e.m_backend.m_limbs == 1) ( + \#(value: \$e.m_backend.m_data.double_first) + ) \#else ( + \#( + sign bit: \$e.m_backend.m_sign, + \#array ( + expr: \$e.m_backend.m_data.la\[\$e.m_backend.m_limbs - \$i - 1\], + size: \$e.m_backend.m_limbs + ) : \[\$e,x\] + ) + ) + ) \#else ( + \#( + \~raw: \[\$c,!\], + sign bit: \$e.m_backend.m_sign, + \#array ( + expr: \$e.m_backend.m_data.ld.data\[\$e.m_backend.m_limbs - \$i - 1\], + size: \$e.m_backend.m_limbs + ) : \[\$e,x\] + ) + ) + ) +} +] + +[endsect] + [endsect] [section:conversions Constructing and Interconverting Between Number Types] diff --git a/example/debug_adaptor_snips.cpp b/example/debug_adaptor_snips.cpp new file mode 100644 index 00000000..8de85dcf --- /dev/null +++ b/example/debug_adaptor_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() +{ + //[debug_adaptor_eg + //=#include + //=#include + + using namespace boost::multiprecision; + + typedef number > > fp_type; + + fp_type denom = 1; + fp_type sum = 1; + + for(unsigned i = 2; i < 50; ++i) + { + denom *= i; + sum += 1 / denom; + } + + std::cout << std::setprecision(std::numeric_limits::digits) << sum << std::endl; + //] +} + +int main() +{ + t1(); + return 0; +} + + + diff --git a/include/boost/multiprecision/debug_adaptor.hpp b/include/boost/multiprecision/debug_adaptor.hpp new file mode 100644 index 00000000..d7987a12 --- /dev/null +++ b/include/boost/multiprecision/debug_adaptor.hpp @@ -0,0 +1,453 @@ +/////////////////////////////////////////////////////////////// +// 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_DEBUG_ADAPTER_HPP +#define BOOST_MATH_DEBUG_ADAPTER_HPP + +#include + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +template +struct debug_adaptor +{ + typedef typename Backend::signed_types signed_types; + typedef typename Backend::unsigned_types unsigned_types; + typedef typename Backend::float_types float_types; + typedef typename extract_exponent_type< + Backend, number_category::value>::type exponent_type; + +private: + std::string debug_value; + Backend m_value; +public: + void update_view() + { + try + { + debug_value = m_value.str(0, static_cast(0)); + } + catch(const std::exception& e) + { + debug_value = "String conversion failed with message: \""; + debug_value += e.what(); + debug_value += "\""; + } + } + debug_adaptor() + { + update_view(); + } + debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value) + { + } + debug_adaptor& operator = (const debug_adaptor& o) + { + debug_value = o.debug_value; + m_value = o.m_value; + return *this; + } + template + debug_adaptor(const T& i, const typename enable_if_c::value>::type* = 0) + : m_value(i) + { + update_view(); + } + template + debug_adaptor(const T& i, const T& j) + : m_value(i, j) + { + update_view(); + } + template + typename enable_if_c::value || is_convertible::value, debug_adaptor&>::type operator = (const T& i) + { + m_value = i; + update_view(); + return *this; + } + debug_adaptor& operator = (const char* s) + { + m_value = s; + update_view(); + return *this; + } + void swap(debug_adaptor& o) + { + std::swap(m_value, o.value()); + std::swap(debug_value, o.debug_value); + } + std::string str(std::streamsize digits, std::ios_base::fmtflags f)const + { + return m_value.str(digits, f); + } + void negate() + { + m_value.negate(); + update_view(); + } + int compare(const debug_adaptor& o)const + { + return m_value.compare(o.value()); + } + template + int compare(const T& i)const + { + return m_value.compare(i); + } + Backend& value() + { + return m_value; + } + const Backend& value()const + { + return m_value; + } +}; + +template +inline Backend const& unwrap_debug_type(debug_adaptor const& val) +{ + return val.value(); +} +template +inline const T& unwrap_debug_type(const T& val) +{ + return val; +} + +#define NON_MEMBER_OP1(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value());\ + result.update_view();\ + } + +#define NON_MEMBER_OP2(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\ + result.update_view();\ + } + +#define NON_MEMBER_OP3(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const U& b)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const debug_adaptor& b)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ + result.update_view();\ + } + +#define NON_MEMBER_OP4(name, str) \ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const U& b, const V& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b, const T& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b, const debug_adaptor& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const debug_adaptor& b, const debug_adaptor& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b, const debug_adaptor& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + template \ + inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b, const U& c)\ + {\ + using default_ops::BOOST_JOIN(eval_, name);\ + BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ + result.update_view();\ + }\ + +NON_MEMBER_OP2(add, "+="); +NON_MEMBER_OP2(subtract, "-="); +NON_MEMBER_OP2(multiply, "*="); +NON_MEMBER_OP2(divide, "/="); + +template +inline void eval_convert_to(R* result, const debug_adaptor& val) +{ + using default_ops::eval_convert_to; + eval_convert_to(result, val.value()); +} + +template +inline void eval_frexp(debug_adaptor& result, const debug_adaptor& arg, Exp* exp) +{ + eval_frexp(result.value(), arg.value(), exp); + result.update_view();\ +} + +template +inline void eval_ldexp(debug_adaptor& result, const debug_adaptor& arg, Exp exp) +{ + eval_ldexp(result.value(), arg.value(), exp); + result.update_view();\ +} + +NON_MEMBER_OP2(floor, "floor"); +NON_MEMBER_OP2(ceil, "ceil"); +NON_MEMBER_OP2(sqrt, "sqrt"); + +template +inline int eval_fpclassify(const debug_adaptor& arg) +{ + using default_ops::eval_fpclassify; + return eval_fpclassify(arg.value()); +} + +/********************************************************************* +* +* Optional arithmetic operations come next: +* +*********************************************************************/ + +NON_MEMBER_OP3(add, "+"); +NON_MEMBER_OP3(subtract, "-"); +NON_MEMBER_OP3(multiply, "*"); +NON_MEMBER_OP3(divide, "/"); +NON_MEMBER_OP3(multiply_add, "fused-multiply-add"); +NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract"); +NON_MEMBER_OP4(multiply_add, "fused-multiply-add"); +NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract"); + +NON_MEMBER_OP1(increment, "increment"); +NON_MEMBER_OP1(decrement, "decrement"); + +/********************************************************************* +* +* Optional integer operations come next: +* +*********************************************************************/ + +NON_MEMBER_OP2(modulus, "%="); +NON_MEMBER_OP3(modulus, "%"); +NON_MEMBER_OP2(bitwise_or, "|="); +NON_MEMBER_OP3(bitwise_or, "|"); +NON_MEMBER_OP2(bitwise_and, "&="); +NON_MEMBER_OP3(bitwise_and, "&"); +NON_MEMBER_OP2(bitwise_xor, "^="); +NON_MEMBER_OP3(bitwise_xor, "^"); +NON_MEMBER_OP4(qr, "quotient-and-remainder"); +NON_MEMBER_OP2(complement, "~"); + +template +inline void eval_left_shift(debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_left_shift; + eval_left_shift(arg.value(), a); + arg.update_view();\ +} +template +inline void eval_left_shift(debug_adaptor& arg, const debug_adaptor& a, unsigned b) +{ + using default_ops::eval_left_shift; + eval_left_shift(arg.value(), a, b); + arg.update_view();\ +} +template +inline void eval_right_shift(debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_right_shift; + eval_right_shift(arg.value(), a); + arg.update_view();\ +} +template +inline void eval_right_shift(debug_adaptor& arg, const debug_adaptor& a, unsigned b) +{ + using default_ops::eval_right_shift; + eval_right_shift(arg.value(), a, b); + arg.update_view();\ +} + +template +inline unsigned eval_integer_modulus(const debug_adaptor& arg, const T& a) +{ + using default_ops::eval_integer_modulus; + return eval_integer_modulus(arg.value(), a); +} + +template +inline unsigned eval_lsb(const debug_adaptor& arg) +{ + using default_ops::eval_lsb; + return eval_lsb(arg.value()); +} + +template +inline bool eval_bit_test(const debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_bit_test; + return eval_bit_test(arg.value(), a); +} + +template +inline void eval_bit_set(const debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_bit_set; + eval_bit_set(arg.value(), a); + arg.update_view();\ +} +template +inline void eval_bit_unset(const debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_bit_unset; + eval_bit_unset(arg.value(), a); + arg.update_view();\ +} +template +inline void eval_bit_flip(const debug_adaptor& arg, unsigned a) +{ + using default_ops::eval_bit_flip; + eval_bit_flip(arg.value(), a); + arg.update_view();\ +} + +NON_MEMBER_OP3(gcd, "gcd"); +NON_MEMBER_OP3(lcm, "lcm"); +NON_MEMBER_OP4(powm, "powm"); + +/********************************************************************* +* +* abs/fabs: +* +*********************************************************************/ + +NON_MEMBER_OP2(abs, "abs"); +NON_MEMBER_OP2(fabs, "fabs"); + +/********************************************************************* +* +* Floating point functions: +* +*********************************************************************/ + +NON_MEMBER_OP2(trunc, "trunc"); +NON_MEMBER_OP2(round, "round"); +NON_MEMBER_OP2(exp, "exp"); +NON_MEMBER_OP2(log, "log"); +NON_MEMBER_OP2(log10, "log10"); +NON_MEMBER_OP2(sin, "sin"); +NON_MEMBER_OP2(cos, "cos"); +NON_MEMBER_OP2(tan, "tan"); +NON_MEMBER_OP2(asin, "asin"); +NON_MEMBER_OP2(acos, "acos"); +NON_MEMBER_OP2(atan, "atan"); +NON_MEMBER_OP2(sinh, "sinh"); +NON_MEMBER_OP2(cosh, "cosh"); +NON_MEMBER_OP2(tanh, "tanh"); +NON_MEMBER_OP3(fmod, "fmod"); +NON_MEMBER_OP3(pow, "pow"); +NON_MEMBER_OP3(atan2, "atan2"); + +} // namespace backends + +using backends::debug_adaptor; + +template +struct number_category > : public number_category {}; + +}} // namespaces + +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: + 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(); } +}; + +} // namespace std + +namespace boost{ namespace math{ + +namespace policies{ + +template +struct precision< boost::multiprecision::number, ExpressionTemplates>, Policy> + : public precision, Policy> +{}; + +#undef NON_MEMBER_OP1 +#undef NON_MEMBER_OP2 +#undef NON_MEMBER_OP3 +#undef NON_MEMBER_OP4 + +} // namespace policies + +}} // namespaces boost::math + + +#endif diff --git a/include/boost/multiprecision/logged_adaptor.hpp b/include/boost/multiprecision/logged_adaptor.hpp index b57b8255..ebc558ee 100644 --- a/include/boost/multiprecision/logged_adaptor.hpp +++ b/include/boost/multiprecision/logged_adaptor.hpp @@ -6,7 +6,7 @@ #ifndef BOOST_MATH_LOGGED_ADAPTER_HPP #define BOOST_MATH_LOGGED_ADAPTER_HPP -#include +#include namespace boost{ namespace multiprecision{ @@ -38,17 +38,6 @@ inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const namespace backends{ -template -struct extract_exponent_type -{ - typedef int type; -}; -template -struct extract_exponent_type -{ - typedef typename Backend::exponent_type type; -}; - template struct logged_adaptor { @@ -298,6 +287,7 @@ NON_MEMBER_OP2(sqrt, "sqrt"); template inline int eval_fpclassify(const logged_adaptor& arg) { + using default_ops::eval_fpclassify; log_prefix_event(arg.value(), "fpclassify"); int r = eval_fpclassify(arg.value()); log_postfix_event(arg.value(), r, "fpclassify"); @@ -508,5 +498,9 @@ struct precision< boost::multiprecision::number + +namespace boost{ +namespace multiprecision{ +namespace backends{ + +template +struct extract_exponent_type +{ + typedef int type; +}; +template +struct extract_exponent_type +{ + typedef typename Backend::exponent_type type; +}; + +}}} // namespaces + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a238698f..96fb2555 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -104,6 +104,9 @@ run test_arithmetic_ab_3.cpp ; run test_arithmetic_logged_1.cpp ; run test_arithmetic_logged_2.cpp ; +run test_arithmetic_dbg_adptr1.cpp ; +run test_arithmetic_dbg_adptr2.cpp ; + run test_arithmetic_mpfi_50.cpp mpfi mpfr gmp : : : [ check-target-builds ../config//has_mpfi : : no ] ; run test_numeric_limits.cpp diff --git a/test/test_arithmetic_dbg_adptr1.cpp b/test/test_arithmetic_dbg_adptr1.cpp new file mode 100644 index 00000000..88fdc5aa --- /dev/null +++ b/test/test_arithmetic_dbg_adptr1.cpp @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////// +// 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_arithmetic.hpp" + +int main() +{ + test > > >(); + return boost::report_errors(); +} + diff --git a/test/test_arithmetic_dbg_adptr2.cpp b/test/test_arithmetic_dbg_adptr2.cpp new file mode 100644 index 00000000..47b5529a --- /dev/null +++ b/test/test_arithmetic_dbg_adptr2.cpp @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////// +// 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_arithmetic.hpp" + +int main() +{ + test > > >(); + return boost::report_errors(); +} +