
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite. Joe Gottman

Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
That would be useful. I just put together some facets for writing and reading non-finite floating point numbers to text streams in a consistent and portable manner. (The code is available in the boost vault, serialization/non_finite_num_facets.zip). And this code contains yet another is_nan function.

Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Floating point numbers can be classified into four categories: 1. finite numbers 2. infinity 3. negative infinity 4. not-a-number (nan) So maybe we need functions: template<class T> bool is_finite(T a) { return a >= -std::numeric_limits<T>::min() && a <= std::numeric_limits<T>::max(); } template<class T> bool is_infinity(T a) { return std::numeric_limits<T>::has_infinity && a == std::numeric_limits<T>::infinity(); } template<class T> bool is_nan(T a) { return a != a; } You test for negative infinity by calling is_infinity(-a). Three issues: 1. Do these implementations work an all platforms? 2. The category not-a-number can be divided into the sub-categories quite not-a-number and signalling not-a-number. Does anyone need to distinguish between them? 3. Are these the most efficient implementations. (Important if you have a large vector of numbers and need to verify that each element is finite.) --Johan Råde

Johan Råde wrote:
Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Floating point numbers can be classified into four categories:
1. finite numbers 2. infinity 3. negative infinity 4. not-a-number (nan)
So maybe we need functions:
template<class T> bool is_finite(T a) { return a >= -std::numeric_limits<T>::min() && a <= std::numeric_limits<T>::max(); }
template<class T> bool is_infinity(T a) { return std::numeric_limits<T>::has_infinity && a == std::numeric_limits<T>::infinity(); }
template<class T> bool is_nan(T a) { return a != a; }
You test for negative infinity by calling is_infinity(-a).
Three issues:
1. Do these implementations work an all platforms?
2. The category not-a-number can be divided into the sub-categories quite not-a-number and signalling not-a-number. Does anyone need to distinguish between them?
3. Are these the most efficient implementations. (Important if you have a large vector of numbers and need to verify that each element is finite.)
--Johan Råde
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Typo, should be template<class T> bool is_finite(T a) { return a >= -std::numeric_limits<T>::max() && a <= std::numeric_limits<T>::max(); } --Johan Råde

Johan Råde wrote:
Floating point numbers can be classified into four categories:
1. finite numbers 2. infinity 3. negative infinity 4. not-a-number (nan)
So maybe we need functions:
[snip] template<class T> bool is_infinity(T a) { return std::numeric_limits<T>::has_infinity && a == std::numeric_limits<T>::infinity(); }
[snip]
You test for negative infinity by calling is_infinity(-a).
...for which it would be easy enough to provide a convenience function (perhaps "is_minus_infinity"), which would just be a wrapper around "is_infinity". Another useful convenience function would be "is_infinite", which would return true if and only if the number was equal to plus or minus infinity (making use of either "is_finite" or both "is_infinity" and "is_minus_infinity") The similarity of the names of "is_infinity" and "is_infinite" might be a problem, but the former could be changed to "is_plus_infinity" to give symmetry with "is_minus_infinity". Paul

Paul Giaccone wrote:
Johan Råde wrote:
Floating point numbers can be classified into four categories:
1. finite numbers 2. infinity 3. negative infinity 4. not-a-number (nan)
So maybe we need functions:
[snip] template<class T> bool is_infinity(T a) { return std::numeric_limits<T>::has_infinity && a == std::numeric_limits<T>::infinity(); }
[snip]
You test for negative infinity by calling is_infinity(-a).
....for which it would be easy enough to provide a convenience function (perhaps "is_minus_infinity"), which would just be a wrapper around "is_infinity".
Another useful convenience function would be "is_infinite", which would return true if and only if the number was equal to plus or minus infinity (making use of either "is_finite" or both "is_infinity" and "is_minus_infinity")
The similarity of the names of "is_infinity" and "is_infinite" might be a problem, but the former could be changed to "is_plus_infinity" to give symmetry with "is_minus_infinity".
Paul
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I agree that having the three functions is_infinite (or maybe is_infinity) is_plus_infinity is negative_infinity is a good idea. John's proposal has the function is_infinity, in the sense of both plus and minus infinity, but not the functions is_plus_infinity and is_negative_infinity. Maybe John's intention is that one should test for plus infinity by writing is_infinity(x) && x >= 0 That would work, but is probably inefficient. --Johan

