Boost logo

Boost :

Subject: Re: [boost] [review] Multiprecision review scheduled for June 8th - 17th, 2012
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-06-02 17:15:31


Le 31/05/12 22:10, Christopher Kormanyos a écrit :
> Thank you for your comments, 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.

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 ======

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"

>>> * 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;
>> Good question :)
>> I don't have a particulary strong view whether it's "number" or
>> "mp_number", but would like to know what others think.
> I actually *do* have a slight preference for "mp_number",
> with the *mp_* part. It simply reminds me that I'm actually doing
> something with multiple precision type. An experienced booster once
> told me that boost favors clarity over terseness. Perhaps this is
> a case thereof.
OK. I see.
>
>>> * I think that the fact that operands of different backends can not
>>> be mixed on the same operation limits some interesting operations:
> I understand your comment, Vicente. In my experience,
> the reduced error resulting from forbidding non-explicit mixing
> of back-ends far outweighs potential benefits from allowing them.
>
> Of course, this is only an opinion. Others will disagree.
> When we discussed potential fixed-point types, you may
> remember my recommendation.
>
> I usually recommend:
> * Do support seamless interaction with built-in types.
> * Forbid implicit conversion of non-same specialized types.
> * Potentially support explicit construction of one type from another.
>
> 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?

>
>>> * 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?
>> Yes you can convert, and the rounding is currently poorly defined :-(
>> I'll let Chris answer about rounding policies, but basically it's a whole lot of work.
>> The aim is not to try and compete with say MPFR, but be "good enough"
>> for most purposes. For some suitable definition of "good enough" obviously ;-)
> Yes, I confirm John's statement. You can explicitly convert.
> Unfortunately, there simply is no support for rounding at
> this time in the cpp_dec_float back-end.
>
> 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.

   using namespace boost::multiprecision;
   {
     cpp_dec_float_50 a(cpp_dec_float_50(-1) / 3);
     cpp_dec_float_100 b=a;
     {
       boost::io::ios_precision_saver ifs( std::cout );

       std::cout << "setprecision(N) " <<
std::setprecision(50) << a << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
<< a << std::endl;
     }
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(100) << b << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10)
<< b << std::endl;
     }
   }
   std::cout << "*****************" << std::endl;
   {
     cpp_dec_float_100 a(cpp_dec_float_100(-1) / 3);
     cpp_dec_float_50 b=cpp_dec_float_50(a);
     {
       boost::io::ios_precision_saver ifs( std::cout );

       std::cout << "setprecision(N) " <<
std::setprecision(100) << a << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10)
<< a << std::endl;
     }
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(100) << b << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
<< b << std::endl;
     }
   }
   std::cout << "*****************" << std::endl;
   {
     cpp_dec_float_50 a(cpp_dec_float_50(1) / 3);
     cpp_dec_float_100 b=a;
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(50) << a << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
<< a << std::endl;
     }
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(100) << b << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10)
<< b << std::endl;
     }
   }
   std::cout << "*****************" << std::endl;
   {
     cpp_dec_float_100 a(cpp_dec_float_100(1) / 3);
     cpp_dec_float_50 b=cpp_dec_float_50(a);
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(100) << a << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10)
<< a << std::endl;
     }
     {
       boost::io::ios_precision_saver ifs( std::cout );
       std::cout << "setprecision(N) " <<
std::setprecision(100) << b << std::endl;
       std::cout << "setprecision(max_digits10)= " <<
std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
<< b << std::endl;
     }
   }

gives
setprecision(N)
-0.33333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(N)
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
*****************
setprecision(N)
-0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(N)
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
-0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
*****************
setprecision(N)
0.33333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(N)
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
*****************
setprecision(N)
0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(N)
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333
setprecision(max_digits10)=
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333

so I guess the rounding is towards zero.

> 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.
>
>>> If not, what about a mp_number_cast function taking as
>>> parameter a rounding policy?
>> I think it would be very hard to a coherant set of rounding policies
>> that were applicable to all backends... including third party ones
>> that haven't been thought of yet. Basically ducking that issue at present :-(
> Yes, and keep ducking. We won't get it done correctly
> in a reasonable time scale. In my opinion, we can consider in
> association with an improved BPL base-2 floating-point
> back-end in the future. Backwards compatibility could
> be achieved with a potential rounding policy of *no rounding*.
> MPFR, GMP, MPIR and the rest will get the rounding
> that they have or don't have.
Or *round_to_zero* instead of *no rounding*.
>>> * 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.

>
>>> * 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk