[squeakdev] The Inbox: Kernelnice.903.mcz
commits at source.squeak.org
commits at source.squeak.org
Sat Feb 14 01:20:23 UTC 2015
Nicolas Cellier uploaded a new version of Kernel to project The Inbox:
http://source.squeak.org/inbox/Kernelnice.903.mcz
==================== Summary ====================
Name: Kernelnice.903
Author: nice
Time: 14 February 2015, 2:19:44.184 am
UUID: d4f06790d47b4cb0b9ff9e0ff7dea9fc
Ancestors: Kernelnice.902
Introduce two new alternatives to integer division: #ratio: and #residue: are like #quo: and #rem: except that they round the quotient to nearest integer (tie to even) instead of truncating (note that // and \\ floor the quotient...).
The second thing that they do differently is that they compute the exact ratio and exact residue when given a pair of Float.
The third thing that they do differently is that they first coerce a pair of numbers to the highest generality before attempting any operation.
=============== Diff against Kernelnice.902 ===============
Item was added:
+  Method: Float>>fratio: (in category 'mathematical functions') 
+ fratio: aFloat
+ "Compute the exact ratio of self divided by aFloat (rounded to nearest integer, tie to even).
+ The result is either a Float in case of null (to wear correct sign) or exceptional value,
+ or an Integer (required in order to avoid overflow and inexact rounding)."
+
+  ex ey sx sy xa ya n result sign 
+ (self isFinite and: [self ~= 0.0 and: [aFloat isFinite and: [aFloat ~= 0.0]]])
+ ifFalse:
+ ["purge cases of exceptional and trivial values"
+ ^self/aFloat].
+
+ xa := self abs.
+ ya := aFloat abs.
+ ex := xa exponent.
+ ey := ya exponent.
+ sx := xa significand.
+ sy := ya significand.
+ n := ex  ey.
+ sign := self significand*aFloat significand.
+ n < 1 ifTrue: [^sign copySignTo: 0.0].
+ result := 0.
+ "subtract as many y significand as we can from x significand"
+ [(n >= 0 and: [sx >= sy])
+ ifTrue:
+ [sx := sx  sy.
+ result := 1<<n+result].
+ sx = 0.0 or: [n < 0]]
+ whileFalse:
+ [n := n  1.
+ sx := sx * 2.0].
+ (sx > sy or: [result odd and: [sx = sy]])
+ ifTrue:
+ ["Round to nearest integer, tie to even"
+ result := result + 1].
+ ^sign copySignTo: (result = 0 ifTrue: [0.0] ifFalse: [result])!
Item was added:
+  Method: Float>>fresidue: (in category 'mathematical functions') 
+ fresidue: aFloat
+ "Compute the exact residue of self divided by aFloat (rounded to nearest integer, tie to even).
+ This operation emulates libm remainder(self,aFloat) and is always exact.
+ The residue is between aFloat negated / 2 and aFloat / 2."
+
+  ex ey sx sy xa ya n sign odd roundToZero 
+ (self isFinite and: [self ~= 0.0 and: [aFloat isFinite and: [aFloat ~= 0.0]]])
+ ifFalse:
+ ["purge cases of exceptional values"
+ ^self*aFloat / (self * aFloat)].
+
+ xa := self abs.
+ ya := aFloat abs.
+ ex := xa exponent.
+ ey := ya exponent.
+ sx := xa significand.
+ sy := ya significand.
+ n := ex  ey.
+ n < 1 ifTrue: [^self].
+ sign := self.
+ roundToZero := true.
+ odd := false.
+ "subtract as many y significand as we can from x significand"
+ [(n >= 0 and: [sx >= sy])
+ ifTrue:
+ [sx := sx  sy.
+ n = 0 ifTrue: [odd := true].
+ sx = 0.0 ifTrue: [^sign copySignTo: 0.0]].
+ n < 0]
+ whileFalse:
+ [n := n  1.
+ sx := sx * 2.0].
+ (sx > sy or: [odd and: [sx = sy]])
+ ifTrue:
+ ["Round to nearest integer, tie to even"
+ sx := sx * 0.5  sy.
+ sign := sign negated]
+ ifFalse:
+ [sx := sx * 0.5].
+ ^(sign copySignTo: sx) timesTwoPower: ey!
Item was added:
+  Method: Float>>ratio: (in category 'arithmetic') 
+ ratio: aNumber
+ aNumber isFloat ifTrue: [^self fratio: aNumber].
+ ^aNumber adaptToFloat: self andSend: #ratio:!
Item was added:
+  Method: Float>>residue: (in category 'arithmetic') 
+ residue: aNumber
+ aNumber isFloat ifTrue: [^self fresidue: aNumber].
+ ^aNumber adaptToFloat: self andSend: #residue:!
Item was added:
+  Method: Fraction>>ratio: (in category 'arithmetic') 
+ ratio: aNumber
+ aNumber isFraction ifTrue: [^super ratio: aNumber].
+ ^aNumber adaptToFraction: self andSend: #ratio:!
Item was added:
+  Method: Fraction>>residue: (in category 'arithmetic') 
+ residue: aNumber
+ aNumber isFraction ifTrue: [^super residue: aNumber].
+ ^aNumber adaptToFraction: self andSend: #residue:!
Item was added:
+  Method: Fraction>>roundedTieToEven (in category 'truncation and round off') 
+ roundedTieToEven
+ "Faster than super."
+  result 
+ denominator = 2 ifFalse: [^self rounded].
+ result := numerator abs bitShift: 1.
+ result := result + (result bitAt: 1).
+ ^numerator positive
+ ifTrue: [result]
+ ifFalse: [result negated]!
Item was added:
+  Method: Integer>>ratio: (in category 'arithmetic') 
+ ratio: aNumber
+ aNumber isFraction ifTrue: [^super ratio: aNumber].
+ ^aNumber adaptToInteger: self andSend: #ratio:!
Item was added:
+  Method: Integer>>residue: (in category 'arithmetic') 
+ residue: aNumber
+ aNumber isFraction ifTrue: [^super residue: aNumber].
+ ^aNumber adaptToInteger: self andSend: #residue:!
Item was added:
+  Method: Integer>>roundedTieToEven (in category 'truncation and round off') 
+ roundedTieToEven
+ ^self!
Item was added:
+  Method: Number>>ratio: (in category 'arithmetic') 
+ ratio: aNumber
+ "Integer quotient defined by division with rounding, tie to nearest even.
+ residue: answers the remainder from this division."
+
+ ^(self / aNumber) roundedTieToEven!
Item was added:
+  Method: Number>>residue: (in category 'arithmetic') 
+ residue: aNumber
+ "Remainder defined in terms of ratio:.
+ Answer a Number between aNumber/2 and aNumber/2"
+
+ ^self  ((self ratio: aNumber) * aNumber)!
Item was added:
+  Method: Number>>roundedTieToEven (in category 'truncation and round off') 
+ roundedTieToEven
+ "Answer the integer nearest the receiver.
+ In case of perfect tie, round to nearest even.
+ Unlike rounded (round away from zero), this mode of rounding is unbiased."
+
+  sign truncated fractionPart 
+ sign := self sign.
+ truncated := self truncated.
+ fractionPart := self  self truncated.
+ ^(fractionPart abs > (1/2) or: [fractionPart = (sign/2) and: [truncated odd]])
+ ifTrue: [truncated + sign]
+ ifFalse: [truncated]!
Item was added:
+  Method: ScaledDecimal>>ratio: (in category 'arithmetic') 
+ ratio: aNumber
+ "Answer the integer quotient after dividing the receiver by aNumber
+ with rounding, tie to even."
+ (aNumber isKindOf: ScaledDecimal) ifTrue: [^super ratio: aNumber].
+ ^aNumber adaptToScaledDecimal: self andSend: #ratio:!
Item was added:
+  Method: ScaledDecimal>>residue: (in category 'arithmetic') 
+ residue: aNumber
+ (aNumber isKindOf: ScaledDecimal) ifTrue: [^super residue: aNumber].
+ ^aNumber adaptToScaledDecimal: self andSend: #residue:!
More information about the Squeakdev
mailing list
