Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-nice.691.mcz ==================== Summary ==================== Name: Kernel-nice.691 Author: nice Time: 22 May 2012, 10:14:29.897 pm UUID: f69b524f-83bb-4ef0-b084-e7a96dd5d33e Ancestors: Kernel-eem.690, Kernel-nice.690 Grace period is over, publish and merge the changes for printing Floating point with fixed precision. =============== Diff against Kernel-eem.690 =============== Item was added: + ----- Method: Float>>absPrintExactlyOn:base:decimalPlaces:showTrailingFractionalZeros: (in category 'printing') ----- + absPrintExactlyOn: aStream base: base decimalPlaces: placesDesired showTrailingFractionalZeros: showtrailingZeros + "Print my value on a stream in the given base with fixed number of digits after floating point. + When placesDesired are beyond Float precision, zeroes are appended. + When showtrailingZeros is false, the trailing zeroes after decimal point will be omitted. + If all fractional digits are zeros, the decimal point is omitted too. + Assumes that my value is strictly positive; negative numbers, zero, and NaNs have already been handled elsewhere. + Based upon the algorithm outlined in: + Robert G. Burger and R. Kent Dybvig + Printing Floating Point Numbers Quickly and Accurately + ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation + June 1996.." + + | significand exp baseExpEstimate r s mPlus mMinus scale roundingLowIncludesLimits roundingHighIncludesLimits d tc1 tc2 decPointCount slowbit shead delta | + self isInfinite ifTrue: [aStream nextPutAll: 'Infinity'. ^ self]. + significand := self significandAsInteger. + exp := (self exponent - 52) max: MinValLogBase2. + exp >= 0 + ifTrue: + [significand ~= 16r10000000000000 + ifTrue: + [r := significand bitShift: 1 + exp. + s := 2. + mPlus := mMinus := 1 bitShift: exp] + ifFalse: + [r := significand bitShift: 2 + exp. + s := 4. + mPlus := 2 * (mMinus := 1 bitShift: exp)]] + ifFalse: + [(exp = MinValLogBase2 or: [significand ~= 16r10000000000000]) + ifTrue: + [r := significand bitShift: 1. + s := 1 bitShift: 1 - exp. + mPlus := mMinus := 1] + ifFalse: + [r := significand bitShift: 2. + s := 1 bitShift: 2 - exp. + mPlus := 2. + mMinus := 1]]. + delta := s / 2 / (base raisedTo: placesDesired). + roundingLowIncludesLimits := (mMinus < delta and: [mMinus := delta. true]) or: [significand even]. + roundingHighIncludesLimits := (mPlus < delta and: [mPlus := delta. true]) or: [significand even]. + baseExpEstimate := (self exponent * base asFloat reciprocalLogBase2 - 1.0e-10) ceiling. + baseExpEstimate >= 0 + ifTrue: [s := s * (base raisedToInteger: baseExpEstimate)] + ifFalse: + [scale := base raisedToInteger: baseExpEstimate negated. + r := r * scale. + mPlus := mPlus * scale. + mMinus := mMinus * scale]. + ((r + mPlus >= s) and: [roundingHighIncludesLimits or: [r + mPlus > s]]) + ifTrue: [baseExpEstimate := baseExpEstimate + 1] + ifFalse: + [r := r * base. + mPlus := mPlus * base. + mMinus := mMinus * base]. + decPointCount := baseExpEstimate. + baseExpEstimate <= 0 + ifTrue: + [placesDesired + baseExpEstimate <= 0 + ifTrue: + [aStream nextPut: $0. + (showtrailingZeros and: [placesDesired > 0]) ifTrue: [aStream nextPut: $.; nextPutAll: (String new: placesDesired withAll: $0)]. + ^self]. + aStream nextPutAll: '0.'; nextPutAll: (String new: 0 - baseExpEstimate withAll: $0)]. + slowbit := 1 - s lowBit . + shead := s bitShift: slowbit. + [d := (r bitShift: slowbit) // shead. + r := r - (d * s). + (tc1 := (r <= mMinus) and: [roundingLowIncludesLimits or: [r < mMinus]]) | + (tc2 := (r + mPlus >= s) and: [roundingHighIncludesLimits or: [r + mPlus > s]])] whileFalse: + [aStream nextPut: (Character digitValue: d). + r := r * base. + mPlus := mPlus * base. + mMinus := mMinus * base. + (decPointCount := decPointCount - 1) = 0 ifTrue: [aStream nextPut: $.]]. + tc2 ifTrue: + [(tc1 not or: [r * 2 >= s]) ifTrue: [d := d + 1]]. + aStream nextPut: (Character digitValue: d). + decPointCount > 0 + ifTrue: + [decPointCount - 1 to: 1 by: -1 do: [:i | aStream nextPut: $0]. + (showtrailingZeros and: [placesDesired > 0]) ifTrue: [aStream nextPut: $.; nextPutAll: (String new: placesDesired withAll: $0)]] + ifFalse: + [(showtrailingZeros and: [placesDesired + decPointCount > 1]) ifTrue: [aStream nextPutAll: (String new: placesDesired + decPointCount - 1 withAll: $0)]].! Item was changed: + ----- Method: Float>>absPrintOn:base:digitCount: (in category 'printing') ----- - ----- Method: Float>>absPrintOn:base:digitCount: (in category 'private') ----- absPrintOn: aStream base: base digitCount: digitCount "Print me in the given base, using digitCount significant figures." | fuzz x exp q fBase scale logScale xi | self isInfinite ifTrue: [^ aStream nextPutAll: 'Inf']. fBase := base asFloat. "x is myself normalized to [1.0, fBase), exp is my exponent" exp := self < 1.0 ifTrue: [self reciprocalFloorLog: fBase] ifFalse: [self floorLog: fBase]. scale := 1.0. logScale := 0. [(x := fBase raisedTo: (exp + logScale)) = 0] whileTrue: [scale := scale * fBase. logScale := logScale + 1]. x := self * scale / x. fuzz := fBase raisedTo: 1 - digitCount. "round the last digit to be printed" x := 0.5 * fuzz + x. x >= fBase ifTrue: ["check if rounding has unnormalized x" x := x / fBase. exp := exp + 1]. (exp < 6 and: [exp > -4]) ifTrue: ["decimal notation" q := 0. exp < 0 ifTrue: [1 to: 1 - exp do: [:i | aStream nextPut: ('0.0000' at: i)]]] ifFalse: ["scientific notation" q := exp. exp := 0]. [x >= fuzz] whileTrue: ["use fuzz to track significance" xi := x asInteger. aStream nextPut: (Character digitValue: xi). x := x - xi asFloat * fBase. fuzz := fuzz * fBase. exp := exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. [exp >= -1] whileTrue: [aStream nextPut: $0. exp := exp - 1. exp = -1 ifTrue: [aStream nextPut: $.]]. q ~= 0 ifTrue: [aStream nextPut: $e. q printOn: aStream]! Item was added: + ----- Method: Float>>printOn:maxDecimalPlaces: (in category 'printing') ----- + printOn: aStream maxDecimalPlaces: placesDesired + "Refine super implementation in order to avoid any rounding error caused by rounded or roundTo:" + + self isFinite ifFalse: [^self printOn: aStream]. + self > 0.0 + ifTrue: [self absPrintExactlyOn: aStream base: 10 decimalPlaces: placesDesired showTrailingFractionalZeros: false] + ifFalse: + [self sign = -1 + ifTrue: [aStream nextPutAll: '-']. + self = 0.0 + ifTrue: [aStream nextPutAll: '0.0'] + ifFalse: [self absPrintExactlyOn: aStream base: 10 decimalPlaces: placesDesired showTrailingFractionalZeros: false]]! Item was added: + ----- Method: Float>>printOn:showingDecimalPlaces: (in category 'printing') ----- + printOn: aStream showingDecimalPlaces: placesDesired + "Refine super implementation in order to avoid any rounding error caused by rounded or roundTo:" + + self isFinite ifFalse: [^self printOn: aStream]. + self > 0.0 + ifTrue: [self absPrintExactlyOn: aStream base: 10 decimalPlaces: placesDesired showTrailingFractionalZeros: true] + ifFalse: + [self sign = -1 + ifTrue: [aStream nextPutAll: '-']. + self = 0.0 + ifTrue: [aStream nextPutAll: '0.0'] + ifFalse: [self absPrintExactlyOn: aStream base: 10 decimalPlaces: placesDesired showTrailingFractionalZeros: true]]! Item was removed: - ----- Method: Float>>printShowingDecimalPlaces: (in category 'printing') ----- - printShowingDecimalPlaces: placesDesired - "This implementation avoids any rounding error caused by rounded or roundTo:" - - self isFinite ifFalse: [^self printString]. - ^self asTrueFraction printShowingDecimalPlaces: placesDesired! |
On Tue, May 22, 2012 at 08:14:50PM +0000, [hidden email] wrote:
> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-nice.691.mcz > > ==================== Summary ==================== > > Name: Kernel-nice.691 > Author: nice > Time: 22 May 2012, 10:14:29.897 pm > UUID: f69b524f-83bb-4ef0-b084-e7a96dd5d33e > Ancestors: Kernel-eem.690, Kernel-nice.690 > > Grace period is over, publish and merge the changes for printing Floating point with fixed precision. > +1 Thanks! Dave |
Free forum by Nabble | Edit this page |