The Trunk: Kernel-nice.853.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Kernel-nice.853.mcz

commits-2
Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-nice.853.mcz

==================== Summary ====================

Name: Kernel-nice.853
Author: nice
Time: 21 May 2014, 2:52:52.286 am
UUID: 0c682a44-c243-440b-8caf-399be09824bc
Ancestors: Kernel-eem.852

Introduce an isAnExactFloat test, which is true when a Number can be converted as Float exactly.
Use this to boost some mixed arithmetic comparisons by avoidance of Float>>asTrueFraction in more cases.
Use this to make Fraction>>hash more explicit.
While at it, improve a bit the Fraction>>hash in inexact case (previous naive bitXor: causes too many collisions)
Since some hash has been modified, rehashAll in postscript.

=============== Diff against Kernel-eem.852 ===============

Item was changed:
  ----- Method: Float>>adaptToFraction:andCompare: (in category 'converting') -----
  adaptToFraction: rcvr andCompare: selector
  "If I am involved in comparison with a Fraction, convert myself to a
  Fraction. This way, no bit is lost and comparison is exact."
 
  self isFinite
  ifFalse: [
  selector == #= ifTrue: [^false].
  selector == #~= ifTrue: [^true].
  self isNaN ifTrue: [^ false].
  (selector = #< or: [selector = #'<='])
  ifTrue: [^ self positive].
  (selector = #> or: [selector = #'>='])
  ifTrue: [^ self positive not].
  ^self error: 'unknow comparison selector'].
 
  "Try to avoid asTrueFraction because it can cost"
+ rcvr isAnExactFloat ifTrue: [^rcvr asExactFloat perform: selector with: self].
+ selector == #= ifTrue: [^false].
+ selector == #~= ifTrue: [^true].
- selector == #= ifTrue: [
- rcvr denominator isPowerOfTwo ifFalse: [^false]].
- selector == #~= ifTrue: [
- rcvr denominator isPowerOfTwo ifFalse: [^true]].
-
  ^ rcvr perform: selector with: self asTrueFraction!

Item was changed:
  ----- Method: Float>>adaptToInteger:andCompare: (in category 'converting') -----
  adaptToInteger: rcvr andCompare: selector
  "If I am involved in comparison with an Integer, convert myself to a
  Fraction. This way, no bit is lost and comparison is exact."
 
  self isFinite
  ifFalse: [
  selector == #= ifTrue: [^false].
  selector == #~= ifTrue: [^true].
  self isNaN ifTrue: [^ false].
  (selector = #< or: [selector = #'<='])
  ifTrue: [^ self positive].
  (selector = #> or: [selector = #'>='])
  ifTrue: [^ self positive not].
  ^self error: 'unknow comparison selector'].
 
  "Try to avoid asTrueFraction because it can cost"
  selector == #= ifTrue: [
  self fractionPart = 0.0 ifFalse: [^false]].
  selector == #~= ifTrue: [
  self fractionPart = 0.0 ifFalse: [^true]].
 
+ rcvr isAnExactFloat ifTrue: [^rcvr asExactFloat perform: selector with: self].
+ selector == #= ifTrue: [^false].
+ selector == #~= ifTrue: [^true].
  ^ rcvr perform: selector with: self asTrueFraction!

