'From Squeak3.9alpha of 4 July 2005 [latest update: #7028] on 6 May 2006 at 9:58:34 pm'!
!Integer methodsFor: 'converting' stamp: 'nice 5/6/2006 21:54'!
asFloat
"Answer a Float that represents the value of the receiver.
This algorithm does honour IEEE 754 round to nearest even mode.
Numbers are first rounded on nearest integer on 53 bits.
In case of exact half difference between two consecutive integers (2r0.1),
there are two possible choices (two integers are as near, 0 and 1)
In this case, the nearest even integer is chosen.
examples (with less than 53bits for clarity)
2r0.00001 is rounded to 2r0
2r1.00001 is rounded to 2.1
2r0.1 is rounded to 2r0 (nearest event)
2r1.1 is rounded to 2.10 (neraest even)
2r0.10001 is rounded to 2r1
2r1.10001 is rounded to 2.10"
| delta abs exponent mask trailingBits carry |
self isZero
ifTrue: [^ 0.0].
abs := self abs.
"Assume Float is a double precision IEEE 754 number with 53bits mantissa.
We should better use some Float class message for that..."
delta := abs highBit - 53.
delta > 0
ifTrue: [mask := (1 bitShift: delta) - 1.
trailingBits := abs bitAnd: mask.
"inexact := trailingBits isZero not."
carry := trailingBits bitShift: 1 - delta.
abs := abs bitShift: delta negated.
exponent := delta.
(carry isZero
or: [(trailingBits bitAnd: (mask bitShift: -1)) isZero
and: [abs even]])
ifFalse: [abs := abs + 1].
^ self positive
ifTrue: [abs asFloatSimply timesTwoPower: exponent]
ifFalse: [abs negated asFloatSimply timesTwoPower: exponent]].
^ self asFloatSimply! !
!Integer methodsFor: 'converting' stamp: 'nice 5/6/2006 21:32'!
asFloatSimply
"Answer a Float that represents the value of the receiver.
Optimized to process only the significant digits of a LargeInteger.
NOTA: this version does not honour IEEE 754 arithmetic
(round to nearest event mode).
It should be used on 53 or less binary digits numbers.
SqR: 11/30/1998 21:11"
| sum firstByte shift |
shift _ 0.
sum _ 0.0.
firstByte _ self size - 7 max: 1.
firstByte to: self size do:
[:byteIndex |
sum _ ((self digitAt: byteIndex) asFloat timesTwoPower: shift) + sum.
shift _ shift + 8].
^sum * self sign asFloat timesTwoPower: firstByte - 1 * 8! !