[squeakdev] The Inbox: Kernelnice.631.mcz
commits at source.squeak.org
commits at source.squeak.org
Mon Sep 26 21:16:51 UTC 2011
A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernelnice.631.mcz
==================== Summary ====================
Name: Kernelnice.631
Author: nice
Time: 26 September 2011, 11:16:10.34 pm
UUID: 54730a61b8b54e3f9066d90e018f15a6
Ancestors: Kernelnice.630
Sorry, previous asFloat was not the fastest in COG.
COG seems to perform some primitives like bitShift: slowly, while it is much faster with some others like digitAt:
So let's use digitAt:.
=============== Diff against Kernelnice.630 ===============
Item was changed:
 Method: LargePositiveInteger>>asFloat (in category 'converting') 
asFloat
"Answer a Float that best approximates the value of the receiver.
This algorithm is optimized to process only the significant digits of a LargeInteger.
And it does honour IEEE 754 round to nearest even mode in case of excess precision (see details below)."
"How numbers are rounded in IEEE 754 default rounding mode:
A shift is applied so that the highest 53 bits are placed before the floating point to form a mantissa.
The trailing bits form the fraction part placed after the floating point.
This fractional number must be rounded to the nearest integer.
If fraction part is 2r0.1, exactly between two consecutive integers, there is a tie.
The nearest even integer is chosen in this case.
Examples (First 52bits of mantissa are omitted for brevity):
2r0.00001 is rounded downward to 2r0
2r1.00001 is rounded downward to 2r1
2r0.1 is a tie and rounded to 2r0 (nearest even)
2r1.1 is a tie and rounded to 2r10 (nearest even)
2r0.10001 is rounded upward to 2r1
2r1.10001 is rounded upward to 2r10
Thus, if the next bit after floating point is 0, the mantissa is left unchanged.
If next bit after floating point is 1, an odd mantissa is always rounded upper.
An even mantissa is rounded upper only if the fraction part is not a tie."
"Algorihm details:
+ The floating point hardware can perform the rounding correctly with several excess bits as long as there is a single inexact operation.
+ This can be obtained by splitting the mantissa plus excess bits in two part with less bits than Float precision.
+ Note 1: the inexact flag in floating point hardware must not be trusted because in some cases the operations would be exact but would not take into account some bits that were truncated before the Floating point operations.
 Floating point hardware will correctly handle the rounding by itself if there is a single inexact operation.
 Except in the last case when extra bits are present after an even mantissa, we must round upper by ourselves.
 Note 1: the inexact flag in floating point hardware must not be trusted because it won't take into account the bits we truncated by ourselves.
Note 2: the floating point hardware is presumed configured in default rounding mode."
+  mantissa shift excess high low 
  mantissa shift excess 
"Check how many bits excess the maximum precision of a Float mantissa."
excess := self highBitOfMagnitude  Float precision.
excess > 7
ifTrue:
+ ["Remove the excess bits but seven."
 ["Remove the excess bits but seven.
 Float precision + 7 = 60 bits = 2 * length of positive small integer"
mantissa := self bitShiftMagnitude: 7  excess.
shift := excess  7.
+ "An even mantissa with a single excess bit immediately following would be truncated.
+ But this would not be correct if above shift has truncated some extra bits.
+ Check this case, and round excess bits upper manually."
 "Handle the case of extra bits truncated after an even mantissa."
((mantissa digitAt: 1) = 2r01000000 and: [self anyBitOfMagnitudeFrom: 1 to: shift])
ifTrue: [mantissa := mantissa + 1]]
ifFalse:
[mantissa := self.
shift := 0].
+ "Combine two Floats with a single inexact round off"
+ low := (mantissa digitAt: 1) asFloat timesTwoPower: shift.
+ 2 to: 4 do: [:i .
+ low := low + ((mantissa digitAt: i) asFloat timesTwoPower: (shift := shift + 8))].
+ high := (mantissa digitAt: 5) asFloat timesTwoPower: (shift := shift + 8).
+ 6 to: mantissa digitLength do: [:i 
+ high := high + ((mantissa digitAt: i) asFloat timesTwoPower: (shift := shift + 8)).].
+ ^high + low!
 "Combine two small integers (SmallInteger maxVale highBit = 30 bits) asFloat with a single inexact round off"
 ^(((mantissa bitShiftMagnitude: 30) asFloat timesTwoPower: 30)
 + (mantissa bitAnd: 16r3FFFFFFF "SmallInteger maxVal"))
 timesTwoPower: shift!
More information about the Squeakdev
mailing list
