[ICL] #6853: boost::icl::contains(NaN) returns true

I had submitted a bug report for icl, and the response I included below seemed indicate this is more for the list than a bug report. It deals with an issue where boost::icl::contains(NaN) returns true, where any NaN value cannot actually be contained within an interval, and so should return false. 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. However, when the data is valid it falls into certain intervals that I found icl well suited for, despite not falling into the original use case of time scheduling I find it to be a reasonable representation to work with. While IEEE floating point numbers is not required by the C++ standard, it is a standard that does seem to have fairly wide use in C++. It seems, at least in my use case, that NaN is a very reasonable value to use and fits well with the functionality icl provides. However, I wanted to open this to wider opinions to learn about the state of the issue. Cheers! Andrew Hundt ---------- Forwarded message ---------- From: Boost C++ Libraries <noreply@lists.boost.org> Date: Fri, May 4, 2012 at 6:50 AM Subject: Re: [Boost C++ Libraries] #6853: [ICL] boost::icl::contains(NaN) returns true To: Cc: boost-bugs@lists.boost.org #6853: [ICL] boost::icl::contains(NaN) returns true -----------------------------------------------+---------------------------- Reporter: Andrew Hundt <ATHundt@…> | Owner: jofaber Type: Bugs | Status: closed Milestone: To Be Determined | Component: ICL Version: Boost 1.49.0 | Severity: Problem Resolution: invalid | Keywords: icl -----------------------------------------------+---------------------------- Changes (by jofaber): * status: new => closed * resolution: => invalid Comment: Hi Andrew, icl code is not intended to be NaN complete. NaN is a weird animal that breaks concepts the icl is based on. Completing icl for NaN would make the code unnecessarily clumsy for cases that are hardly ever used. If you desire to complete your code for NaN cases you will have to do it in your code or write your own NaN layer around the icl. Regards, Joachim -- Ticket URL: <https://svn.boost.org/trac/boost/ticket/6853#comment:1> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andrew Hundt Sent: Friday, May 04, 2012 4:14 PM To: boost@lists.boost.org Subject: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
I had submitted a bug report for icl, and the response I included below seemed indicate this is more for the list than a bug report. It deals with an issue where boost::icl::contains(NaN) returns true, where any NaN value cannot actually be contained within an interval, and so should return false.
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. However, when the data is valid it falls into certain intervals that I found icl well suited for, despite not falling into the original use case of time scheduling I find it to be a reasonable representation to work with. While IEEE floating
is not required by the C++ standard, it is a standard that does seem to have fairly wide use in C++.
It seems, at least in my use case, that NaN is a very reasonable value to use and fits well with
point numbers the
functionality icl provides. However, I wanted to open this to wider opinions to learn about the state of the issue.
IMO it would seem reasonable and useful to 'support' NaN. (If you mean that an interval cannot be bounded by a NaN, and a NaN cannot be contained by any set?) But the library author is 'in charge' and Joachim obviously thinks it would be too complicated to do this, so probably we have to accept that for now. The now-standard since tr1 isnan() function will help portability. Perhaps if you can provide patches to deal with NaN, and some additional Boost-style tests, (and some 'patches' to the docs) you might change his mind? Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com
---------- Forwarded message ---------- From: Boost C++ Libraries <noreply@lists.boost.org> Date: Fri, May 4, 2012 at 6:50 AM Subject: Re: [Boost C++ Libraries] #6853: [ICL] boost::icl::contains(NaN) returns true To: Cc: boost-bugs@lists.boost.org
#6853: [ICL] boost::icl::contains(NaN) returns true -----------------------------------------------+------------------------ -----------------------------------------------+---- Reporter: Andrew Hundt <ATHundt@.> | Owner: jofaber Type: Bugs | Status: closed Milestone: To Be Determined | Component: ICL Version: Boost 1.49.0 | Severity: Problem Resolution: invalid | Keywords: icl -----------------------------------------------+------------------------ -----------------------------------------------+---- Changes (by jofaber):
* status: new => closed * resolution: => invalid
Comment:
Hi Andrew,
icl code is not intended to be NaN complete. NaN is a weird animal that breaks concepts the icl is based on. Completing icl for NaN would make the code unnecessarily clumsy for cases that are hardly ever used. If you desire to complete your code for NaN cases you will have to do it in your code or write your own NaN layer around the icl.
Regards, Joachim
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/6853#comment:1> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.