Johan Råde wrote:
I agree that having the three functions
is_infinite (or maybe is_infinity) is_plus_infinity is negative_infinity
is a good idea.
One minor refinement to this list: Have either: is_plus_infinity and is_minus_infinity or is_positive_infinity and is_negative_infinity rather than mixing the terminology. The former pair is probably better as the names are more concise. Sorry for repeating myself in my last past - I hadn't read Johan's posting.

Johan Råde wrote:
I agree that having the three functions
is_infinite (or maybe is_infinity) is_plus_infinity is negative_infinity
is a good idea.
John's proposal has the function is_infinity, in the sense of both plus and minus infinity, but not the functions is_plus_infinity and is_negative_infinity.
Maybe John's intention is that one should test for plus infinity by writing is_infinity(x) && x >= 0 That would work, but is probably inefficient.
For is_plus_infinity why not just: x > std::numeric_limits<T>::max() ? John.

| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Johan Råde | Sent: 25 July 2006 11:32 | To: boost@lists.boost.org | Subject: Re: [boost] is_nan | | Paul Giaccone wrote: | > Johan Råde wrote: | >> Floating point numbers can be classified into four categories: | >> | >> 1. finite numbers | >> 2. infinity | >> 3. negative infinity | >> 4. not-a-number (nan) | >> | >> So maybe we need functions: | >> | >> [snip] | >> template<class T> bool is_infinity(T a) | >> { | >> return std::numeric_limits<T>::has_infinity | >> && a == std::numeric_limits<T>::infinity(); | >> } | >> | >> [snip] | >> | >> You test for negative infinity by calling is_infinity(-a). I'd point out that one can (should?) use a separate test for the signbit, using the C99 function signbit (which also works OK on zero and NaNs) It would perhaps be more nicely named "is_negative" for C++. But perhaps one would not wish to add yet another new name? This sign bit exists on all types (or can simply return false if really is unsigned), even thouhg its meaning for zero and NaN is mathematically unclear. Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Yes! I'm working on these and other functions, see http://www.johnmaddock.co.uk/toolkit for a reasonably recent sets of docs, follow the link to floating point classification. HTH, John.

