Nicolas Cellier uploaded a new version of Kernel to project The Inbox:
http://source.squeak.org/inbox/Kernel-nice.1260.mcz ==================== Summary ==================== Name: Kernel-nice.1260 Author: nice Time: 20 August 2019, 12:47:47.233148 pm UUID: 71e9900d-adf5-194d-be4b-28fbe395a937 Ancestors: Kernel-nice.1259 Fast-up the SmallInteger/Float comparisons This is not necessary in 32 bits images, because SmallInteger asFloat is exact, so comparison can be performed exactly by the primitive and is already very fast. But in 64bits images, SmallInteger asFloat may be inexact. Thus the primitive may fail, reverting to slower adaptToFloat:andCompare: Though, we can perform the comparison very simply for SmallInteger: if anInteger asFloat == aFloat then we are not sure that anInteger asFloat did not introduce a rounding error. However, in this case, we know that aFloat has no fraction part, and that it can be converted back to Integer exactly (without fear of overflow). So we just have to perform the comparison the other way around, anInteger op: aFloat truncated if anInteger asFloat != aFloat, then we are safe, the rounding error cannot modify the result of operation, so we simply return the result of anInteger asFloat op: aFloat I put this in the inbox so as to show and demonstrate the hack, but IMO the right place would be in the primitive (and JIT) because the scheme is simple enough. =============== Diff against Kernel-nice.1259 =============== Item was changed: ----- Method: SmallInteger>>< (in category 'comparing') ----- < aNumber "Primitive. Compare the receiver with the argument and answer with true if the receiver is less than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 3> + aNumber isFloat ifTrue: [| asFloat | + ^(asFloat := self asFloat) = aNumber + ifTrue: [self < aNumber truncated] + ifFalse: [asFloat < aNumber] ]. ^super < aNumber! Item was changed: ----- Method: SmallInteger>><= (in category 'comparing') ----- <= aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is less than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive. " <primitive: 5> + aNumber isFloat ifTrue: [| asFloat | + ^(asFloat := self asFloat) = aNumber + ifTrue: [self <= aNumber truncated] + ifFalse: [asFloat <= aNumber] ]. ^super <= aNumber! Item was changed: ----- Method: SmallInteger>>= (in category 'comparing') ----- = aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive. " <primitive: 7> + aNumber isFloat ifTrue: [ ^self asFloat = aNumber and: [self = aNumber truncated] ]. ^super = aNumber! Item was changed: ----- Method: SmallInteger>>> (in category 'comparing') ----- > aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Essential. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 4> + aNumber isFloat ifTrue: [| asFloat | + ^(asFloat := self asFloat) = aNumber + ifTrue: [self > aNumber truncated] + ifFalse: [asFloat > aNumber] ]. ^super > aNumber! Item was changed: ----- Method: SmallInteger>>>= (in category 'comparing') ----- >= aNumber "Primitive. Compare the receiver with the argument and answer true if the receiver is greater than or equal to the argument. Otherwise answer false. Fail if the argument is not a SmallInteger. Optional. No Lookup. See Object documentation whatIsAPrimitive." <primitive: 6> + aNumber isFloat ifTrue: [| asFloat | + ^(asFloat := self asFloat) = aNumber + ifTrue: [self >= aNumber truncated] + ifFalse: [asFloat >= aNumber] ]. ^super >= aNumber! Item was added: + ----- Method: SmallInteger>>adaptToFloat:andCompare: (in category 'converting') ----- + adaptToFloat: rcvr andCompare: selector + "If I am involved in comparison with a Float, care to perform an exact comparison of values." + + | asFloat | + "First try cheap asFloat conversion. + There is no comparison ambiguity when self does not round to same Float value" + asFloat := self asFloat. + (rcvr ~= asFloat or: [self isAnExactFloat]) ifTrue: [^rcvr perform: selector with: asFloat]. + "rcvr and self are not equal because self is not an exact Float, but self round to same Float value. + It is necessary to convert the Float to an exact representation so as to perform the compariosn without rounding error. + We know that the Float has no fractionPart because it is equal to self asFloat, and self asFloat has no fractionPart. + Thus we can use truncated which is faster than asTrueFraction." + selector == #= ifTrue: [^false]. + selector == #~= ifTrue: [^true]. + ^ rcvr truncated perform: selector with: self! |
Free forum by Nabble | Edit this page |