Subject: Re: [boost] [Review Request] Multiprecision Arithmetic Library
From: John Maddock (boost.regex_at_[hidden])
Date: 2012-04-16 06:37:42
>> I'm not sure I follow you - what the std says is:
>> static constexpr int digits10;
>> 11 Number of base 10 digits that can be represented without change.
>> 12 Meaningful for all specializations in which is_bounded != false.
> Could you please tell me where this is in ISO 14882:2011?
> I can't find it.
Section 184.108.40.206 para 13 (I'm looking at the final draft though so there may
be detail changes to the final std I guess).
>> Which I take as meaning that if you print at least max_digits10 digits
>> then you should always be able to get back to the same unique value.
> I agree.
>> Oh wait.... just looked at the code and I see the issue - you set
>> to digits10+1 which isn't enough, should be set to
>> which is the largest number of digits possible in the number right?
>> Making that change causes the test to pass, so committing,
>> but please advise if that's upping max_digits10 too far ;-)
>> Cheers, John.
> Wait John.
> It took me a long time to finally figure this out. And it gets back to
> some of our original work with Paul Bristow. I believe that we actually
> need to test for equality to within 1ULP, whereby the ULP in this
> case is the least significant, potentially rounded and carried
> base-10 "digit" in the limb containing the ULP of least
> precision in cpp_dec_float.
> I need to actually add more intelligence to
> template <unsigned Digits10>
> int cpp_dec_float<Digits10>::cmp_data(const array_type& vd) const.
> The current equality case includes *all* the guard limbs, even though
> some are insignificant. I need to analyze the real number of identical
> base-10 digits in LHS and RHS, take rounding into account and test
> for equality not until the end of the limbs, but until one max_digits10,
> potentially rounded and carried from (max_digits10 + 1).
> Can you follow me? Do you agree with this? It shouldn't be
> too difficult to implement and I don't anticipate significant
> performance loss due to analyzing two limbs in the array
> in base-10, possibly in conjunction with lexical conversion.
> And I would really like to give this a try.
> With your permission, may I try this?
> Am I on the right track?
I don't know ;-)
Here's what I think - firstly lets "Keep It Simple" - and if the digits are
present in the internal representation, then why *shouldn't* they be used
for comparisons and printing out?
Let me give you an example - if there are guard digits which aren't used for
comparisons - could you not get into a situation where two numbers which
compare equal lead to different results after some sequence of arithmetic
operations? IMO that would not be good, and at the very least could lead to
all kinds of confusions.
Consider what GMP's mpf_t does - there are hidden guard digits that you
don't see, which do take part in comparisons and all arithmetic operations,
on the other hand they don't provide a way to print those out which makes
round tripping impossible - which IMO is very annoying.
On the other hand, MPFR takes a much less loose approach, and rounds
everything to *exactly* the requested precision after each step, round
tripping is also possible in this case. The equivalent in cpp_dec_float
would be to have no guard digits at all, and round after each operation to
exactly Digits10 decimal places. While there may be use cases for that, I
think we want to Keep It Simple for now and not go down that road.
So.... the situation we have now seems to be path of least resistance. It's
somewhat inelegant having max_digits10 so much larger than digits10, but it
seems to me that nothing really bad can happen here - just maybe that
serialized numbers will occupy a touch more space on disk than expected?