[squeakdev] The Trunk: Kernelnice.1262.mcz
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Fri Aug 30 19:34:44 UTC 2019
Le jeu. 29 août 2019 à 12:28, <commits at source.squeak.org> a écrit :
> Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
> http://source.squeak.org/trunk/Kernelnice.1262.mcz
>
> ==================== Summary ====================
>
> Name: Kernelnice.1262
> Author: nice
> Time: 29 August 2019, 12:28:31.665288 pm
> UUID: 3e167d35e96e7649832428d9cb255a65
> Ancestors: Kernelnice.1261
>
> Accelerate LargeInteger asFloat in 64bits images.
>
> =============== Diff against Kernelnice.1261 ===============
>
> Item was added:
> +  Method: Integer>>digitsAsFloat (in category 'private') 
> + digitsAsFloat
> + "private  naive conversion method.
> + This method should be used if and only if
> + Float precision + 8 >= self highBit.
> + This way, all floating point operations will be exact, but
> eventually the
> + last one, giving a guaranty that result will be the nearest Float."
> +  result n 
> + result := (self digitAt: (n := self digitLength)) asFloat.
> + [(n := n  1) > 0]
> + whileTrue: [result := 256.0 * result + (self digitAt: n)
> asFloat].
> + ^ result!
>
> Some additional notes:
I've also tried a simple split of the 53 (Float precision) + 7 (excess
bits) significand into two 30 bits SmallInteger:
digitsAsFloat2
^(self bitShift: 30) asFloat * 1073741824.0
+ (self bitAnd: 16r3FFFFFFF) asFloat
Unfortunately, this is slower than looping on the bytedigits like proposed
above:
self assert: 923456789012345678 highBit = 60.
[923456789012345678 digitsAsFloat] bench. '7,290,000 per second. 137
nanoseconds per run.'
[923456789012345678 digitsAsFloat2] bench. '3,430,000 per second. 291
nanoseconds per run.'
I did not use latest VM when trying this (Macosmetal pb
https://github.com/OpenSmalltalk/opensmalltalkvm/issues/397)
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.
> Note 2: the floating point hardware is presumed configured in
> default rounding mode."
>
> +  mantissa shift excess 
>   mantissa shift excess result n 
>
> "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."
> 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."
> ((mantissa digitAt: 1) = 2r01000000 and: [self
> anyBitOfMagnitudeFrom: 1 to: shift])
> ifTrue: [mantissa := mantissa + 1]]
> ifFalse:
> [mantissa := self.
> shift := 0].
>
> + "We can use naive digit by digit conversion because there will be
> a single inexact round off at last iteration.
> + But the nice thing is that Float precision + 7 excess bits = 60
> which fit in a SmallInteger in Spur64.
> + So the best to do is to delegate this final operation"
> + ^mantissa digitsAsFloat timesTwoPower: shift.!
>  "There will be a single inexact round off at last iteration"
>  result := (mantissa digitAt: (n := mantissa digitLength)) asFloat.
>  [(n := n  1) > 0] whileTrue: [
>  result := 256.0 * result + (mantissa digitAt: n) asFloat].
>  ^result timesTwoPower: shift.!
>
> Item was added:
> +  Method: SmallInteger>>digitsAsFloat (in category 'private') 
> + digitsAsFloat
> + "private  let the primitive take care to answer the nearest float"
> + <primitive: 40>
> + ^super digitsAsFloat!
>
>
>
 next part 
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeakdev/attachments/20190830/9db6b659/attachment.html>
More information about the Squeakdev
mailing list