Item was changed:
  ----- Method: Float>>adaptToScaledDecimal:andCompare: (in category 'converting') -----
  adaptToScaledDecimal: rcvr andCompare: selector
  "If I am involved in comparison with a scaled Decimal, convert myself to a
  Fraction. This way, no bit is lost and comparison is exact."
 
  self isFinite
  ifFalse: [
  selector == #= ifTrue: [^false].
  selector == #~= ifTrue: [^true].
  self isNaN ifTrue: [^ false].
  (selector = #< or: [selector = #'<='])
  ifTrue: [^ self positive].
  (selector = #> or: [selector = #'>='])
  ifTrue: [^ self positive not].
  ^self error: 'unknow comparison selector'].
 
+ "Try to avoid asTrueFraction because it can cost"
+ rcvr isAnExactFloat ifTrue: [^rcvr asExactFloat perform: selector with: self].
+ selector == #= ifTrue: [^false].
+ selector == #~= ifTrue: [^true].
  ^ rcvr perform: selector with: self asTrueFraction!

Item was added:
+ ----- Method: Float>>isAnExactFloat (in category 'testing') -----
+ isAnExactFloat
+ ^true!

Item was added:
+ ----- Method: Fraction>>asExactFloat (in category 'converting') -----
+ asExactFloat
+ "When we know that this Fraction is an exact Float, this conversion is much faster than asFloat."
+
+ ^numerator asFloat timesTwoPower: 1 - denominator highBit!

Item was changed:
  ----- Method: Fraction>>hash (in category 'comparing') -----
  hash
+ "Hash is reimplemented because = is implemented."
- "Hash is reimplemented because = is implemented.
- Care is taken that a Fraction equal to a Float also have an equal hash"
-
- | tmp |
- denominator isPowerOfTwo ifTrue: [
- "If denominator is a power of two, I can be exactly equal to a Float"
- tmp := self asFloat.
- tmp isFinite ifTrue: [^tmp hash]].
 
+ "Care is taken that a Fraction equal to a Float also has an equal hash"
+ self isAnExactFloat ifTrue: [^self asExactFloat hash].
+
+ "Else, I cannot be exactly equal to a Float, use own hash algorithm."
+ ^numerator hash hashMultiply bitXor: denominator hash!
- "Else, I cannot be exactly equal to a Float, use own hash algorithm.
- (Assume the fraction is already reduced)"
- ^numerator hash bitXor: denominator hash!

Item was added:
+ ----- Method: Fraction>>isAnExactFloat (in category 'testing') -----
+ isAnExactFloat
+ "Answer true if this Fraction can be converted exactly to a Float"
+ ^ denominator isPowerOfTwo
+ and: ["I have a reasonable significand: not too big"
+ numerator highBitOfMagnitude <= Float precision
+ and: ["I have a reasonable exponent: not too small"
+ Float emin + denominator highBitOfMagnitude <= Float precision]]!

Item was added:
+ ----- Method: Integer>>isAnExactFloat (in category 'testing') -----
+ isAnExactFloat
+ "Answer true if this Integer can be converted exactly to a Float"
+ | h |
+ (h := self highBitOfMagnitude) <= Float precision
+ ifTrue: [^ true].
+ ^ h - 1 <= Float emax
+ and: [h - self abs lowBit < Float precision]!

Item was changed:
  ----- Method: Number>>adaptToFloat:andCompare: (in category 'converting') -----
  adaptToFloat: rcvr andCompare: selector
  "If I am involved in comparison with a Float, convert rcvr to a
  Fraction. This way, no bit is lost and comparison is exact."
 
  rcvr isFinite
  ifFalse: [
  selector == #= ifTrue: [^false].
  selector == #~= ifTrue: [^true].
  rcvr isNaN ifTrue: [^ false].
  (selector = #< or: [selector = #'<='])
  ifTrue: [^ rcvr positive not].
  (selector = #> or: [selector = #'>='])
  ifTrue: [^ rcvr positive].
  ^self error: 'unknow comparison selector'].
 
+ "Try to avoid asTrueFraction because it can cost"
+ self isAnExactFloat ifTrue: [^rcvr perform: selector with: self asExactFloat].
+ selector == #= ifTrue: [^false].
+ selector == #~= ifTrue: [^true].
  ^ rcvr asTrueFraction perform: selector with: self!

Item was added:
+ ----- Method: Number>>asExactFloat (in category 'converting') -----
+ asExactFloat
+ "Convert this number asFloat with a priori knowledge that it is an exact Float.
+ Some subclass might exploit this knowledge for a faster implementation.
+ Only send this if self isAnExactFloat."
+ ^self asFloat!

Item was added:
+ ----- Method: Number>>isAnExactFloat (in category 'testing') -----
+ isAnExactFloat
+ "Answer true if this Number can be converted exactly to a Float"
+ ^self subclassResponsibility!

Item was added:
+ ----- Method: ScaledDecimal>>asExactFloat (in category 'converting') -----
+ asExactFloat
+ ^fraction asExactFloat!

Item was added:
+ ----- Method: ScaledDecimal>>isAnExactFloat (in category 'testing') -----
+ isAnExactFloat
+ ^fraction isAnExactFloat!

Item was changed:
+ (PackageInfo named: 'Kernel') postscript: 'HashedCollection rehashAll.'!
- (PackageInfo named: 'Kernel') postscript: 'Deprecation showDeprecationWarnings: Preferences showDeprecationWarnings.
- Preferences removePreference: #showDeprecationWarnings.'!