Eliot Miranda

2018-11-21 18:45:54 UTC

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

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