
2012/5/9 Paul A. Bristow <pbristow@hetp.u-net.com>:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Joachim Faulhaber Sent: Wednesday, May 09, 2012 3:32 PM To: boost@lists.boost.org Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
2012/5/9 Paul A. Bristow <pbristow@hetp.u-net.com>:
2012/5/8 Joachim Faulhaber <afojgo@googlemail.com>:
I don't think the ICL should support NaN. Moreover I believe boost libraries and generic concepts should not integrate NaN in general. In a way I conceive NaN as being "anti generic". Wherever I run into the NaN phenomenon, it tends to jeopardize simplicity and elegance in generic designs.
NaNtheLess! I found a generic solution to the problem :)
template<class Float> struct NaNtheLess { bool operator()(Float lhs, Float rhs)const { return tr1::isnan(lhs) ? !tr1::isnan(rhs) : std::less<Float>()(lhs, rhs); } };
Hope this solves your problems. NaNtheless, I am a NaN loather ;)
Well, in a way everyone hates them too, but they *are out there*, and hitting them is nasty.
This sounds an excellent solution, protecting the hapless user from the almost certainly unpleasant results of tripping over a NaN in the night ;-)
Hi Paul, nice to meet you here again :)
:-)
I am afraid though that this "solution" like every NaN-workaround for sound generic concepts is only a bluff package that tries to heal the fundamental flaws of NaN, that are incurable by construction. Functor NaNtheLess bends the semantic of NaN for sake of sortability:
As the nanySet shows
{[1.#QNAN,2.22507e-308)(2.22507e-308,42]}
we now assume that
NaN < numeric_limits<Float>::min()
which directly contradicts the semantics defined for NaN. If we'd extend this for infinities we might end up with constructions like
NaN < -numeric_limits<Float>::infinity()
that adds just another bizarre oddity to the land of NaN sense.
So it is better to be more conservative and just prohibit NaN from intervals?
In a way the NaNtheLess workaround is conservative in the sense that it allow to deal with the user's need and at the same time keeps away NaN from the generic library code. I can happily live with the fact that user code, NaNtheLess in this case, bends the NaN properties. I would not accept messing up ICL code with NaN cases.
Your original instinct, but maybe adding a check when creating an interval.
In user code yes, in library code NO.
(Perhaps throw an exception if the user tries to create an interval using a NaN?)
NO, that would mean to adapt library code to NaN.
And contains() returns false for all NaN? (which is what Andrew wanted to start with).
This is provided by the workaround since the icl::containers and intervals share the same ordering which is NaNtheLess when using the workaround.
(Of course, he could also achieve that by testing isnan(value) ? false : contains(value)), and making sure that he didn't create an interval with a NaN (less risk but worse results?)
An even better solution in my view.
Musing out loud (or should that be mumbling ;-). :-)
The interesting thing in this thread is this: It appears to me that everyone is fighting (or at least ignoring) NaN and its properties all the time: (1) icl::contains(interval<float>(1,30), NaN) == true is considered to be a bug. But in fact this is consistent with the NaN properties: For all x: !(NaN < x) && !(x < NaN) (2) We are surprised, that for Sorted Associative Containers sac we have sac.insert(NaN).insert(x1). ... .insert(xn).size() == 1 although this is perfectly consistent with the NaN properties. (3) In general we tend to ignore the fact that a datatype like float is completely unusable with all std containers and algorithms relying on Comparability concepts because NaN, that is a float value breaks all the axioms needed for Comparability. (4) The standard is extended by a predicate isnan that allows to circumvent basic NaN properties like NonEqualityComparability. Defining the NaNtheLess functor we do just that and everyone seems to be happy with it. Spontaneously, intuitively everyone seems to fight NaN ;-) My own view, that is expressed in more detail in my first posting in this thread is this: 1. We should keep NaN away from generic designs. 2. We should not mix levels of abstraction: "Special values" do not belong to the value level of data types. Or, to put it another way, SaNV: Special values are not values. Infinities, missing values etc. should be handled using separate concepts. Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de