
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 18.3.2.4 para 13 (I'm looking at the final draft though so there may be detail changes to the final std I guess).
<snip>
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.
<snip>
Oh wait.... just looked at the code and I see the issue - you set max_digits10 to digits10+1 which isn't enough, should be set to cpp_dec_float_total_digits10 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? Cheers, John.