Boost logo

Boost :

Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2012-05-09 08:11:29


> -----Original Message-----
> From: boost-bounces_at_[hidden] [mailto:boost-bounces_at_[hidden]] On Behalf Of Joachim
> Faulhaber
> Sent: Tuesday, May 08, 2012 7:25 PM
> To: boost_at_[hidden]
> Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
>
> Hi Andrew again,
>
> 2012/5/8 Joachim Faulhaber <afojgo_at_[hidden]>:
> > 2012/5/7 Andrew Hundt <athundt_at_[hidden]>:
> >>>
> >>>
> >>> IMO it would seem reasonable and useful to 'support' NaN.
> >>>
> >
> > 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 :)
>
> Look how flexible generic designs can be :) Even in the presence of an awkward and
self-contradicting idea
> like NaN, the desired behavior seems to be implementable with the tools provided by the generic
design.
>
> We can complete the ordering relation in a way such that NaN is smaller than all regular values,
by
> defining the comparison functor
> 'NaNTheLess':
>
> template<class Float>
> struct NaNtheLess
> {
> bool operator()(Float lhs, Float rhs)const
> {
> return tr1::isnan(lhs)
> ? !tr1::isnan(rhs)
> : std::less<Float>()(lhs, rhs);
> }
> };
>
>
> BOOST_AUTO_TEST_CASE(NaNtheLessTest)
> {
> typedef interval_set<double, NaNtheLess> NaNy_SetT;
> typedef NaNy_SetT::interval_type NaNy_IntervalT;
>
> NaNy_SetT nanySet;
>
> double NaN = numeric_limits<double>::quiet_NaN();
> nanySet.insert(NaN);
> nanySet.insert(42);
> cout << nanySet << endl;
>
> nanySet.insert(NaNy_IntervalT::right_open(40,42));
> BOOST_CHECK(contains(nanySet, NaN));
> BOOST_CHECK(contains(nanySet, 42));
>
> nanySet.insert(NaNy_IntervalT::right_open(40,42));
> cout << nanySet << endl;
>
> nanySet += NaNy_IntervalT::right_open(NaN,42);
> cout << nanySet << endl;
>
> double Min = (numeric_limits<double>::min)();
> nanySet -= Min;
> cout << nanySet << endl;
>
> nanySet += Min;
> cout << nanySet << endl;
> }
>
> //---- Output --------------------------- {

[1.#QNAN,1.#QNAN][42,42]}

 {[1.#QNAN,1.#QNAN][40,42]}

> {[1.#QNAN,42]}

 {[1.#QNAN,2.22507e-308)(2.22507e-308,42]}

> {[1.#QNAN,42]}
>
> 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 ;-)

Without this it would have been necessary to check every value for NaN before doing anything with
it.

Some users may still prefer to do this because it allows one to decide what action to take?

Andrew Hundt original wish was to use NaN as a proxy for "missing item"
- something that cannot be a member of any (useful) set.

> I'm dealing with data that comes from a physical device, so each
> measurement the system returns is not guaranteed to be valid.
> We set those invalid measurements to NaN.

IMO it would have been more sensible to designate a specific NaN for "missing value" - and we could
still do this.
But so far it is not a priority for the Standards Bodies?

Thanks for giving this so much thought.

Paul

---
Paul A. Bristow,
Prizet Farmhouse, Kendal LA8 8AB  UK
+44 1539 561830  07714330204
pbristow_at_[hidden]
So thanks to Joachim for giving this so much thought

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