<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2015-02-12 3:02 GMT+01:00 Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br><div dir="ltr">Again not close enough.  If value &lt; 0, then result is &lt; 0, so<div><br></div><div><div>primitiveTimesTwoPower</div><div><span style="white-space:pre-wrap">        </span>&lt;option: #Spur64BitMemoryManager&gt;</div><div><span style="white-space:pre-wrap">        </span>| rcvr result arg twiceMaxExponent |</div><div><span style="white-space:pre-wrap">        </span>&lt;var: #rcvr type: #double&gt;</div><div><span style="white-space:pre-wrap">        </span>&lt;var: #result type: #double&gt;</div><div><span style="white-space:pre-wrap">        </span>arg := self stackTop.</div><div><span style="white-space:pre-wrap">        </span>(objectMemory isIntegerObject: arg) ifFalse:</div><div><span style="white-space:pre-wrap">                </span>[^self primitiveFailFor: PrimErrBadArgument].</div><div><span style="white-space:pre-wrap">        </span>rcvr := objectMemory floatValueOf: (self stackValue: 1).</div><div><span style="white-space:pre-wrap">        </span>((self isFinite: rcvr) and: [rcvr ~= 0])</div><div><span style="white-space:pre-wrap">                </span>ifFalse:</div><div><span style="white-space:pre-wrap">                        </span>[result := rcvr]</div><div><span style="white-space:pre-wrap">                </span>ifTrue:</div><div><span style="white-space:pre-wrap">                        </span>[arg := objectMemory integerValueOf: arg.</div><div><span style="white-space:pre-wrap">                        </span> twiceMaxExponent := 2 * (1 &lt;&lt; self floatExponentBits).</div><div><span style="white-space:pre-wrap">                        </span> arg &lt; twiceMaxExponent negated</div><div><span style="white-space:pre-wrap">                                </span>ifTrue:</div><div><span style="white-space:pre-wrap">                                        </span>[result := rcvr &lt; 0.0 ifTrue: [-0.0] ifFalse: [0.0]]</div><div><span style="white-space:pre-wrap">                                </span>ifFalse:</div><div><span style="white-space:pre-wrap">                                        </span>[arg &gt; twiceMaxExponent</div><div><span style="white-space:pre-wrap">                                                </span>ifTrue:</div><div><span style="white-space:pre-wrap">                                                        </span>[result := rcvr &lt; 0.0 ifTrue: [-1.0e200 / 10.e-200] ifFalse: 1.0e200 / 1.0e-200]]</div><div><span style="white-space:pre-wrap">                                                </span>ifFalse:</div><div><span style="white-space:pre-wrap">                                                        </span>[result := self cCode: [self ld: rcvr exp: arg]</div><div><span style="white-space:pre-wrap">                                                                                        </span>inSmalltalk: [rcvr timesTwoPower: arg]]]].</div><div><span style="white-space:pre-wrap">        </span>self pop: 2 thenPushFloat: result</div></div><div><br></div><div>Right?</div></div></blockquote><div><br></div>I was focused on image side fallback code and came up to more or less the same <br></div><div class="gmail_quote">So it sounds very good to me :)<br><br></div><div class="gmail_quote"><div>We still have a compiler warning for long -&gt; int,.<br>For sure, we can ignore it this time...<br></div><div>But this kind of false warning is pesky.<br>The risk is to drown a true positive into a flow of false ones...<br></div><div><br>Using an argument &gt; 2^31 is more theoretical than practicle. It should be very rare.<br>So once we have image side for handling this rare case, I wonder if it is really necessary to complexify the primitive...<br>And it&#39;s good anyway to have a fallback code, it makes the primitives optional and lower the barrier for guys doing experiments like Bert.<br></div><div>So I would say let the primitive fail, and eliminate the warning.<br><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 11, 2015 at 5:57 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hmm, close, but I need to check explicitly for zero.  Here&#39;s the version for the FloatMathPlugin (&amp; with more conventional formatting :-) ):<div><br></div><div><div>primitiveTimesTwoPower</div><div><span style="white-space:pre-wrap">        </span>&quot;Computes E raised to the receiver power.&quot;</div><div><span style="white-space:pre-wrap">        </span>| rcvr arg twiceMaxExponent result |</div><div><span style="white-space:pre-wrap">        </span>&lt;export: true&gt;</div><span><div><span style="white-space:pre-wrap">        </span>&lt;var: #rcvr type: #double&gt;</div><div><span style="white-space:pre-wrap">        </span>&lt;var: #result type: #double&gt;</div></span><div><span style="white-space:pre-wrap">        </span>arg := interpreterProxy stackIntegerValue: 0.</div><div><span style="white-space:pre-wrap">        </span>rcvr := interpreterProxy stackFloatValue: 1.</div><div><span style="white-space:pre-wrap">        </span>(interpreterProxy failed) ifTrue:</div><div><span style="white-space:pre-wrap">                </span>[^nil].</div><div><span style="white-space:pre-wrap">        </span>((self isFinite: rcvr) and: [rcvr ~= 0.0])</div><span><div><span style="white-space:pre-wrap">                </span>ifFalse:</div><div><span style="white-space:pre-wrap">                        </span>[result := rcvr]</div><div><span style="white-space:pre-wrap">                </span>ifTrue:</div></span><div><span style="white-space:pre-wrap">                        </span>[twiceMaxExponent := 2 * (1 &lt;&lt; 11).</div><span><div><span style="white-space:pre-wrap">                        </span> arg &lt; twiceMaxExponent negated</div><div><span style="white-space:pre-wrap">                                </span>ifTrue:</div><div><span style="white-space:pre-wrap">                                        </span>[result := 0.0]</div><div><span style="white-space:pre-wrap">                                </span>ifFalse:</div><div><span style="white-space:pre-wrap">                                        </span>[arg &gt; twiceMaxExponent</div><div><span style="white-space:pre-wrap">                                                </span>ifTrue:</div><div><span style="white-space:pre-wrap">                                                        </span>[result := 1.0e200 / 1.0e-200]</div><div><span style="white-space:pre-wrap">                                                </span>ifFalse:</div></span><div><span style="white-space:pre-wrap">                                                        </span>[result := self cCode: &#39;__ieee754_ldexp(rcvr, arg)&#39;</div><div><span style="white-space:pre-wrap">                                                                                        </span>inSmalltalk: [rcvr timesTwoPower: arg]]]].</div><div><span style="white-space:pre-wrap">        </span>(self isnan: result) ifTrue:</div><div><span style="white-space:pre-wrap">                </span>[^interpreterProxy primitiveFail].</div><div><span style="white-space:pre-wrap">        </span>interpreterProxy</div><div><span style="white-space:pre-wrap">                </span>pop: interpreterProxy methodArgumentCount + 1;</div><div><span style="white-space:pre-wrap">                </span>pushFloat: result</div></div></div><div class="gmail_extra"><div><div><br><div class="gmail_quote">On Wed, Feb 11, 2015 at 5:43 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">and of course I meant<div><br></div><div><span><div style="color:rgb(0,0,0);font-size:13px">primitiveTimesTwoPower</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>| rcvr result arg twiceMaxExponent |</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>&lt;var: #rcvr type: #double&gt;</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>&lt;var: #result type: #double&gt;</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>arg := self stackTop.</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>(objectMemory isIntegerObject: arg) ifFalse:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">                </span>[^self primitiveFailFor: PrimErrBadArgument].</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>rcvr := objectMemory floatValueOf: (self stackValue: 1).</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>(self isFinite: rcvr) ifFalse:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">                </span>[result := rcvr] ifTrue:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>[arg := objectMemory integerValueOf: arg.</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span> twiceMaxExponent := 2 * (1 &lt;&lt; self floatExponentBits).</div></span><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span> arg &lt; twiceMaxExponent negated ifTrue:</div><span><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">                </span>[result := 0.0] ifFalse:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>[arg &gt; twiceMaxExponent ifTrue:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">                </span>[result := 1.0e200 / 1.0e-200] ifFalse:</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>[result := self cCode: [self ld: rcvr exp: arg]</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">                                        </span>inSmalltalk: [rcvr timesTwoPower: arg]]]].</div><div style="color:rgb(0,0,0);font-size:13px"><span style="white-space:pre-wrap">        </span>self pop: 2 thenPushFloat: result</div></span></div></div><div class="gmail_extra"><div><div><br><div class="gmail_quote">On Wed, Feb 11, 2015 at 5:41 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><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:1px solid rgb(204,204,204);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 style="white-space:pre-wrap">        </span>| rcvr result arg twiceMaxExponent |</div><div><span style="white-space:pre-wrap">        </span>&lt;var: #rcvr type: #double&gt;</div><div><span style="white-space:pre-wrap">        </span>&lt;var: #result type: #double&gt;</div><div><span style="white-space:pre-wrap">        </span>arg := self stackTop.</div><div><span style="white-space:pre-wrap">        </span>(objectMemory isIntegerObject: arg) ifFalse:</div><div><span style="white-space:pre-wrap">                </span>[^self primitiveFailFor: PrimErrBadArgument].</div><div><span style="white-space:pre-wrap">        </span>rcvr := objectMemory floatValueOf: (self stackValue: 1).</div><div><span style="white-space:pre-wrap">        </span>(self isFinite: rcvr) ifFalse:</div><div><span style="white-space:pre-wrap">                </span>[result := rcvr] ifTrue:</div><div><span style="white-space:pre-wrap">        </span>[arg := objectMemory integerValueOf: arg.</div><div><span style="white-space:pre-wrap">        </span> twiceMaxExponent := 2 * (1 &lt;&lt; self floatExponentBits).</div><div><span style="white-space:pre-wrap">        </span> arg &lt; twiceMaxExponent ifTrue:</div><div><span style="white-space:pre-wrap">                </span>[result := 0.0] ifFalse:</div><div><span style="white-space:pre-wrap">        </span>[arg &gt; twiceMaxExponent ifTrue:</div><div><span style="white-space:pre-wrap">                </span>[result := 1.0e200 / 1.0e-200] ifFalse:</div><div><span style="white-space:pre-wrap">        </span>[result := self cCode: [self ld: rcvr exp: arg]</div><div><span style="white-space:pre-wrap">                                        </span>inSmalltalk: [rcvr timesTwoPower: arg]]]].</div><div><span style="white-space:pre-wrap">        </span>self pop: 2 thenPushFloat: result</div></div><span><font color="#888888">-- <br><div>best,<div>Eliot</div></div>
</font></span></div></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br><div>best,<div>Eliot</div></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br><div>best,<div>Eliot</div></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>best,<div>Eliot</div></div>
</div>
<br></blockquote></div><br></div></div>