[squeak-dev] Re: [ANN] Number comparison, hash, NaN, Point, and other partially ordered sets

nicolas cellier ncellier at ifrance.com
Tue Jan 6 22:20:31 UTC 2009

Andreas Raab a écrit :
> nicolas cellier wrote:
>> I think I now have an acceptable and consistent solution.
>> This is spreaded across several mantis bug reports:
> Wow. This is quite a bit of work. Here are some comments:
>> http://bugs.squeak.org/view.php?id=3374
> [transitive equality of arithmetic comparison]
> I'm a little confused here which version is the "correct" patch. I'm 
> assuming it's the M3374-xxx versions of the files - if not, please let 
> me know.

Yes, the correct version is the one corresponding to last Installer hook 
in bugnotes.

> I generally like the solution proposed for comparisons here but the 
> coercion methods itself look a little odd: First, they appear to rely on 
> a method #isFinite which is not defined anywhere and second -assuming 
> that isFinite returns false for well-defined infinities like IEEE 754- I 
> am not sure why two infinities should not compare equal. I don't have my 
> IEEE 754 spec handy but at least for Float I think that is well defined. 
> Can you explain your reasoning here a little more?

isFinite is a pre-requisite that can be found at 

This is corresponding to Installer hook (Installer mantis ensureFix: 6983)

Definition is very simple and answer false both for nans and infinities
     ^self - self = 0.0

Concerning equality of infinities, I think IEEE 754 say they are equal
Once, i did wonder why. My rationale is
	(Float infinity - Float infinity) isNan.
Since the difference of two infinities is not defined, how can we decide 
they represent equal quantities ?
I developped this theme at http://bugs.squeak.org/view.php?id=6729

However, I did not change anything, that would mean change IEEE, 
hardware implementation, etc... A bit too much.

The only thing I change is this:
	(10 raisedTo: 400) < Float infinity.
It used to be equal, because it's asFloat avatar isInfinite...

> I really like the fix for Integer/Fraction/Float hash.

Then thank Andrew Tween for the base idea 

>> http://bugs.squeak.org/view.php?id=6719
> [NaN comparisons]
> This one I don't like quite as much. How about a much simpler version 
> along the lines of:
> Magnitude <= aMagnitude
>     "Answer whether the receiver is less than or equal to the argument."
>     ^(self > aMagnitude or:[aMagnitude isNaN]) not
> Etc. This should work just as well and requires only changes in 
> Magnitude instead of polluting too many subclasses (may require 
> promoting isNaN to Magnitude).

Agree, this is much more simple.
I was probably biased by other situations when there is not a total 
order like Number and Point comparison.

However there are other cases like these ones where it could serve:

(1/2) < #(0 1 2). "#(false true true)"
(1/2) > #(0 1 2). "Array does not understand <"

(1/2) < '1'. "true"
(1/2) > '1'. "Error: Instances of Fraction are not indexable"

I agree, these are not beautiful examples, some functionalities that 
might better take there way out of the image.

Notice that:
3 > '2' and: [3.0 > '2']. "true"

Why not define in Fraction what already is in Integer and Float?

> Also, out of curiosity, what's your take on the IEEE 754 requirement 
> that NaN compares not equal to itself? This breaks fundamental 
> relationships (for example you can't use NaN in Sets or Dicts) and my 

Gasp, I thought I could retrieve an official reference...
successor ISO/IEC 10967-2 is not very verbose about that 

But you can read page 8 of Kahan's 
(via http://en.wikipedia.org/wiki/IEEE_754-1985)

Anyway, this is implemented by all libraries I know of:

#include <stdio.h>
int main() {
double nan;
nan =0.0 / 0.0;
printf("nan == nan is %s\n",(nan==nan)?"true":"false");
return 0;

Just try the Smalltalk primitive to confirm...
Float nan = Float nan

> feeling has always been that it would be more useful if:
> * there was a bit-fiddling test for Float>>isNaN
> * NaNs would compare equal to itself (though not necessarily to NaNs 
> with different bit-patterns)
> * Standard float prims would *never* return NaN but rather fail
> The last one proved tremendously helpful in Croquet where I've been 
> using fdlibm and simply fail any float prims that would produce NaNs. 
> The image can then take care of it properly.

Agree, I much prefer an Exception (a pimitiveFail) to a NaN.
NaN is not of any use in Smalltalk, except for hooking a poor man 
external world.

>> http://bugs.squeak.org/view.php?id=7259
> [point-number comparisons]
> This is an elegant solution (nice use of adaptTo:andCompare:) but I'm 
> not sure how much code will break with it. Have you tried running this 
> for a while in daily use?

No, I have absolutely no guaranty.
My Rationale is as follow:
-1) old behaviour is rather broken
	(1/2) > (1 @3). "MNU"
	2 <= (1 at 3). "true ???"
	2 >= (1 at 3). "true ???"
-2) It is easy to revert to a (corrected) coercion behaviour

Point>>adaptToNumber: rcvr andCompare: comparisonSelector
     ^rcvr at rcvr perform: comparisonSelector with: self

However, such coercion would be a typical case where defining
Magnitude >= aMagnitude
	^(self > aMagnitude or:[aMagnitude isNaN]) not
would not work... (even if Point>>isNan is defined).

>> http://bugs.squeak.org/view.php?id=7260
> [float prim behavior with NaN]
> I'm with you on this one. The primitives are very, very badly broken at 
> this point and I'm really surprised this has escaped us for so long.
> All in all, this is great stuff!


> Cheers,
>   - Andreas

More information about the Squeak-dev mailing list