<div dir="ltr">Hi,<div><br></div><div>I&#39;m working on some low-level pixel processing code (stuff that is not possible to do using standard API or on eg GPU), and I had lots of eg these:</div><div><br></div><div>for y in someStartY ..&lt; someStopY {</div><div>    for x in someStartX ..&lt; someStopX {</div><div>        ... pixels[x, y] ...</div><div>    }</div><div>}</div><div><br></div><div>So I implemented some (value) types like eg IntPoint2D, IntSize2D, IntRect2D and I made an IntRect2DIterator so that IntRect2D could be a Sequence over its (discrete) points. With this I could rewrite the above like so:</div><div><br></div><div>for pixelPosAsIntPoint2D in someIntRect2D {</div><div>    ... pixels[pixelPosAsIntPoint2D] ...</div><div>}</div><div><br></div><div>For some reason the first version (two nested for loops for x and y) is always a bit faster than the abstracted version no matter how I write it (tried using eg &amp;+ instead of + etc).</div><div><br></div><div><br></div><div><br></div><div>Is it possible to write as a zero cost abstraction like this, if so, how? If not, why?</div><div><br></div><div><br></div><div><br></div><div><br></div><div>PS</div><div><br></div><div>Note that eg this:</div><div><br></div><div><div>for y in someStartY ..&lt; someStopY {</div><div>    for x in someStartX ..&lt; someStopX {</div><div>       let pixelPosAsIntPoint2D = IntPoint2D(x: x, y: y)</div><div>        ... pixels[pixelPosAsIntPoint2D] ...</div><div>    }</div><div>}</div></div><div><br></div><div>is exactly as fast as the top example (using just ... pixels[x, y] ...). So the difference in execution time seems to be due to something in the Iterator and not eg the pixel accessing subscript taking the 2d int point type instead of separate x and y ints.</div><div><br></div><div>Here is one Iterator variant that I have tested:</div><div><br></div><div><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">struct Rect2DIntPointIterator : IteratorProtocol, Sequence {</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    let startX, startY, stopX, stopY: Int</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    var px, py: Int</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    init(rect: Rect2DInt) {</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        startX = rect.origin.x</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        startY = rect.origin.y</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        stopX = rect.maxX</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        stopY = rect.maxY</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        px = startX</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        py = startY</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    }</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    mutating func next() -&gt; Point2DInt? {</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        defer { px = px &amp;+ 1 }</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        if px == stopX {</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">            px = startX</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">            py = py &amp;+ 1</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">            if py == stopY { return nil }</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        }</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">        return Point2DInt(x: px, y: py)</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">    }</span></font></p><p style="margin:0px;line-height:normal"><font color="#000000" face="menlo"><span style="font-size:12px">}</span></font></p></div><div><br></div><div><br></div><div>And here are typical execution times from an example test:</div><div>2.1 seconds using my Iterator (the fastest I can get it, no matter how I try to rewrite it).</div><div>1.5 seconds using nested x, y for loops.</div><div><br></div><div>I&#39;m pretty sure my testing is done thoroughly (measuring average of many runs, using random data, avoiding dead code elimination, whole module optimization, etc).<br></div><div><br></div><div>I have tried profiling the code and looking at the disassmbly but I&#39;m failing to understand what&#39;s going on.</div><div><br></div><div>So the ultimate answer would be in the form of a (2d, Int) Rectangle type whose (2d, Int) Points can be iterated in a for loop, at zero cost compared to doing the same using two nested for loops. Or an explanation of why this is impossible.</div><div><br></div><div>DS</div><div><br></div><div>/Jens</div><div><br></div></div>