John Maddock wrote:
Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Yes! I'm working on these and other functions, see http://www.johnmaddock.co.uk/toolkit for a reasonably recent sets of docs, follow the link to floating point classification.
HTH, John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I looked at your (John Maddock's) doc. Looks good. This should be very useful. I think the floating point number classification should not be part of your math tool kit library, but should be submitted separately. The math tool kit is for experts only, while the number classification is of more general interest. So the floating point number classification now goes like: 1. Finite 1.1. Normalized finite 1.2. Denormalized finite 2. Infinity 2.1. Positive infinity 2.2. Negative infinity 3. Not-a-number 3.1. Quite not-a-number 3.2. Signalling not-a-number I noticed that you do not support the quite/signalling distinction. I agree that is probably not needed. --Johan Råde

Johan Råde wrote:
So the floating point number classification now goes like:
1. Finite 1.1. Normalized finite 1.2. Denormalized finite 2. Infinity 2.1. Positive infinity 2.2. Negative infinity 3. Not-a-number 3.1. Quite not-a-number 3.2. Signalling not-a-number
I believe the term normal is more common nowadays than normalized or non-denormalized. I believe the term subnormal is more common nowadays than denormalized. So it would make sense to have the functions is_finite() is_normal() is_subnormal() is_infinity() is_plus_infinity() is_minus_infinity() is_nan() and possibly is_quite_nan() is_signalling_nan() The last two are tricky to implement though. --Johan Råde

Johan Råde wrote:
So it would make sense to have the functions
is_finite() is_normal() is_subnormal()
is_infinity() is_plus_infinity() is_minus_infinity()
Is "is_infinity" the opposite of "is_finite" or the same as "is_plus_infinity"? The former, I would presume, but the name suggests the latter. This is the ambiguity I mentioned before. The function would be better named "is_infinite", IMO.

On 7/25/06, Paul Giaccone <paulg@cinesite.co.uk> wrote:
Is "is_infinity" the opposite of "is_finite" or the same as "is_plus_infinity"? The former, I would presume, but the name suggests the latter. This is the ambiguity I mentioned before. The function would be better named "is_infinite", IMO.
Agreed. A few people have mentioned:
is_plus_infinity() is_minus_infinity() I think positive/negative is better than plus/minus. It's slightly longer but fits the terminology I understand as being more "correct". std::plus and std::minus also give a precedent for plus/minus being operations (addition and subtraction), not classifications for values.
So I'd vote for these instead: is_positive_infinity() is_negative_infinity() ~ Scott McMurray

me22 wrote:
On 7/25/06, Paul Giaccone <paulg@cinesite.co.uk> wrote:
Is "is_infinity" the opposite of "is_finite" or the same as "is_plus_infinity"? The former, I would presume, but the name suggests the latter. This is the ambiguity I mentioned before. The function would be better named "is_infinite", IMO.
Agreed.
A few people have mentioned:
is_plus_infinity() is_minus_infinity() I think positive/negative is better than plus/minus. It's slightly longer but fits the terminology I understand as being more "correct". std::plus and std::minus also give a precedent for plus/minus being operations (addition and subtraction), not classifications for values.
So I'd vote for these instead: is_positive_infinity() is_negative_infinity()
~ Scott McMurray _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Agree. Then we have: template<class T> bool is_finite(T t); template<class T> bool is_normal(T t); template<class T> bool is_subnormal(T t); template<class T> bool is_infinite(T t); template<class T> bool is_positive_infinity(T t); template<class T> bool is_negative_infinity(T t); template<class T> bool is_nan(T t); template<class T> bool is_quiet_nan(T t); template<class T> bool is_signalling_nan(T t); --Johan Råde

Johan Råde wrote:
So it would make sense to have the functions
is_finite() is_normal() is_subnormal()
is_infinity() is_plus_infinity() is_minus_infinity()
is_nan()
Do we really want to use gratuitously different names from those in C99: isfinite isnorm isinf isnan ?
and possibly
is_quite_nan() is_signalling_nan()
The last two are tricky to implement though.
Actually probably impossible without decoding the bits in the FP number - for which you would have to deal with multiple formats in multiple endianness's etc. John.

John Maddock wrote:
Johan Råde wrote:
So it would make sense to have the functions
is_finite() is_normal() is_subnormal()
is_infinity() is_plus_infinity() is_minus_infinity()
is_nan()
Do we really want to use gratuitously different names from those in C99:
isfinite isnorm isinf isnan
?
Probably not. I was just ignorant about C99, and tried to put together Boost style names. Lets stick with the C99 names then. When will you submit your implementations of isnan etc to Boost? --Johan Råde

On Jul 25, 2006, at 8:31 AM, John Maddock wrote:
Johan Råde wrote:
So it would make sense to have the functions
is_finite() is_normal() is_subnormal()
is_infinity() is_plus_infinity() is_minus_infinity()
is_nan()
Do we really want to use gratuitously different names from those in C99:
isfinite isnorm isinf isnan
If we use the C99 names, do we intend on #undef'ing the C99 macros if they exist (C99 says these are macros, not functions)? If we don't then the macros will trash our functions. There's an easy technique for converting the macro (if it exists) into a function (demonstrated by gcc's <cmath>). If we do #undef the C99 macros, this is observable behavior which we should document (lest the client be testing #ifndef isnan after the boost header gets included). I recommend restricting these templates to floating point types. Otherwise they are overly generic, and could easily be called accidently, especially isnormal, is_normal, isnorm (or whatever, C99 and C++0X call it isnormal). -Howard

Howard Hinnant wrote:
Do we really want to use gratuitously different names from those in C99:
isfinite isnorm isinf isnan
If we use the C99 names, do we intend on #undef'ing the C99 macros if they exist (C99 says these are macros, not functions)? If we don't then the macros will trash our functions. There's an easy technique for converting the macro (if it exists) into a function (demonstrated by gcc's <cmath>). If we do #undef the C99 macros, this is observable behavior which we should document (lest the client be testing #ifndef isnan after the boost header gets included).
The way I have it set up is to *not* undef anything, that means you have to call them using either: (isnan)(x); or: (boost::math::isnan)(x); Just like we have to do the same thing with min and max already: this usage is documented with examples as well BTW :-)
I recommend restricting these templates to floating point types. Otherwise they are overly generic, and could easily be called accidently, especially isnormal, is_normal, isnorm (or whatever, C99 and C++0X call it isnormal).
Oh, actually I *need* generic versions of these functions in order to make parts of the math toolkit I'm working on generic: at the very least these scale to pretty much anything that has numeric_limits defined, without that all you can do is assume the number is a zero or a normal: but that's OK too because most (all?) extended precision types like NTL::RR don't support infinities or NaN's anyway. Of course passing a complex number or an octonium or something *would* be a mistake, but I'm assuming that any function that makes use of isnan etc wouldn't be compatible with these anyway. John.

