[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 
http://bugs.squeak.org/view.php?id=6983

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

Definition is very simple and answer false both for nans and infinities
isFinite
     ^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=6601

>> 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 
http://www.cs.chalmers.se/~kent/ISOStandards/SC22/WG11/LIA-2/N424.ps

But you can read page 8 of Kahan's 
http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF
(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!
> 

Thanks

> Cheers,
>   - Andreas
> 
> 




More information about the Squeak-dev mailing list