<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"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>></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> <var: #rcvr type: #double><br> arg := self popInteger.<br> rcvr := self popFloat.<br> self successful<br> ifTrue: [ self pushFloat: (self cCode: 'ldexp(rcvr, arg)' inSmalltalk: [rcvr timesTwoPower: arg]) ]<br> ifFalse: [ self unPop: 2 ]<br><br>arg will be a long in Spur64, won'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> <var: #arg type: #int><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 > (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</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><var: #rcvr type: #double></div><div><span class="" style="white-space:pre">        </span><var: #result type: #double></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 << self floatExponentBits).</div><div><span class="" style="white-space:pre">        </span> arg < 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 > 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>