On Jul 25, 2006, at 12:53 PM, John Maddock wrote:
I recommend restricting these templates to floating point types. Otherwise they are overly generic, and could easily be called accidently, especially isnormal, is_normal, isnorm (or whatever, C99 and C++0X call it isnormal).
Oh, actually I *need* generic versions of these functions in order to make parts of the math toolkit I'm working on generic: at the very least these scale to pretty much anything that has numeric_limits defined, without that all you can do is assume the number is a zero or a normal: but that's OK too because most (all?) extended precision types like NTL::RR don't support infinities or NaN's anyway.
Of course passing a complex number or an octonium or something *would* be a mistake, but I'm assuming that any function that makes use of isnan etc wouldn't be compatible with these anyway.
Here's the type of code one needs to defend against: namespace Mine { struct Person {}; struct Female : public Person {}; bool isnormal(const Person&); } int main() { using namespace boost; // for boost::bind (just as an example) Mine::Female Jane; bool b = isnormal(Jane); } I.e. the user includes boost for some reason completely unrelated to fp-classification. He may even be ignorant of its existence. But somehow via includes the client isn't even in control of, boost::isnormal(T) gets included in the translation unit. It greedily grabs the call to isnormal because it ends up being a better match than the client's intended function (which he didn't even realize he was overloading with a boost function). If you can restrict your template parameter somehow (perhaps with numeric_limits<T>::is_specialized), you can avoid accidental clients. isnan doesn't seem so susceptible to this type of accident, but isnormal sure does. I've been bitten by this one before (with sqrt believe it or not). -Howard

