
Le 03/06/12 18:37, Christopher Kormanyos a écrit :
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. Hrr, unfortunately I have not implemented closed arithmetic operations on my fixed_point library, so I can not create the backend yet. 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; } The result is
-0.0000000008567
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. There is no issue using specific c++11, but the example should be run either only on c++11 mode or just compile conditionally the c++11 parts.
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);
This not answer my question "Why the implicit conversion from cpp_dec_float_50 to cpp_dec_float_100 doesn't helps?". Have you an idea?
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.
Yes but it round while converting 100 digits to 50, and this should be documented.
* 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.
Does this mean that we can not create a generic class mp_number that provides some of the interfaces the backend can provide and the user will need to be able to create instances of mp_number from instances of the backend. Could the following constructor be implemented as a constexpr if the move of BE is a constexpr? constexpr mp_number<BE>::mp_number(const BE&&); Best, Vicente