[boost] [review] Multiprecision review scheduled for June 8th - 17th, 2012

Hi all, The review of the proposed Boost.Multiprecision library authored by John Maddock and Christopher Kormanyos has been scheduled for June 8th - June 17th, 2012 and will be managed by myself.
From the 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." -------- And from the original formal review request from John: -------- Features: * Expression template enabled front end. * Support for Integer, Rational and Floating Point types. Supported Integer backends: * GMP. * Libtommath. * cpp_int. cpp_int is an all C++ Boost licensed backend, supports both arbitrary precision types (with Allocator support), and signed and unsigned fixed precision types (with no memory allocation). There are also some integer specific functions - for Miller Rabin testing, bit fiddling, random numbers. Plus interoperability with Boost.Rational (though that loses the expression template frontend). Supported Rational Backends: * GMP * libtommath * cpp_int (as above) Supported Floating point backends: * GMP * MPFR * cpp_dec_float cpp_dec_float is an all C++ Boost licensed type, adapted from Christopher Kormanyos' e_float code (published in TOMS last year). All the floating point types, have full std lib support (cos sin exp, pow etc), as well as full interoperability with Boost.Math. There's nothing in principal to prevent extension to complex numbers and interval arithmetic types (plus any other number types I've forgotten!), but I've run out of energy for now ;-) Code is in the sandbox under /big_number/. Docs can be viewed online here: http://svn.boost.org/svn/boost/sandbox/big_number/libs/multiprecision/doc/ht... -------- I hope everyone interested can reserve some time to read through the documentation, try the code out, and post a formal review, either during the formal review window or before. I expect to conduct the review in the "traditional" manner, i.e., entirely within the regular boost developers' mailing list (boost@lists.boost.org). I will send a reminder of review process details closer to the review window. Thanks! - Jeff

Hi all,
The review of the proposed Boost.Multiprecision library authored by John Maddock and Christopher Kormanyos has been scheduled for
June 8th - June 17th, 2012
and will be managed by myself.
I hope everyone interested can reserve some time to read through the documentation, try the code out, and post a formal review, either during
Le 29/05/12 23:08, Jeffrey Lee Hellrung, Jr. a écrit : the formal review window or before.
Hi, glad to see that the library will be reviewed soon. I have spent some hours reading the documentation. Here are some comments and a lot of questions. * As all the classes are at the multi-precision namespace, why name the main class mp_number and not just number? typedef mp::number<mp::mpfr_float_backend<300> > my_float; * I think that the fact that operands of different backends can not be mixed on the same operation limits some interesting operations: I would expect the result of unary operator-() always signed? Is this operation defined for signed backends? I would expect the result of binary operator-() always signed? Is this operation defined for signed backends? what is the behavior of mp_uint128_t(0) - mp_uint128_t(1)? It would be great if the tutorial could show that it is possible however to add a mp_uint128_t and a mp_int256_t, or isn't it possible? I guess this is possible, but a conversion is needed before adding the operands. I don't know if this behavior is not hiding some possible optimizations. I think it should be possible to mix backends without too much complexity and that the library could provide the mechanism so that the backend developer could tell to the library about how to perform the operation and what should be the result. * Anyway, if the library authors don't want to open to this feature, the limitation should be stated more clearly, e.g in the reference documentation "The arguments to these functions must contain at least one of the following: An mp_number. An expression template type derived from mp_number. " there is nothing that let think mixing backend is not provided. * What about replacing the second bool template parameter by an enum class expression_template {disabled, enabled}; which will be more explicit. That is typedef mp::mp_number<mp::mpfr_float_backend<300>, false> my_float; versus typedef mp::mp_number<mp::mpfr_float_backend<300>, mp::expression_template::disabled> my_float; * As I posted in this ML already I think that allocators and precision are orthogonal concepts and the library should allow to associate one for fixed precision. What about adding a 3rd parameter to state if it is fixed or arbitrary precision? * Why cpp_dec_float doesn't have a template parameter to give the integral digits? or as the C++ standard proposal from Lawrence Crow (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html), take the range and resolution as template parameters? * What about adding Throws specification on the mp_number and backend requirements operations documentation? * Can the user define a backend for fixed int types that needs to manage with overflow? * Why bit_set is a free function? * I don't see nothing about overflow for cpp_dec_float backend operations. I guess it is up to the user to avoid overflow as for integers. what would be the result on overflow? Could this be added to the documentation? * can we convert from a cpp_dec_float_100 to a cpp_dec_float_50? if yes, which rounding policy is applied? Do you plan to let the user configure the rounding policy? BTW, I see in the reference "Type mp_number is default constructible, and both copy constructible and assignable from: ... Any type that the Backend is constructible or assignable from. " I would expect to have this information in some way on the tutorial. I will appreciate also if section "Constructing and Interconverting Between Number Types" says something about convert_to<T> member function. If not, what about a mp_number_cast function taking as parameter a rounding policy? * Does the cpp_dec_float back end satisfies any of the Optional Requirements? The same question for the other backends? * Is there a difference between implicit and explicit construction? * On c++11 compilers providing explicit conversion, couldn't the convert_to function be replaced by a explicit conversion operator? * Are implicit conversion possible? * Do you plan to add constexpr and noexcept to the interface? After thinking a little bit I'm wondering if this is this possible when using 3pp libraries backends that don't provide them? * Why do you allow the argument of left and right shift operations to be signed and throw an exception when negative? Why don't just forbid it for signed types? * Why the "Non-member standard library function support" can be used only with floating-point Backend types? Why not with fixed-point types? * What is the type of boost::multiprecision::number_category<B>::type for all the provided backends? Could the specialization for boost::multiprecision::number_category<B>::type be added in the documentation of each backend? and why not add also B::signed_types, B::unsigned_types, B::float_types, B::exponent_type? * Why have you chosen the following requirements for the backend? - negate instead of operator-() - eval_op instead of operator op=() - eval_convert_to instead of explicit operator T() - eval_floor instead of floor Optimization? Is this optimization valid for short types (e.g. up to 4/8 bytes)? * As the developer needs to define a class with some constraints to be a model of backend, which are the advantages of requiring free functions instead of member functions? * Couldn't these be optional if the backend defines the usual operations? * Or could the library provide a trivial backend adaptor that requires the backend just to provide the usual operations instead of the eval_xxx? * How the performances of mp_number<this_trivial_adaptor<float>, false> will compare with float? * And last, I don't see anything related to rvalue references and move semantics. Have you analyzed if its use could improve the performances of the library? Good luck for the review. A really good work. Vicente