On Jul 25, 2006, at 1:45 PM, Howard Hinnant wrote:
namespace Mine {
struct Person {};
struct Female : public Person {};
bool isnormal(const Person&);
}
int main() { using namespace boost; // for boost::bind (just as an example) Mine::Female Jane; bool b = isnormal(Jane); }
If this code doesn't make you nervous (because of the using directive), the related code below might: namespace Mine { struct sense_of_humor {}; struct Person : private boost::optional<sense_of_humor> {}; struct Female : public Person {}; bool isnormal(const Person&); bool foo() { Female Jane; return isnormal(Jane); } } // Mine int main() { Mine::foo(); } Again, isnormal will get hijacked by boost::isnormal(T) if it is in the translation unit (and in namespace boost and not somehow constrained). template <class T> typename enable_if < std::numeric_limits<T>::is_specialized, bool
::type isnormal(T t) {...}
-Howard

Howard Hinnant wrote:
On Jul 25, 2006, at 1:45 PM, Howard Hinnant wrote:
namespace Mine {
struct Person {};
struct Female : public Person {};
bool isnormal(const Person&);
}
int main() { using namespace boost; // for boost::bind (just as an example) Mine::Female Jane; bool b = isnormal(Jane); }
If this code doesn't make you nervous (because of the using directive), the related code below might:
namespace Mine {
struct sense_of_humor {};
struct Person : private boost::optional<sense_of_humor> {};
struct Female : public Person {};
bool isnormal(const Person&);
bool foo() { Female Jane; return isnormal(Jane); }
} // Mine
int main() { Mine::foo(); }
Again, isnormal will get hijacked by boost::isnormal(T) if it is in the translation unit (and in namespace boost and not somehow constrained).
Won't bool isnormal(const Person&) be the better overload and therefore the one called? The worst I can see happening is an "ambiguous overload" error. BTW "isnorm" (note the spelling) should be in boost::math:: not boost:: so the risk is somewhat reduced.
template <class T> typename enable_if < std::numeric_limits<T>::is_specialized, bool
type isnormal(T t) {...}
Sigh, yes I can see the point of that, I'm fighting against it because it would break *my* code: it uses numeric types (NTL::RR) for which std::numeric_limits<> support is not appropriate, 'cos the precision is not a compile time constant. I could use another traits class that defaults to std::numeric_limits<T>::is_specialized but provides a backdoor for other types I guess. John.

John Maddock wrote:
Howard Hinnant wrote:
On Jul 25, 2006, at 1:45 PM, Howard Hinnant wrote:
namespace Mine {
struct Person {};
struct Female : public Person {};
bool isnormal(const Person&);
}
int main() { using namespace boost; // for boost::bind (just as an example) Mine::Female Jane; bool b = isnormal(Jane); } If this code doesn't make you nervous (because of the using directive), the related code below might:
namespace Mine {
struct sense_of_humor {};
struct Person : private boost::optional<sense_of_humor> {};
struct Female : public Person {};
bool isnormal(const Person&);
bool foo() { Female Jane; return isnormal(Jane); }
} // Mine
int main() { Mine::foo(); }
Again, isnormal will get hijacked by boost::isnormal(T) if it is in the translation unit (and in namespace boost and not somehow constrained).
Won't bool isnormal(const Person&) be the better overload and therefore the one called? The worst I can see happening is an "ambiguous overload" error.
BTW "isnorm" (note the spelling) should be in boost::math:: not boost:: so the risk is somewhat reduced.
template <class T> typename enable_if < std::numeric_limits<T>::is_specialized, bool
type isnormal(T t) {...}
Sigh, yes I can see the point of that, I'm fighting against it because it would break *my* code: it uses numeric types (NTL::RR) for which std::numeric_limits<> support is not appropriate, 'cos the precision is not a compile time constant. I could use another traits class that defaults to std::numeric_limits<T>::is_specialized but provides a backdoor for other types I guess.
John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
The functions isnorm etc do not have to be in namespace boost. Put them in some nested namespace, such as boost::fp_classification. Then nobody is likely to bring them into scope unknowingly. --Johan Råde

On Jul 26, 2006, at 4:55 AM, John Maddock wrote:
Won't bool isnormal(const Person&) be the better overload and therefore the one called? The worst I can see happening is an "ambiguous overload" error.
Fwiw, here's a standalone test. But at this point it's academic as I didn't know about boost::math which I think is probably sufficient protection. #include <iostream> namespace boost { template <class T> bool isnormal(T t) {std::cout << "boost::isnormal\n"; return true;} template<class T> class optional {}; } namespace Mine { struct sense_of_humor {}; struct Person : private boost::optional<sense_of_humor> {}; struct Female : public Person {}; bool isnormal(const Person&) {std::cout << "Mine::isnormal\n"; return false;} bool foo() { Female Jane; return isnormal(Jane); } } int main() { Mine::foo(); } This prints out "boost::isnormal" for me. -Howard

John Maddock wrote:
Oh, actually I need generic versions of these functions in order to make parts of the math toolkit I'm working on generic: at the very least these scale to pretty much anything that has numeric_limits defined, without that all you can do is assume the number is a zero or a normal: but that's OK too because most (all?) extended precision types like NTL::RR don't support infinities or NaN's anyway.
Sounds like another good test candidate for C++0x Concepts ;?) -- AlisdairM

AlisdairM wrote:
John Maddock wrote:
Oh, actually I need generic versions of these functions in order to make parts of the math toolkit I'm working on generic: at the very least these scale to pretty much anything that has numeric_limits defined, without that all you can do is assume the number is a zero or a normal: but that's OK too because most (all?) extended precision types like NTL::RR don't support infinities or NaN's anyway.
Sounds like another good test candidate for C++0x Concepts ;?)
Yes please :-) In fact they would work very well in situations like this. John.

John Maddock wrote:
Johan Råde wrote:
So it would make sense to have the functions
is_finite() is_normal() is_subnormal()
is_infinity() is_plus_infinity() is_minus_infinity()
is_nan()
Do we really want to use gratuitously different names from those in C99:
isfinite isnorm isinf isnan
Yes ! Once again there is no reason to let the "C" language determine how things are done in "C++". The names suggested by Johan Rade are much more easily rememberable than the "C" names above.

