Hi Eliot,

On Cuis I have been recently working on hash consistency for numeric types, making same value (or different values that compare as equal due to rounding) answer same hash regardless of class. But I have missed the SmallInteger / LargeInteger consistency across 32 / 64 bits images. Thanks! Fixes for Cuis now at GitHub repo. In particular, it is necessary for the following to answer the same values in 32 and 64 bits (it wasn't the case!):


largeInteger := (LargePositiveInteger new: 4)
            digitAt: 1 put: 1;
            digitAt: 2 put: 2;
            digitAt: 3 put: 3;
            digitAt: 4 put: 4;
            yourself.
smallInteger := largeInteger normalize.
float := smallInteger asFloat.
boxedFloat := BoxedFloat64 new basicAt: 1 put: (float basicAt: 1); basicAt: 2 put: (float basicAt: 2); yourself.
{largeInteger class. smallInteger class. float class. boxedFloat class.
largeInteger hash. smallInteger hash. float hash. boxedFloat hash } print.



largeInteger _ (LargePositiveInteger new: 4)
            digitAt: 1 put: 1;
            digitAt: 2 put: 2;
            digitAt: 3 put: 3;
            digitAt: 4 put: 80;
            yourself.
smallIntIn64ButLargeIntIn32Bits := largeInteger normalize.
float := smallIntIn64ButLargeIntIn32Bits asFloat.
boxedFloat := BoxedFloat64 new basicAt: 1 put: (float basicAt: 1); basicAt: 2 put: (float basicAt: 2); yourself.
{largeInteger class. smallIntIn64ButLargeIntIn32Bits class. float class. boxedFloat class.
largeInteger hash. smallIntIn64ButLargeIntIn32Bits hash. float hash. boxedFloat hash } print.


Note that I also included consistency between un-normalized LargeIntegers in the SmallInteger range (just in case).

On 11/21/2018 3:45 PM, Eliot Miranda via Cuis-dev wrote:
Hi All,

    right now we have the following definition of Large(Positive)Integer>>hash:

hash
^ByteArray hashBytes: self startingWith: self species hash

which means that for all integers outside of the 32-bit SmallInteger range (-2 ^ 30 to 2 ^ 30 - 1), the 32-bit system and the 64-bit system answer different values for hash.

e.g. in 64 bits: (2 raisedTo: 30) hash 1073741824
 but in 32 bits: (2 raisedTo: 30) hash 230045764

This is unsatisfactory.  I propose changing Large(Positive)Integer>>hash to

hash
^self digitLength <= 8
ifTrue: [self]
ifFalse: [ByteArray hashBytes: self startingWith: self species hash]


P.S. Note that this will not break Float hash, which is defined as

Float>>hash
"Hash is reimplemented because = is implemented. Both words of the float are used. (The bitShift:'s ensure that the intermediate results do not become a large integer.) Care is taken to answer same hash as an equal Integer."

(self isFinite and: [self fractionPart = 0.0]) ifTrue: [^self truncated hash].
^ ((self basicAt: 1) bitShift: -4) +
  ((self basicAt: 2) bitShift: -4)

P.P.S. I *think* that "(self isFinite and: [self fractionPart = 0.0])" is equivalent to "self - self = self fractionPart" ;-)

_,,,^..^,,,_
best, Eliot


Cheers,
-- 
Juan Vuletich
www.cuis-smalltalk.org
https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
https://github.com/jvuletich
https://www.linkedin.com/in/juan-vuletich-75611b3
@JuanVuletich