<div dir="ltr"><div>Chris, this is a case of gradual underflow, and it seems like it is not handled correctly in Float class>>fromIEEE32Bit: .<br></div>Since the method has my initials, I'll try to sort out what the mess is...<br></div><div class="gmail_extra"><br><div class="gmail_quote">2014-12-23 21:50 GMT+01:00 Chris Muller <span dir="ltr"><<a href="mailto:asqueaker@gmail.com" target="_blank">asqueaker@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Mon, Dec 22, 2014 at 3:59 AM, Bert Freudenberg <<a href="mailto:bert@freudenbergs.de">bert@freudenbergs.de</a>> wrote:<br>
> On 22.12.2014, at 00:13, Levente Uzonyi <<a href="mailto:leves@elte.hu">leves@elte.hu</a>> wrote:<br>
>><br>
>> ConverterFloatArray at: 1 put: self; basicAt: 1.<br>
><br>
> Any reason not to use this in #asIEEE32BitWord? Endianness? Arch-dependency?<br>
><br>
> I see, it's not thread-safe. This would be:<br>
><br>
> (FloatArray new: 1) at: 1 put: self; basicAt: 1.<br>
><br>
> Might still be faster?<br>
<br>
</div></div>Yes. Since creation of a one-element FloatArray every time did not<br>
adversely affect performance of Levente's too significantly (only 3.7X<br>
instead of 4.0X faster), I decided it was worth the cost of the<br>
allocation than to worry about concurrency. So I ended up with<br>
Levente's latest except I cannot risk a calculation ending up -0.0, so<br>
I have to account for it too. And, NaN too. Thus:<br>
<br>
hashKey32<br>
| bits |<br>
self = NegativeInfinity ifTrue: [ ^ 0 ].<br>
self = Infinity ifTrue: [ ^ 4294967294 ].<br>
self = NaN ifTrue: [ ^ 4294967295 ].<br>
self = NegativeZero ifTrue: [ ^ 2147483651 ].<br>
bits := (FloatArray new: 1) at: 1 put: self; basicAt: 1.<br>
self < 0.0 ifTrue: [ ^ 4286578688 - bits ].<br>
^ 2147483651 + bits<br>
<br>
Since there are not a full 32-bits worth of IEEE 32-bit floats (e.g.,<br>
several thousand convert to NaN), it might be wise to move +Infinity<br>
and NaN _down_ a bit from the very maximum, for better continuity<br>
between the float and integer number lines, or for potential future<br>
special-case needs..?<br>
<br>
In any case, I wanted to at least see if what we have, above, works<br>
for every 32-bit IEEE float. To verify that, I enumerated all Floats<br>
in numerical order from -Infinity to +Infinity by creating them via<br>
#fromIEEE32BitFloat: from the appropriate ranges.<br>
<br>
It hit a snag at 2151677948. Check this out:<br>
<br>
| this next |<br>
this := Float fromIEEE32Bit: 2151677949.<br>
next := Float fromIEEE32Bit: 2151677948.<br>
self<br>
assert: next > this ;<br>
assert: ((FloatArray new: 1) at: 1 put: (next); basicAt: 1)<br>
> ((FloatArray new: 1) at: 1 put: (this); basicAt: 1)<br>
<br>
As I thought, the representations between IEEE floats and FloatArray<br>
floats are different-enough that their precisions align differently<br>
onto the 32-bit map for these two floats. IEEE's are precise-enough<br>
to distinguish these two floats, FloatArray representations are not.<br>
<br>
That these guys are considered "equal" by the FloatArray is actually<br>
good enough for my indexing requirement, but now I'm looking at the<br>
prim-fail code for FloatArray:<br>
<br>
at: index<br>
<primitive: 'primitiveAt' module: 'FloatArrayPlugin'><br>
^Float fromIEEE32Bit: (self basicAt: index)<br>
<br>
If this or the #at:put: primitive were to ever fail on the storage<br>
(at:put:) exclusive-or the access (at:) side, then it appears<br>
FloatArray itself would retrieve a value different than was stored..!<br>
<br>
</blockquote></div><br></div>