IMO it would seem reasonable and useful to 'support' NaN.
(If you mean that an interval cannot be bounded by a NaN, and a NaN cannot be contained by any set?)
Yes, this is exactly what I had in mind. I'm sure data sets with invalid data points are fairly common across many domains, particularly in cases where measurements are involved such as scientific data.
But the library author is 'in charge' and Joachim obviously thinks it would be too complicated to do this, so probably we have to accept that for now.
Understood and agreed, I'm simply trying to facilitate discussion since it seemed like an interesting and fairly reasonable use case.
The now-standard since tr1 isnan() function will help portability.
Perhaps if you can provide patches to deal with NaN, and some additional Boost-style tests, (and some 'patches' to the docs) you might change his mind?
Paul

Hi Andrew, list, the NaN topic is not my favorite topic it's more a NaTo (not a Topic ;) 2012/5/7 Andrew Hundt <athundt@gmail.com>:
IMO it would seem reasonable and useful to 'support' NaN.
(If you mean that an interval cannot be bounded by a NaN, and a NaN cannot be contained by any set?)
Yes, this is exactly what I had in mind. I'm sure data sets with invalid data points are fairly common across many domains, particularly in cases where measurements are involved such as scientific data.
But the library author is 'in charge' and Joachim obviously thinks it would be too complicated to do this, so probably we have to accept that for now.
Understood and agreed, I'm simply trying to facilitate discussion since it seemed like an interesting and fairly reasonable use case.
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. Some thoughts and observations: (1) NaN seems to be a paradox: "I am a number that is not a number". But the paradox exists only in the naming: NaN = "not a number". In the implementation NaN is of course a number: double zero = 0.0; double not_a_double = zero/zero; BOOST_CHECK(tr1::isnan(not_a_double)); //will pass Now, *all values* of a datatype should obey certain axioms. If we want to be able to sort them, which we certainly want to do with floating point numbers at times, we need e.g. Induced Equivalence: if !(x<y) and !(y<x) then x =^= y where =^= is a equivalence relation (for a strict weak ordering) or an identity relation (for a total ordering). Sorted Associative Containers in the stl rely on such concepts and their axioms. NaN poisons the generic design: For all double x : Since !(x<NaN) and !(NaN<x) it follows that NaN =^= x. NaN is equivalent to all "regular" double values. Therefore, if you insert NaN into a std::set<double> you cannot insert any other value and every find-operation results in NaN. In a way NaN is the black hole of generic designs ;) //---- code ------------- set<double> NaN_set; double NaN = std::numeric_limits<double>::quiet_NaN(); NaN_set.insert(NaN); cout << "NaN_set.size() = " << NaN_set.size() << endl; NaN_set.insert(42.0); cout << "NaN_set.size() = " << NaN_set.size() << endl; set<double>::iterator it = NaN_set.find(42.0); if(it != NaN_set.end()) cout << "NaN_set contains: " << *it << endl; else cout << "42.0 not found\n"; //---- edoc ------------- //Output: NaN_set.size() = 1 NaN_set.size() = 1 NaN_set contains: 1.#QNAN //----------------------- (2) Being part of a standard (IEEE-754) NaN comes with a certain authoritative appearance and tends to leak from the domain of floating point numbers into other areas like unlimited integer implementation or e.g. the boost::data_time library. The idea of "not_a_date_time" made the integration of boost::data_time with the ICL unnecessary clumsy. I had to write adapter code that is completely unnecessary based on a generic design without not_a_date_time. I am happy the boost::chrono people did not follow the NaN-path (and did not fall into the black hole;) Chrono and ICL therefore are working perfectly together. (3) Undefinedness, invalidness, over/underflow, infinities for data types are concepts do not live at the same abstraction level as the data values themselves. I think it is a bad idea to try to code them into the level of naked values. (4) After some experiences with NaN, infinity and generic concepts I come to the conclusion that a concept or "abstract data type" shall not include any "special values" that are not reachable by fundamental operations of the datatype (E.g. x/0, infinities) and do not obey the laws that are fundamental to its semantics. I think we can work with such notions in separate concepts, like e.g. an infinite_interval<T>. T does not need to have an infinity-value but infinite_interval<T> may have the the property to be infinite on one or both sides. Datatypes T can stay simple and the infinity handling is the responsibility of concept infinite_interval<T>. I'd love to work on those ideas and more, but unfortunately I don't have time to develop much code in boost quality currently :( Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Hi Andrew, list, the NaN topic is not my favorite topic it's more a NaTo (not a Topic ;)
Thank you for your time and response Joachim, it is very insightful. However, it leads me back to a question I've been grappling with for some time. (3) Undefinedness, invalidness, over/underflow, infinities for data
types are concepts do not live at the same abstraction level as the data values themselves. I think it is a bad idea to try to code them into the level of naked values.
Suppose in the ICL tutorial example of finding a party's average guest height, one guest refuses to disclose their height when they enter. Every other piece of information is there, you can't pretend this guest is not present, and the average over everyone else is still useful. I originally considered boost.optional and NaN for that situation, and decided to go with NaN. If NaN is a flawed design decision, is there an effective alternative in cases where invalid values are not avoidable that can be used with various algorithms as you describe? I expect using boost.optional would require many similar workarounds to use. Perhaps those workarounds are simply a requirement of any design I could choose, given that invalid values of some kind are a constraint I must contend with. Cheers! Andrew Hundt

