<div dir="ltr">Hi Nicolas,<div><br></div><div><br><div class="gmail_extra"><div class="gmail_quote">On Mon, Jun 30, 2014 at 1:05 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">2014-06-30 21:24 GMT+02:00 Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></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">Hi All,<div><br></div><div> I recently eliminated the optimization in Slang that replaces a division by a power of two with a shift, because the code cast the argument to signed, and hence broke unsigned division. That's what used to be controlled by the UseRightShiftForDivide class var of CCodeGenerator.</div>
<div><br></div><div>Yesterday I found out that that optimization is the only thing that's keeping the LargeIntegers plugin afloat. To whit:</div><div><br></div><div>LargeIntegersPlugin>>cDigitSub: pByteSmall<div>
<span style="white-space:pre-wrap">                </span>len: smallLen</div><div><span style="white-space:pre-wrap">                </span>with: pByteLarge</div><div><span style="white-space:pre-wrap">                </span>len: largeLen</div><div><span style="white-space:pre-wrap">                </span>into: pByteRes</div>
<div><span style="white-space:pre-wrap">        </span>| z limit |</div><div><span style="white-space:pre-wrap">        </span><var: #pByteSmall type: 'unsigned char * '></div><div><span style="white-space:pre-wrap">        </span><var: #pByteLarge type: 'unsigned char * '></div>
<div><span style="white-space:pre-wrap">        </span><var: #pByteRes type: 'unsigned char * '></div><div><br></div><div><span style="white-space:pre-wrap">        </span>z := 0.</div><div><span style="white-space:pre-wrap">        </span>"Loop invariant is -1<=z<=1"</div>
<div><span style="white-space:pre-wrap">        </span>limit := smallLen - 1.</div><div><span style="white-space:pre-wrap">        </span>0 to: limit do: </div><div><span style="white-space:pre-wrap">                </span>[:i | </div><div>
<span style="white-space:pre-wrap">                </span>z := z + (pByteLarge at: i) - (pByteSmall at: i).</div><div><span style="white-space:pre-wrap">                </span>pByteRes at: i put: z - (z // 256 * 256).</div><div><span style="white-space:pre-wrap">                </span>"sign-tolerant form of (z bitAnd: 255)"</div>
<div><span style="white-space:pre-wrap">                </span>z := z // 256].</div><div><span style="white-space:pre-wrap">        </span>limit := largeLen - 1.</div><div><span style="white-space:pre-wrap">        </span>smallLen to: limit do: </div>
<div><span style="white-space:pre-wrap">                </span>[:i | </div><div><span style="white-space:pre-wrap">                </span>z := z + (pByteLarge at: i) .</div><div><span style="white-space:pre-wrap">                </span>pByteRes at: i put: z - (z // 256 * 256).</div>
<div><span style="white-space:pre-wrap">                </span>"sign-tolerant form of (z bitAnd: 255)"</div><div><span style="white-space:pre-wrap">                </span>z := z // 256].</div><div><br></div><div>The "z := z // 256"'s at the end of the loops were being generated as</div>
<div><div> z = ((sqInt) z) >> 8;</div><div> which is essential for the signed arithmetic implicit in "z := z + (pByteLarge at: i) - (pByteSmall at: i)" to work.</div></div><div><br></div><div>So what's the right thing to do?</div>
<div><br></div><div>In C -1 // 256 = 0, but in Smalltalk -1 // 256 = -1 (// rounds towards - infinity), whereas (-1 quo: 256) = 0 (quo: rounds towards 0).</div><div><br></div><div>I could modify the code generator to generate Smalltalk semantics for //, but its not pretty (one has to check signedness, check if there's a remainder, etc).</div>
<div><br></div><div>What I'd like is to have a signed bitShift:. Wait you say, bitShift: is signed. Ah, but the code generator generates unsigned shifts for all bitShift:'s !!!!.</div><div><br></div><div>So some ideas:</div>
<div><br></div><div>1. change bitShift: to obey the type of the receiver (Slang allows one to type variables, defaulting to a singed long). This is my preference, but it risks breaking a good handful of negative bitShift: uses in plugins (which is where I'm worried about regressions).</div>
<div><br></div><div>2. change bitShift: to obey explicit casts, generating a signed shift for </div><div> foo asInteger bitShift: expr</div><div> (self cCoerceSimple: #foo to: #sqInt) bitShift: expr</div><div>Seriously?!?! this stinks.</div>
<div><br></div><div>3. write</div><div><span style="white-space:pre-wrap">        </span>z := self cCode: [z >>= 8] inSmalltalk: [z // 256]</div><br>Seriously?!?! this stinks too.</div><div><br><div>Anything else that makes any sense?</div>
-- <br>best,<div>Eliot</div></div></div></blockquote></div></div></div></blockquote><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">
<div class="gmail_extra">Hi Eliot,<br></div><div class="gmail_extra">look how I did it in the 32bits LargInt variant:<br></div></div></blockquote><div><br></div><div>if the 32-bit large int version passes all the tests why hasn't it replaced the byte one?</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">cDigitSub: pWordSmall<br> len: smallLen<br> with: pWordLarge<br>
len: largeLen<br> into: pWordRes<br> | z limit |<br> <var: #pWordSmall type: 'unsigned int * '><br> <var: #pWordLarge type: 'unsigned int * '><br> <var: #pWordRes type: 'unsigned int * '><br>
<var: #z type: 'unsigned long long '><br><br> z := 0.<br> limit := smallLen - 1.<br> 0 to: limit do: <br> [:i | <br> z := z + (pWordLarge at: i) - (pWordSmall at: i).<br> pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).<br>
z := 0 - (z >> 63)].<br> limit := largeLen - 1.<br> smallLen to: limit do: <br> [:i | <br> z := z + (pWordLarge at: i) .<br> pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).<br> z := 0 - (z >> 63)].<br>
^0<br><br></div><div class="gmail_extra">In unsigned arithmetic, all these ops are perfectly well defined, and I don't think they suck.<br></div><div class="gmail_extra">So you can translate it back to unsigned char * and unsigned short (z >> 16)</div>
</div></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div>
</div></div></div>