 ## [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 ===============

+ ----- 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])!

+ ----- 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!

+ ----- Method: Float>>ratio: (in category 'arithmetic') -----
+ ratio: aNumber
+ 	aNumber isFloat ifTrue: [^self fratio: aNumber].
+ 	^aNumber adaptToFloat: self andSend: #ratio:!

+ ----- Method: Float>>residue: (in category 'arithmetic') -----
+ residue: aNumber
+ 	aNumber isFloat ifTrue: [^self fresidue: aNumber].
+ 	^aNumber adaptToFloat: self andSend: #residue:!

+ ----- Method: Fraction>>ratio: (in category 'arithmetic') -----
+ ratio: aNumber
+ 	aNumber isFraction ifTrue: [^super ratio: aNumber].
+ 	^aNumber adaptToFraction: self andSend: #ratio:!

+ ----- Method: Fraction>>residue: (in category 'arithmetic') -----
+ residue: aNumber
+ 	aNumber isFraction ifTrue: [^super residue: aNumber].
+ 	^aNumber adaptToFraction: self andSend: #residue:!

+ ----- 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]!

+ ----- Method: Integer>>ratio: (in category 'arithmetic') -----
+ ratio: aNumber
+ 	aNumber isFraction ifTrue: [^super ratio: aNumber].
+ 	^aNumber adaptToInteger: self andSend: #ratio:!

+ ----- Method: Integer>>residue: (in category 'arithmetic') -----
+ residue: aNumber
+ 	aNumber isFraction ifTrue: [^super residue: aNumber].
+ 	^aNumber adaptToInteger: self andSend: #residue:!

+ ----- Method: Integer>>roundedTieToEven (in category 'truncation and round off') -----
+ roundedTieToEven
+ 	^self!

+ ----- 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!

+ ----- 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)!

+ ----- Method: Number>>roundedTieToEven (in category 'truncation and round off') -----
+ roundedTieToEven
+ 	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]!

+ ----- Method: ScaledDecimal>>ratio: (in category 'arithmetic') -----
+ ratio: aNumber
+ 	with rounding, tie to even."
+ 	(aNumber isKindOf: ScaledDecimal) ifTrue: [^super ratio: aNumber].
+ 	^aNumber adaptToScaledDecimal: self andSend: #ratio:!