Just to preempt this, I think it will be more appropriate for any review discussions to take place on the developers' list (boost@lists.boost.org). On Wed, May 30, 2012 at 2:38 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Hi all,
The review of the proposed Boost.Multiprecision library authored by John Maddock and Christopher Kormanyos has been scheduled for
June 8th - June 17th, 2012
and will be managed by myself.
I hope everyone interested can reserve some time to read through the documentation, try the code out, and post a formal review, either during
Le 29/05/12 23:08, Jeffrey Lee Hellrung, Jr. a écrit : the formal review window or before.
Hi,
glad to see that the library will be reviewed soon.
I have spent some hours reading the documentation. Here are some comments and a lot of questions.
* As all the classes are at the multi-precision namespace, why name the main class mp_number and not just number?
typedef mp::number<mp::mpfr_float_**backend<300> > my_float;
* I think that the fact that operands of different backends can not be mixed on the same operation limits some interesting operations:
I would expect the result of unary operator-() always signed? Is this operation defined for signed backends? I would expect the result of binary operator-() always signed? Is this operation defined for signed backends? what is the behavior of mp_uint128_t(0) - mp_uint128_t(1)?
It would be great if the tutorial could show that it is possible however to add a mp_uint128_t and a mp_int256_t, or isn't it possible? I guess this is possible, but a conversion is needed before adding the operands. I don't know if this behavior is not hiding some possible optimizations.
I think it should be possible to mix backends without too much complexity and that the library could provide the mechanism so that the backend developer could tell to the library about how to perform the operation and what should be the result.
* Anyway, if the library authors don't want to open to this feature, the limitation should be stated more clearly, e.g in the reference documentation "The arguments to these functions must contain at least one of the following:
An mp_number. An expression template type derived from mp_number. " there is nothing that let think mixing backend is not provided.
* What about replacing the second bool template parameter by an enum class expression_template {disabled, enabled}; which will be more explicit. That is
typedef mp::mp_number<mp::mpfr_float_**backend<300>, false> my_float;
versus
typedef mp::mp_number<mp::mpfr_float_**backend<300>, mp::expression_template::**disabled> my_float;
* As I posted in this ML already I think that allocators and precision are orthogonal concepts and the library should allow to associate one for fixed precision. What about adding a 3rd parameter to state if it is fixed or arbitrary precision?
* Why cpp_dec_float doesn't have a template parameter to give the integral digits? or as the C++ standard proposal from Lawrence Crow ( http://www.open-std.org/jtc1/**sc22/wg21/docs/papers/2012/**n3352.html<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html>), take the range and resolution as template parameters?
* What about adding Throws specification on the mp_number and backend requirements operations documentation?
* Can the user define a backend for fixed int types that needs to manage with overflow?
* Why bit_set is a free function?
* I don't see nothing about overflow for cpp_dec_float backend operations. I guess it is up to the user to avoid overflow as for integers. what would be the result on overflow? Could this be added to the documentation?
* can we convert from a cpp_dec_float_100 to a cpp_dec_float_50? if yes, which rounding policy is applied? Do you plan to let the user configure the rounding policy? BTW, I see in the reference "Type mp_number is default constructible, and both copy constructible and assignable from: ... Any type that the Backend is constructible or assignable from. " I would expect to have this information in some way on the tutorial. I will appreciate also if section "Constructing and Interconverting Between Number Types" says something about convert_to<T> member function.
If not, what about a mp_number_cast function taking as parameter a rounding policy?
* Does the cpp_dec_float back end satisfies any of the Optional Requirements? The same question for the other backends?
* Is there a difference between implicit and explicit construction? * On c++11 compilers providing explicit conversion, couldn't the convert_to function be replaced by a explicit conversion operator? * Are implicit conversion possible?
* Do you plan to add constexpr and noexcept to the interface? After thinking a little bit I'm wondering if this is this possible when using 3pp libraries backends that don't provide them?
* Why do you allow the argument of left and right shift operations to be signed and throw an exception when negative? Why don't just forbid it for signed types?
* Why the "Non-member standard library function support" can be used only with floating-point Backend types? Why not with fixed-point types?
* What is the type of boost::multiprecision::number_**category<B>::type for all the provided backends? Could the specialization for boost::multiprecision::number_**category<B>::type be added in the documentation of each backend? and why not add also B::signed_types, B::unsigned_types, B::float_types, B::exponent_type?
* Why have you chosen the following requirements for the backend? - negate instead of operator-() - eval_op instead of operator op=() - eval_convert_to instead of explicit operator T() - eval_floor instead of floor
Optimization? Is this optimization valid for short types (e.g. up to 4/8 bytes)?
* As the developer needs to define a class with some constraints to be a model of backend, which are the advantages of requiring free functions instead of member functions? * Couldn't these be optional if the backend defines the usual operations? * Or could the library provide a trivial backend adaptor that requires the backend just to provide the usual operations instead of the eval_xxx? * How the performances of mp_number<this_trivial_**adaptor<float>, false> will compare with float?
* And last, I don't see anything related to rvalue references and move semantics. Have you analyzed if its use could improve the performances of the library?
Good luck for the review. A really good work. Vicente
______________________________**_________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/**mailman/listinfo.cgi/boost-**users<http://lists.boost.org/mailman/listinfo.cgi/boost-users>

Hi, what should be the result of template <int N> void test1() { boost::io::ios_precision_saver ifs( std::cout ); using namespace boost::multiprecision; mp_number<cpp_dec_float<N> > a(mp_number<cpp_dec_float<N> >(1) / 3); std::cout << "N= " << N << std::endl; std::cout << "max_digits10= " << std::numeric_limits<mp_number<cpp_dec_float<N> > >::max_digits10 << std::endl; std::cout << "sizeof= " << sizeof(mp_number<cpp_dec_float<N> > ) << std::endl; std::cout << " " << a << std::endl; std::cout << "setprecision(N) " << std::setprecision(N) << a << std::endl; std::cout << "setprecision(max_digits10)= " << std::setprecision(std::numeric_limits<mp_number<cpp_dec_float<N> >
::max_digits10) << a << std::endl; }
test1<50>(); test1<100>(); test1<1>(); I'm getting N= 50 max_digits10= 80 sizeof= 64 0.333333 setprecision(N) 0.33333333333333333333333333333333333333333333333333 setprecision(max_digits10)= 0.33333333333333333333333333333333333333333333333333333333333333333333333333333333 N= 100 max_digits10= 128 sizeof= 88 0.333333 setprecision(N) 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 setprecision(max_digits10)= 0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 N= 1 max_digits10= 40 sizeof= 48 0.333333 setprecision(N) 0.3 setprecision(max_digits10)= 0.3333333333333333333333333333333333333333 Why the max_digits10 are not respectively 50,100 and 1? The single think in the documentation that could let think the number of digits to be greater than the parameter is the *should* word in the sentence "The class takes a single template parameter - |Digits10| - which is the number of decimal digits precision the type *should* support." Could the documentation be more precise? Is there a way to request for exactly N decimal digits to minimize the sizeof? Best, Vicente

Why the max_digits10 are not respectively 50,100 and 1?
numeric_limits<>::digits10 are those values.
The single think in the documentation that could let think the number of digits to be greater than the parameter is the *should* word in the sentence "The class takes a single template parameter - |Digits10| - which is the number of decimal digits precision the type *should* support." Could the documentation be more precise?
Is there a way to request for exactly N decimal digits to minimize the sizeof?
No, Chris has added a number of guard digits to the implementation of cpp_dec_float and there's no way to force it not to use these. Chris can better explain why they're needed. That's also why max_digits10 > digits10. John.
participants (3)
-
Jeffrey Lee Hellrung, Jr.
-
John Maddock
-
Vicente J. Botet Escriba