[squeak-dev] The Inbox: Kernel-nice.1260.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue Aug 20 10:48:04 UTC 2019
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!
More information about the Squeak-dev
mailing list
|