[squeak-dev] The Inbox: Kernel-nice.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/Kernel-nice.903.mcz
==================== Summary ====================
Name: Kernel-nice.903
Author: nice
Time: 14 February 2015, 2:19:44.184 am
UUID: d4f06790-d47b-4cb0-b9ff-9e0ff7dea9fc
Ancestors: Kernel-nice.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 Kernel-nice.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 Squeak-dev
mailing list
|