John Maddock wrote:
Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Yes! I'm working on these and other functions, see http://www.johnmaddock.co.uk/toolkit for a reasonably recent sets of docs, follow the link to floating point classification.
HTH, John.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I think John Maddock is well qualified to submit a general is_nan function. He has obviously thought a lot about floating point arithemtic and tested things on several different platforms. He is working on a math tool kit library that contains an is_nan function. Maybe he could just extract that function and submit it. --Johan Råde

Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
The date_time library contains the following is_nan function: static bool is_nan(const T& x) { return std::numeric_limits<T>::has_quiet_NaN && (x != x); } It has been pointed out by Martin Bonner that this is not safe, for it requires strict IEEE 754 compliance and it may be optimized away by an over-eager optimizing compiler. Here is the implementation I'm currently using: //------------------------------------------------------------------- #if defined(BOOST_MSVC) // Microsoft Visual C++ template<class T> int is_nan(T t) { return _isnan(t); } #elif defined(__GNUC__) // GCC template<class T> int is_nan(T t) { return isnan(t); } #else // generic template<class T> int is_nan(T t) { if(std::numeric_limits<T>::has_infinity) return !(t <= std::numeric_limits<T>::infinity()); else return t != t; } #endif //-------------------------------------------------------------------- Comments? Anyone wants to add more #if's? --Johan Råde

John Maddock wrote:
Johan Råde wrote:
Comments? Anyone wants to add more #if's?
Quite a few! :-)
See attached.
John.
Impressive. You seem to have thought of everything. I'm just a bit concerned about efficiency. For instance, if I call your isnan and I use VC++, then the following happens: 1. _fpclass is called 2. a switch statement is called to translate the result 3. the translated result is compared against FP_NAN Just doing x != x must be a lot faster, and works, at least on VC++ 7.1, even with compiler optimizations turned on. I have situations where I want to check every element in an array with more than 100,000,000 elements, so I care about efficiency. --Johan

Johan Råde wrote:
Impressive. You seem to have thought of everything. I'm just a bit concerned about efficiency. For instance, if I call your isnan and I use VC++, then the following happens:
1. _fpclass is called 2. a switch statement is called to translate the result 3. the translated result is compared against FP_NAN
Just doing x != x must be a lot faster, and works, at least on VC++ 7.1, even with compiler optimizations turned on.
I have situations where I want to check every element in an array with more than 100,000,000 elements, so I care about efficiency.
Understood, it's a question of getting a portable version - maybe an overly pessimistic version - and then adding optimisations for specific compilers where required. Actually MSVC has _isnan, so I really should be calling that :-) Likewise platforms that have an isnan macro should use it etc... John.

Johan Råde wrote:
Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
The date_time library contains the following is_nan function:
static bool is_nan(const T& x) { return std::numeric_limits<T>::has_quiet_NaN && (x != x); }
It has been pointed out by Martin Bonner that this is not safe, for it requires strict IEEE 754 compliance and it may be optimized away by an over-eager optimizing compiler.
FYI, this is basically unused code in that date_time int_adapter (note name) is only ever used with integer types internally. This really should be removed to avoid confusion... Jeff

Joe Gottman wrote:
Several libraries have an is_nan() function buried deep in the code. Are there any plans to make a general is_nan function available? This would be quite useful, as well as similar functions like is_finite.
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
An interesting observation: The is_nan implementation x!=x works, while !((x<=0)||(x>=0)) does not work on VC++ 7.1, with optimizations turned on. It seems that !((x<=0)||(x>=0)) is evaluated to false at compile time while x!=x is evaluated at run time. Could it be that the compiler has a special rule that says, do not optimize the expression x!=x, precisely because it is a common implementation of isnan? Does anyone know if x!=x actually fails on any real world platform? Maybe we should just keep using x!=x ? --Johan Råde
participants (10)
-
AlisdairM
-
Edward Diener
-
Howard Hinnant
-
Jeff Garland
-
Joe Gottman
-
Johan Råde
-
John Maddock
-
me22
-
Paul A Bristow
-
Paul Giaccone