
Thank you once again for your detailed report, Vicente.
I have spent some hours reading the documentation. Here are some comments and a lot of questions.
Did you get a chance to use it also? You always have such good comments, that we would benefit from some your experience with use-cases.
I would like to create a backend for my fixed_point library before the review.
Wow! That was fast. It seems like just yesterday when we were preliminarily talking about your development.
I have run the test and I'm getting a lot of errors for test_float_io_cpp_dec_float bjam toolset=clang-2.9,clang-2.9x -j2
Precision is: 13 Got: -987654312.0000000000000 Expected: -0.0000000008567 Testing value -8.5665356058806096939e-10 Formatting flags were: fixed showpos Precision is: 13 Got: -987654312.0000000000000 Expected: -0.0000000008567 9360 errors detected.
EXIT STATUS: 1 ====== END OUTPUT ======
OK. This one looks like a real nugget of a find. You can never do enough testing. I just ran the tests on Visual Studio 2010 and they all pass. I don't have clang but if we can't track this down relatively easily, I can build it. The error report tells me a few things. * The number is completely wrong. So it's not just a rounding thing. * It might be related to the conversion to string. * On the other hand, it could be related to the actual algorithms. Before I download and build that compiler from source, could you please do two things for me? 1) Could you please zip and send the entire error text? Or if all 9360 errors are simply too big of a file, maybe the first 1000 error text messages or so. I would like to see if there is a visible trend in the kinds of numbers failing. 2) Could you please (with your compiler) create the reported number from string as cpp_dec_float_50(" -8.5665356058806096939e-10")? Then simply print it out with precision(13), fixed and showpos. This helps me see if the error is merely in printout or rather goes deeper into the class algorithms. I used the code below and got a sensible result of -0.0000000008567. #include <iomanip> #include <iostream> #include <boost/multiprecision/cpp_dec_float.hpp> int main(int, char**) { boost::multiprecision::cpp_dec_float_50 x("-8.5665356058806096939e-10"); std::cout << std::setprecision(13) << std::fixed << std::showpos << x << std::endl; }
and others like
darwin.compile.c++ bin/floating_point_examples.test/darwin-4.2.1/debug/floating_point_examples.o ../example/floating_point_examples.cpp:11:17: error: array: No such file or directory ../example/floating_point_examples.cpp: In function 'mp_type mysin(const mp_type&)': ../example/floating_point_examples.cpp:361: error: expected initializer before '<' token ../example/floating_point_examples.cpp:666: error: expected `}' at end of input
"g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -dynamic -gdwarf-2 -fexceptions -fPIC -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/floating_point_examples.test/darwin-4.2.1/debug> /floating_point_examples.o" "../example/floating_point_examples.cpp"
These are easy to understand. It's probably *my bad* on this one because I used some of C++11 in selected samples. For example, in the polynomial expansion of my_sin(), I use std::array. In the functional derivative and integral examples, I use a C++11 anonymous (lambda) function. Please tell me if I need to avoid using C++11 in the examples due to boost policy. I would like to use these examples because they exhibit where I want to go with the language. But if boost policy demands, I can re-write for C++03.
Accordingly, we do support this:
boost::multiprecision::cpp_dec_float_100 a(boost::multiprecision::cpp_dec_float_100(123) / 100); boost::multiprecision::cpp_dec_float_50 b(boost::multiprecision::cpp_dec_float_50(456) / 100); boost::multiprecision::cpp_dec_float_50 c = boost::multiprecision::cpp_dec_float_50(a) * b;
But we do not support this:
boost::multiprecision::cpp_dec_float_100 a(boost::multiprecision::cpp_dec_float_100(123) / 100); boost::multiprecision::cpp_dec_float_50 b(boost::multiprecision::cpp_dec_float_50(456) / 100); boost::multiprecision::cpp_dec_float_50 c = a * b;
This is OK as there is no implicit conversion from cpp_dec_float_100 to cpp_dec_float_50. But I would expect
boost::multiprecision::cpp_dec_float_100 d = a * b; to compile, but it doesn't. Why the implicit conversion from cpp_dec_float_50 to cpp_dec_float_100 doesn't helps?
Well, I guess this is simply a design choice. At this time, we decided to prohibit both narrowing as well as widening implicit conversion of binary arithmetic operations. This means that you need to explicitly convert both larger as well as smaller digit ranges in binary arithmetic operations. For example, boost::multiprecision::cpp_dec_float_100 d = a * boost::multiprecision::cpp_dec_float_100(b);
To be quite honest, I do not have the time to work out a sensible rounding scheme for the base-10 back-end in a reasonable time schedule. One of the difficulties of base-10 is its unruly nature regarding rounding.
I understand your words as, the user can not configure the way rounding is done. But AFAIU it is valid to do a conversion, so the documentation should add which kind of rounding is applied.
<snip>
so I guess the rounding is towards zero.
Yes. you are right. My previous post was also misleading. The cpp_dec_float back-end does not round on operations or conversions from 50 to 100 digits, etc. It does, however, round when preparing an output string. I believe that I used round-to-zero. John has indicated a slight preference not to document these internal details.
I see the present review candidate of Boost.Multiprecision as a good start on a long-term development with many potential future improvements.
In particular, my long-term goal with a potential Boost.Multiprecision is to create a greatly improved base-2 floating-point back-end in the future. At that time, I would want to target vastly improved performance, sensible allocation/deallocation, clear rounding semantics, etc.
One of the advantages of John's architecture is that mp_number can be used with any back-end fulfilling the requirements. So one could potentially phase out cpp_dec_float via deprecation in the future and support a future cpp_bin_float.
Yes, having a common interface is a good thing and it can be obtained with different approaches. I believe the main goal of mp_number is to put in a common class the expression templates.
Yes. The whole of Boost.Multiprecision is, however, larger in its scope. It also should provide BPL big number float, integer and rational support. And as soon as we make more progress with fixed-point, then that as well. Today's collection of back-ends is sort of jumbled. But mp_number puts a generic interface on them. My future goal is to improve the floating-point back-end and also try to find any sensible unification for integer, float, rational and fixed-point. This goal does, however, go far beyond the scope of the upcoming review.
Or *round_to_zero* instead of *no rounding*. OK.
* 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? I'm also not sure if it's possible, or even what we would gain - I can't
offhand think of any interfaces that could use constexp for example. If you are aiming at compile-time constant mp_numbers, then I do not believe it is possible with the specified low-complexity constraints a constexpr functions and objects.
This works with state-of-the-art compilers today. constexpr double pi = 3.14159265358979323846
But this may not work soon, or ever. constexpr boost::multiprecision::cpp_dec_float_50 pi("3.14159265358979323846264338327950288419716939937510582097494");
Not all operations can be defined as constexpr but I will expect some to be. constexpr boost::multiprecision::cpp_dec_float_50 pi(3.14159265358979323846);
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3352.html propose also to have some kind of literals through some factory methods. |to_nonnegative<2884,-4>()| will produce a |nonnegative| constant with a range and resolution just sufficient to hold the value 2884*2^-4. I don't know if this kind of factories could be applicable to the current backends.
I suspect it can not be applied to the current back-ends because the creation of a big number from a string or a built-in type simply exceeds the low-complexity limit required for constexpr. Maybe I'm wrong here. Your idea is certainly a valid goal to look for in the future.
* How the performances of mp_number<this_trivial_adaptor<float>, false> will compare with float? No idea, might be interesting to find out, will investigate. I never tested it yet. It interests me as well for my research in generic numeric programming.
Let us know as soon as you have some results. Best, Vicente
OK. I need to find a day for the benchmark. Best regards, Chris.