Hi Andrew again, 2012/5/8 Joachim Faulhaber <afojgo@googlemail.com>:
2012/5/7 Andrew Hundt <athundt@gmail.com>:
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

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.
That looks like a great solution, thanks! Perhaps this is useful for simplifying "not_a_date_time" too. NaNtheless, I am a NaN loather ;)
Cheers, Joachim
I find it NaNcomfortable to deal with as well, and I can feel your pain. :-) Cheers! Andrew Hundt

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Joachim Faulhaber Sent: Tuesday, May 08, 2012 7:25 PM To: boost@lists.boost.org Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
Hi Andrew again,
2012/5/8 Joachim Faulhaber <afojgo@googlemail.com>:
2012/5/7 Andrew Hundt <athundt@gmail.com>:
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@hetp.u-net.com So thanks to Joachim for giving this so much thought

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 bizarr oddity to the land of NaN sense. Best regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

-----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? Your original instinct, but maybe adding a check when creating an interval. (Perhaps throw an exception if the user tries to create an interval using a NaN?) And contains() returns false for all NaN? (which is what Andrew wanted to start with). (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?) Musing out loud (or should that be mumbling ;-). Cheers Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

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

On Fri, May 4, 2012 at 8:14 AM, Andrew Hundt <ahundt@gmail.com> wrote:
I had submitted a bug report for icl, and the response I included below seemed indicate this is more for the list than a bug report. It deals with an issue where boost::icl::contains(NaN) returns true, where any NaN value cannot actually be contained within an interval, and so should return false.
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. However, when the data is valid it falls into certain intervals that I found icl well suited for, despite not falling into the original use case of time scheduling I find it to be a reasonable representation to work with. While IEEE floating point numbers is not required by the C++ standard, it is a standard that does seem to have fairly wide use in C++.
It seems, at least in my use case, that NaN is a very reasonable value to use and fits well with the functionality icl provides. However, I wanted to open this to wider opinions to learn about the state of the issue.
Cheers! Andrew Hundt
---------- Forwarded message ---------- From: Boost C++ Libraries <noreply@lists.boost.org> Date: Fri, May 4, 2012 at 6:50 AM Subject: Re: [Boost C++ Libraries] #6853: [ICL] boost::icl::contains(NaN) returns true To: Cc: boost-bugs@lists.boost.org
#6853: [ICL] boost::icl::contains(NaN) returns true
-----------------------------------------------+---------------------------- Reporter: Andrew Hundt <ATHundt@…> | Owner: jofaber Type: Bugs | Status: closed Milestone: To Be Determined | Component: ICL Version: Boost 1.49.0 | Severity: Problem Resolution: invalid | Keywords: icl
-----------------------------------------------+---------------------------- Changes (by jofaber):
* status: new => closed * resolution: => invalid
Comment:
Hi Andrew,
icl code is not intended to be NaN complete. NaN is a weird animal that breaks concepts the icl is based on. Completing icl for NaN would make the code unnecessarily clumsy for cases that are hardly ever used. If you desire to complete your code for NaN cases you will have to do it in your code or write your own NaN layer around the icl.
Regards, Joachim
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/6853#comment:1> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
I'd guess that including and supporting NaN makes floating point types not conform to the ordering concepts required by the ICL, so it seems reasonable to me to document NaN's as unsupported. How well does std::set/std::map interact with NaN when floating point types are used as keys? - Jeff

