[Vm-dev] Potential issue of primitiveTimesTwoPower in Spur 64

Eliot Miranda eliot.miranda at gmail.com
Thu Feb 12 01:57:00 UTC 2015


Hmm, close, but I need to check explicitly for zero.  Here's the version
for the FloatMathPlugin (& with more conventional formatting :-) ):

primitiveTimesTwoPower
"Computes E raised to the receiver power."
| rcvr arg twiceMaxExponent result |
<export: true>
<var: #rcvr type: #double>
<var: #result type: #double>
arg := interpreterProxy stackIntegerValue: 0.
rcvr := interpreterProxy stackFloatValue: 1.
(interpreterProxy failed) ifTrue:
[^nil].
((self isFinite: rcvr) and: [rcvr ~= 0.0])
ifFalse:
[result := rcvr]
ifTrue:
[twiceMaxExponent := 2 * (1 << 11).
 arg < twiceMaxExponent negated
ifTrue:
[result := 0.0]
ifFalse:
[arg > twiceMaxExponent
ifTrue:
[result := 1.0e200 / 1.0e-200]
ifFalse:
[result := self cCode: '__ieee754_ldexp(rcvr, arg)'
inSmalltalk: [rcvr timesTwoPower: arg]]]].
(self isnan: result) ifTrue:
[^interpreterProxy primitiveFail].
interpreterProxy
pop: interpreterProxy methodArgumentCount + 1;
pushFloat: result

On Wed, Feb 11, 2015 at 5:43 PM, Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> and of course I meant
>
> primitiveTimesTwoPower
> | rcvr result arg twiceMaxExponent |
> <var: #rcvr type: #double>
> <var: #result type: #double>
> arg := self stackTop.
> (objectMemory isIntegerObject: arg) ifFalse:
> [^self primitiveFailFor: PrimErrBadArgument].
> rcvr := objectMemory floatValueOf: (self stackValue: 1).
> (self isFinite: rcvr) ifFalse:
> [result := rcvr] ifTrue:
> [arg := objectMemory integerValueOf: arg.
>  twiceMaxExponent := 2 * (1 << self floatExponentBits).
>  arg < twiceMaxExponent negated ifTrue:
> [result := 0.0] ifFalse:
> [arg > twiceMaxExponent ifTrue:
> [result := 1.0e200 / 1.0e-200] ifFalse:
> [result := self cCode: [self ld: rcvr exp: arg]
> inSmalltalk: [rcvr timesTwoPower: arg]]]].
> self pop: 2 thenPushFloat: result
>
> On Wed, Feb 11, 2015 at 5:41 PM, Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
>
>> Hi Nicolas,
>>
>> On Wed, Feb 11, 2015 at 2:57 PM, Nicolas Cellier <
>> nicolas.cellier.aka.nice at gmail.com> wrote:
>>
>>>
>>> Some C functions in libm only take an int, not a long.
>>> In 32 bits int=long, so no problem.
>>> In 64 bits generally int=32 bits, long=64 bits, so casting a long to int
>>> might lead to catastrophic loss and unexpected behavior.
>>>
>>> This is the case for example in primitiveTimesTwoPower
>>>     | rcvr arg |
>>>     <var: #rcvr type: #double>
>>>     arg := self popInteger.
>>>     rcvr := self popFloat.
>>>     self successful
>>>         ifTrue: [ self pushFloat: (self cCode: 'ldexp(rcvr, arg)'
>>> inSmalltalk: [rcvr timesTwoPower: arg]) ]
>>>         ifFalse: [ self unPop: 2 ]
>>>
>>> arg will be a long in Spur64, won't it?
>>> but ldexp only takes an int
>>>     double ldexp(double x, int exp);.
>>>
>>> So guess what if we call (1.0 timesTwoPower: 16r10000000001)...
>>> Normally there should be a C compiler warning, and we should care of it.
>>>
>>> To solve this, maybe we need a
>>>
>>>     <var: #arg type: #int>
>>>     arg := self signed32BitValueOf: stackTop.
>>>
>>
>>
>> I think we can check intelligently.  We know that for a finite non-zero
>> value,  ldexp(value, n) is infinite if n > (2 * max exponent) and zero if n
>> < (2 * max exponent), that for a NaN value, ldexp(value, n) is NaN and for
>> an infinite value ldexp(value,n) is infinite, and for a 0 value, it is
>> zero.  So I propose
>>
>> primitiveTimesTwoPower
>> | rcvr result arg twiceMaxExponent |
>> <var: #rcvr type: #double>
>> <var: #result type: #double>
>> arg := self stackTop.
>> (objectMemory isIntegerObject: arg) ifFalse:
>> [^self primitiveFailFor: PrimErrBadArgument].
>> rcvr := objectMemory floatValueOf: (self stackValue: 1).
>> (self isFinite: rcvr) ifFalse:
>> [result := rcvr] ifTrue:
>> [arg := objectMemory integerValueOf: arg.
>>  twiceMaxExponent := 2 * (1 << self floatExponentBits).
>>  arg < twiceMaxExponent ifTrue:
>> [result := 0.0] ifFalse:
>> [arg > twiceMaxExponent ifTrue:
>> [result := 1.0e200 / 1.0e-200] ifFalse:
>> [result := self cCode: [self ld: rcvr exp: arg]
>> inSmalltalk: [rcvr timesTwoPower: arg]]]].
>> self pop: 2 thenPushFloat: result
>> --
>> best,
>> Eliot
>>
>
>
>
> --
> best,
> Eliot
>



-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20150211/b232c959/attachment.htm


More information about the Vm-dev mailing list