<div dir="ltr"><div dir="ltr">On Tue, Jul 28, 2020 at 4:34 AM Stephan Lutz <<a href="mailto:dev@stlutz.net">dev@stlutz.net</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  

    
  
  <div>
    <p>While transforming points using MatrixTransform2x3 we noticed
      some strange rounding behavior:</p>
    <blockquote>
      <p><tt>"with plugin"</tt><tt><br>
        </tt><tt>(MatrixTransform2x3 withOffset: 5 @ 10)
          localPointToGlobal: 0@0. "5@10"</tt><tt><br>
        </tt><tt>(MatrixTransform2x3 withOffset: -5 @ -10)
          localPointToGlobal: 0@0. "-4@ -9"</tt><tt><br>
        </tt><tt><br>
        </tt><tt>"without plugin"</tt><tt><br>
        </tt><tt>((MatrixTransform2x3 withOffset: 5 @ 10)
          transformPoint: 0@0) rounded. "5@10"</tt><tt><br>
        </tt><tt>((MatrixTransform2x3 withOffset: -5 @ -10)
          transformPoint: 0@0) rounded. "-5@ -10"</tt></p>
    </blockquote>
    <p>It appears the code used to round in the plugin simply adds 0.5
      and truncates the result, which does not work correctly for
      negative numbers.<br>
      This code can be found in <tt>Matrix2x3Plugin >>
        #roundAndStoreResultPoint:</tt> and <tt>Matrix2x3Plugin
        >> #roundAndStoreResultRect:x0:y0:x1:y1:</tt> .</p>
    <p>----</p>
    <p>On a kind of related note: Is there even a reason to round the
      resulting floats?</p>
    <p>While the class comment of MatrixTransform2x3 notes that this
      behavior is intentional, glancing quickly over its uses we could
      not find anything taking advantage or benefiting from it. It's
      also not a limitation of the DisplayTransform interface, since
      MorphicTransform does produce floating point values. Wouldn't it
      be much more versatile and easier to leave rounding to users if
      they actually need it?</p></div></blockquote><div>No. Having a float result means that the primitive would need to allocate two Float objects. Any allocation can fail due to memory exhaustion. So the primitive would have to be made to retry the allocation after running a garbage collection.</div><div><br></div><div>Secondly, its results are primarily used to set up a WarpBlt IIRC, for drawing rotated user objects in Etoys. WarpBlt fails if the coords are not integers. The failure code rounds the numbers and retries. Doing the rounding in the matrix primitives ensured a fast path to rendering - that's why it was done that way.</div><div><br></div><div>So, there are very good reasons why the plugin returns integers. And there are Squeak VMs where this still is a very reasonable behavior. It also would be a good idea to document the reasoning in the class comment of MatrixTransform2x3.</div><div><br></div><div>That being said, there is virtually no reason to use it when running on Cog, much less Sista, especially on 64 bits where we have immediate floats. An interesting thing would be to compare a pure Smalltalk implementation to the performance of the plugin. If you need floating point transform results, just write it in Smalltalk, would be my suggestion.</div><div><br></div><div>- Vanessa -</div></div></div>