[squeak-dev] The Trunk: Kernel-nice.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/Kernel-nice.1262.mcz
>
> ==================== Summary ====================
>
> Name: Kernel-nice.1262
> Author: nice
> Time: 29 August 2019, 12:28:31.665288 pm
> UUID: 3e167d35-e96e-7649-8324-28d9cb255a65
> Ancestors: Kernel-nice.1261
>
> Accelerate LargeInteger asFloat in 64bits images.
>
> =============== Diff against Kernel-nice.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 byte-digits 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 (Macos-metal pb
https://github.com/OpenSmalltalk/opensmalltalk-vm/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/squeak-dev/attachments/20190830/9db6b659/attachment.html>


More information about the Squeak-dev mailing list