
2010/3/29 Chad Nelson <chad.thecomfychair@gmail.com>:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
An xint::integer which is +infinity or -infinity is more meaningful than one which is NaN.
Agreed -- but only slightly. It carries one additional bit's worth of meaning, the sign.
Even if you identify +infinity and -infinity as a single infinity, it should *still* mean something different from an NaN. You might group infinity into the class of NaNs, but that doesn't mean that every operation which results in an NaN may as well result in an infinity (signed or unsigned). 0/0 and sqrt(-1) should evaluate to an NaN (or throw); it would be unsettling to evaluate these as infinity.
I guess I'm not explaining myself very well. I was suggesting using the NaN value as infinity only where you need an infinity value. The only viable use I've seen suggested for infinity, in this library, is for unbounded intervals (which I'll address below).
At the very least, you can make more refined calculations and comparisons with +/-infinity (compared to NaN),
Do you have an example where this would make any noticeable difference in XInt?
Noticeable in what sense? 1/NaN is NaN; 1/+infinity is +0 (or 1/infinity is 0 if you don't want signed infinities and zeros). Assuming, of course, you allow calculations with NaNs.
Noticeable in the sense that it would make any difference to people using the library.
An interval consists of two points. Setting the lower point to Not-a-Number would work exactly the same as setting it to -infinity. Same with the higher point and +infinity. It wouldn't make any sense to set the lower point to +infinity, or the higher one to -infinity, so the sign doesn't convey any useful information in that case.
Since NaN compares false to anything else, good luck getting your intervals with NaN endpoints to work in any kind of generic setting ;)
Now that's a decent argument for infinity values. Though I'm still not sure whether they'd ever be used... is there a scientific or mathematical use of intervals that you can foresee this library being used for?
Hi Chad, as an author of a library of intervals and interval containers, I have encountered places in my library design, where infinity values not only seemed to be useful but also appeared to be a "natural" solution. Natural, in this context means, easy to understand and in line with common math knowledge. (1) Complement of an interval set: complement({[0..0]}) == {(-inf..0), (0..+inf)} If we had infinity values, we could always define the complements of interval sets, like in the example above. (2) Size of an interval set: Throughout the stl, the size function returns the number of elements for containers. So for an std::set, we have {1,2, 5,6,7}.size() == 5 As interval set of integers this is {[1..2], [5..7]}.size() == 5 but for an interval set of doubles we have a "theoretic" result {[1.0..2.0], [5.0..7.0]}.size() == inf because the number of elements in this set of reals is *theoretically* infinite. In both cases, if felt kind of compelled to use infinity values. While these use cases seem to provide good reasons to introduce infinity values for integral numbers, I never had any use for "not a number" values. Contrary to infinities that are a part both of natural and mathematical language, not-a-number values appear pretty bizarr to me ... Their meaning is a contradiction in itself and their properties are non-intuitive. Meanwhile I doubt the usefulness of both of them, NaN and Infinity, on fundamental numeric types. Since there is the IEEE 754 for floating point numbers that proposes them, there is probably a vast amount of mathematical and numerical expert knowledge that this standard is based on. But my gut feeling is different. I think, the values of a numeric types should be (1) closed under their fundamental operations e.g. +. (2) Their values should be reachable from the initial value 0 or T() applying (fundamental) operations. Where operations are not defined like y/0, instead of introducing NaN, the undefined case should be guarded against by (1) program logic (asserts) or (2) denominator checks, if the condition can not be determined from the program logic otherwise. Neither NaN nor +/-Inf can be computed from 0 using fundamental operations like ++, +, -- and -. But the user can assign them to variables integer myNaN = integer(not_a_number()); and pass them to any operation that is provided by your type. So you have to check for NaN in every single function you implement. IIUC you provide NaN as emergency result for 3 functions only. Neither of these is fundamental to integral types. I don't think these functions justify to spoil the whole type with NaNs. My be it would be more interesting to provide the minimal and "pure" numeric type and provide a NaN and Infinity closure as template template<class IntegralT, class ClosureTraits=...> closed { ... } because the way in which NaNs, Infinities (and maybe more special values) are handled should be the same for all the different implementations of integral numeric types. Concerning my own yearning for infinity, I had the insight, that I can provide infinitely open interval borders myself as a property of my interval type. So I can be independent of the properties of my parameter types in case of example (1: complement). For example (2: size) I can provide an is_infinite() function instead, with a little loss of simplicity though. Generally I think we should avoid special values for integral numeric types. Thank you for submitting your library. If I find time, I might try to use it with my ITL library of interval containers. Cheers Joachim