Boost logo

Boost :

Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
From: Joachim Faulhaber (afojgo_at_[hidden])
Date: 2012-05-08 14:25:04


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 ;)

Cheers,
Joachim

-- 
Interval Container Library [Boost.Icl]
http://www.joachim-faulhaber.de

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