On Fri, May 04, 2012 at 11:48:30AM -0700, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 4, 2012 at 8:14 AM, Andrew Hundt <ahundt@gmail.com> wrote: How well does std::set/std::map interact with NaN when floating point types are used as keys?
Undefinedly, most usually explodedly. For libraries that have sanity checks on the comparator, hard asserts. For the rest (or NDEBUG), amusing loss of elements and general malfunction. -- Lars Viklund | zao@acc.umu.se

On Fri, May 4, 2012 at 11:54 AM, Lars Viklund <zao@acc.umu.se> wrote:
On Fri, May 04, 2012 at 11:48:30AM -0700, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 4, 2012 at 8:14 AM, Andrew Hundt <ahundt@gmail.com> wrote: How well does std::set/std::map interact with NaN when floating point types are used as keys?
Undefinedly, most usually explodedly.
For libraries that have sanity checks on the comparator, hard asserts. For the rest (or NDEBUG), amusing loss of elements and general malfunction.
Then it seems reasonable to me for ICL to also opt not to support NaN's in favor of a simpler implementation, better performance, etc. - Jeff

Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 04, 2012 at 11:48:30AM -0700, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 4, 2012 at 8:14 AM, Andrew Hundt <ahundt@gmail.com> wrote: How well does std::set/std::map interact with NaN when floating point types are used as keys?
Undefinedly, most usually explodedly.
For libraries that have sanity checks on the comparator, hard asserts. For the rest (or NDEBUG), amusing loss of elements and general malfunction.
Then it seems reasonable to me for ICL to also opt not to support NaN's in favor of a simpler implementation, better performance, etc.
I want to add that for recent gcc (at least for gcc 4.5.2), even the built-in "isnan" functions stops working when the compiler flag "-ffast-math" is used. That broke some of my code, and I had to debug quite a while before I found the reason. It took me so long since I couldn't believe that the built-in "isnan" would go wrong. My conclusion from this is that NaN can't be used portably, so there is no point for Boost.ICL to try to support it. Regards, Thomas

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lars Viklund Sent: Friday, May 04, 2012 7:54 PM To: boost@lists.boost.org Subject: Re: [boost] [ICL] #6853: boost::icl::contains(NaN) returns true
On Fri, May 04, 2012 at 11:48:30AM -0700, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 4, 2012 at 8:14 AM, Andrew Hundt <ahundt@gmail.com> wrote: How well does std::set/std::map interact with NaN when floating point types are used as keys?
Undefinedly, most usually explodedly.
Well of course NaN shouldn't get anywhere near sets and maps. And a NaN should never be contained by any element. Is the real issue here whether the user should have to check for NaNs, or whether the ICL library protects itself from them? (and what it does if a NaN is found. Perhaps throw for trying to make an interval with it, and just returning false for contains()? I think I tend to favour the library on the grounds that the user who provides a NaN by accident will come to grief - and a really helpful library would protect against this. But some users will complain that they are paying for something they don't need. Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com
participants (7)
-
Andrew Hundt
-
Andrew Hundt
-
Jeffrey Lee Hellrung, Jr.
-
Joachim Faulhaber
-
Lars Viklund
-
Paul A. Bristow
-
Thomas Klimpel