<div dir="ltr">Hi Nicolas,<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 11, 2015 at 2:57 PM, Nicolas Cellier <span dir="ltr">&lt;<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <br><div dir="ltr"><div><div>Some C functions in libm only take an int, not a long.<br>In 32 bits int=long, so no problem.<br>In 64 bits generally int=32 bits, long=64 bits, so casting a long to int might lead to catastrophic loss and unexpected behavior.<br><br>This is the case for example in primitiveTimesTwoPower<br>    | rcvr arg |<br>    &lt;var: #rcvr type: #double&gt;<br>    arg := self popInteger.<br>    rcvr := self popFloat.<br>    self successful<br>        ifTrue: [ self pushFloat: (self cCode: &#39;ldexp(rcvr, arg)&#39; inSmalltalk: [rcvr timesTwoPower: arg]) ]<br>        ifFalse: [ self unPop: 2 ]<br><br>arg will be a long in Spur64, won&#39;t it?<br>but ldexp only takes an int<br>    double ldexp(double x, int exp);.<br><br>So guess what if we call (1.0 timesTwoPower: 16r10000000001)... <br>Normally there should be a C compiler warning, and we should care of it.<br><br></div>To solve this, maybe we need a<br>    <br>    &lt;var: #arg type: #int&gt;<br></div>    arg := self signed32BitValueOf: stackTop.</div></blockquote><div><br></div><div><br></div><div>I think we can check intelligently.  We know that for a finite non-zero value,  ldexp(value, n) is infinite if n &gt; (2 * max exponent) and zero if n &lt; (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</div></div><br clear="all"><div><div>primitiveTimesTwoPower</div><div><span class="" style="white-space:pre">        </span>| rcvr result arg twiceMaxExponent |</div><div><span class="" style="white-space:pre">        </span>&lt;var: #rcvr type: #double&gt;</div><div><span class="" style="white-space:pre">        </span>&lt;var: #result type: #double&gt;</div><div><span class="" style="white-space:pre">        </span>arg := self stackTop.</div><div><span class="" style="white-space:pre">        </span>(objectMemory isIntegerObject: arg) ifFalse:</div><div><span class="" style="white-space:pre">                </span>[^self primitiveFailFor: PrimErrBadArgument].</div><div><span class="" style="white-space:pre">        </span>rcvr := objectMemory floatValueOf: (self stackValue: 1).</div><div><span class="" style="white-space:pre">        </span>(self isFinite: rcvr) ifFalse:</div><div><span class="" style="white-space:pre">                </span>[result := rcvr] ifTrue:</div><div><span class="" style="white-space:pre">        </span>[arg := objectMemory integerValueOf: arg.</div><div><span class="" style="white-space:pre">        </span> twiceMaxExponent := 2 * (1 &lt;&lt; self floatExponentBits).</div><div><span class="" style="white-space:pre">        </span> arg &lt; twiceMaxExponent ifTrue:</div><div><span class="" style="white-space:pre">                </span>[result := 0.0] ifFalse:</div><div><span class="" style="white-space:pre">        </span>[arg &gt; twiceMaxExponent ifTrue:</div><div><span class="" style="white-space:pre">                </span>[result := 1.0e200 / 1.0e-200] ifFalse:</div><div><span class="" style="white-space:pre">        </span>[result := self cCode: [self ld: rcvr exp: arg]</div><div><span class="" style="white-space:pre">                                        </span>inSmalltalk: [rcvr timesTwoPower: arg]]]].</div><div><span class="" style="white-space:pre">        </span>self pop: 2 thenPushFloat: result</div></div>-- <br><div class="gmail_signature">best,<div>Eliot</div></div>
</div></div>