From: John Maddock (john_at_[hidden])
Date: 2008-02-27 07:50:29


OK, finally(!), here comes my review of this library - purely as a potential
user, not as review manager.

First off the headline: I think the library should be accepted into Boost.

fpclassify
~~~~~~~~~~

Having already demonstated my ignorance of the aliasing rules, I'm quite
happy to accept this as is :-) There's little to say design wise, as it
follows existing practice, so as long as Johan is happy to see this merged
with my code that handles non-builtin floating point numbers (class types
like NTL::RR or mpfr_class etc) then I'm happy.

It's been suggested that isinf should indicate the sign of the infinity.
Personally I would prefer isinf etc to return a bool as per TR1 than return
+1 or -1 etc to indicate the sign as well (as per glibc) - we have other
functions for that purpose, and IMO a function name should indicate it's
purpose clearly - relying on the sign of the result of isinf seems like a
recipe for hard to maintain code to me... just my 2c worth.

Sign Manipulation
~~~~~~~~~~~~~~~~~

As these use the same core code as the fpclassify code, I'm happy with the
implementation. We've discussed changesign previously, so I won't labour
the point again :-)

There is one other useful function worth having IMO:

template <class T>
int sign(T x);

returns 0 (x is zero), +1 (x is > 0) or -1 (x is < 0). This is trivial to
implement (lot's of old C code - for example the Numerical Recipies stuff -
implement this as a helper macro), and there's an undocumented version
currently in Boost.Math. Is this worth integrating with Johan's code? I've
found it quite useful in Boost.Math from time to time.

Number Facets
~~~~~~~~~~~~~

I think these are a good idea, a few comments about the interface follow:

1) I assume that these:

const int legacy;
const int signed_zero;
const int trap_infinity;
const int trap_nan;

Should be declared "static" as well?

2) I'm not completely sure about the "legacy" flag: shouldn't the facet just
read in everything that it recognises by default? Or maybe we should flip
the meanings and "legacy" should become "strict_read" or "nolegacy" or
something - I'm not that keen on those names, but Boosters can usually come
up with something snappy when asked :-)

3) I think someone else mentioned that there is a lot of boilerplate code
that gets repeated when using these facets, so I think I'd like to see
something like:

std::locale get_nonfinite_num_locale(int flags = 0, std::locale base_locale
= std::locale());

which returns a locale containing the same instantiations of these facets
that a default locale would have for num_put and num_get, which is to say:

nonfinite_num_get<char>,
nonfinite_num_get<wchar_t>
nonfinite_num_put<char>
nonfinite_num_get<wchar_t>

Then we could simply write:

my_iostream.imbue(get_nonfinite_num_locale());

or

std::locale::global(get_nonfinite_num_locale());

and be done with it.

4) I think the flags are useful, but would be a lot nicer as iostream
manipulators - although I accept this may not work with lexical_cast :-(

BTW what was the issue that would require separate file compilation for
manipulators?

Overall nice job.

Regards, John.