[squeak-dev] The Inbox: Kernel-nice.690.mcz

Bert Freudenberg bert at freudenbergs.de
Sun May 20 10:46:58 UTC 2012


Looks good to me - but I doubt you will get any testing unless you actually commit to trunk :)

- Bert -

On 20.05.2012, at 08:05, commits at source.squeak.org wrote:

> A new version of Kernel was added to project The Inbox:
> http://source.squeak.org/inbox/Kernel-nice.690.mcz
> 
> ==================== Summary ====================
> 
> Name: Kernel-nice.690
> Author: nice
> Time: 20 May 2012, 10:05:07.444 am
> UUID: 2c2aba8b-d8bd-4ec3-8b88-a873de9c68c4
> Ancestors: Kernel-nice.689
> 
> 1) Correct the very new #printOn:maxDecimalPlaces: which often rounds inexactly for large Float or large number of digits.
> Rationale: the printed representation shall be rounded exactly
> 
> 2) Don't print arbitrary digits beyond Float precision, just print zeros
> (0.1 printShowingDecimalPlaces: 20) now prints '0.10000000000000000000' instead of '0.10000000000000000555',
> Rationale: those digits, while reflecting internal representation exactly, are totally insignificant and could be replaced with any other digits, while still representing the same Float. 
> 
> 3) Print the negative sign, even if the number vanishes to zero at prescribed decimal places
> (-0.001 printShowingDecimalPlaces: 2) now prints '-0.00' instead of '0.00',
> Rationale: this behaves like classical lib printf, and is in the spirit of Float negativeZero printString: when the precision vanishes, the Float keeps its sign.
> 
> Note: I find the scheme feature which prints # for insignificant digits is very nice, but we should find a re-interpretable format...
> 
> Implementation details:
> 
> Of course, algorithms are taken from:
> 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.
> 
> Note that there is lot of duplicated code between free format and fixed format Float printing.
> And we should also fix the case of fixed number of digits #absPrintOn:base:digitCount: ...
> 
> =============== Diff against Kernel-nice.689 ===============
> 
> 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!
> 
> 



More information about the Squeak-dev mailing list