<br><br><div><span class="gmail_quote">On 1/10/07, <b class="gmail_sendername">A. M. Archibald</b> <<a href="mailto:peridot.faceted@gmail.com">peridot.faceted@gmail.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On 10/01/07, Charles R Harris <<a href="mailto:charlesr.harris@gmail.com">charlesr.harris@gmail.com</a>> wrote:<br><br>> > You're the second or third person to recently come up with a useful<br>> application for using inplace ops with repeated indices only to be stymied
<br>> by that fact that they don't actually work that way. I've been wondering if<br>> we should try to come up with a way to support this usage. Although it might<br>> be feasible to make += work, the implementation is horrible, and there are
<br>> all sorts of inefficiencies built into that method of doing it.<br>> ><br>> > The natural approach would seem to be to hang another method off the<br>> ufuncs. That way you get support for all of the various operations. I was
<br>> thinking something like:<br>> ><br>> ><br>> > unfunc.inplace (dest, indices, source)<br>><br>> Yeah, something like that. A general indirect addressing primitive of some<br>> sort would be useful for these situations. The indices are sort of pointers
<br>> into the destination, the problem is how to bind this to operators. It<br>> should almost be some sort lvalue analogous to **p = whatever, or in this<br>> case dest[index[j]] {assignment} src[j]. So maybe indirect(dest, indices,
<br>> source, op). Then there is all the madness of fancy indexing (which I think<br>> I could have done without). Because the current applications are limited and<br>> could be met with the simplest 1D version, it would probably be best to
<br>> start with the most basic functionality and then extend it if the need<br>> arose. Or maybe even some simple c extension that did the whole basic +=<br>> thing for one dimension.<br><br>I disagree that it should be hung off ufuncs. That doesn't allow, for
<br>example, averaging of normal vectors (without some highly clever and<br>hard-to-follow axis specification).</blockquote><div><br>What makes you think this? To go back to the start of the thread,  the OP wanted the following to work:
<br><br><div style="margin-left: 40px;">    def calculate_normals(indices, vertices):<br>        i = indices<br>        faces = vertices[i].reshape((i.shape[0] / 3, 3, 3)) # indices = 3 x N?<br>        face_normals = cross(faces[:,1] - faces[:,0], faces[:,2] -faces[:,0])
<br>        normals = zeros(vertices.shape, float32)<br>        normals[i] += face_normals.repeat(3, axis=0)<br>        normals /= sqrt(sum(normals*normals,axis=1)).reshape(normals.shape[0], 1)<br>        return normals    
<br></div> <br>Hanging it off of ufuncs, would just mean that the line:<br><div style="margin-left: 40px;">normals[i] += face_normals.repeat(3, axis=0)<br></div>would get replaced by this line:<br><div style="margin-left: 40px;">
add.inplace(normals, i, face_normals.repeat(3, axis=0))</div><br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">I implemented one possible version in pure python, just to think about
<br>the UI (and to see if it could be made fast using sorting; I don't<br>think it will actually help much, and I also note that whether it even<br>has any hope depends on whether there are more objects to accumulate<br>
than destination slots, or fewer). The basic design is<br><br>def accumulate(dest, indices, values, combine=N.add);</blockquote><div><br>Unless I'm mistaken, semantically, this is no different than add.inplace as defined above, you've just moved stuff around. In practice, I think that hanging something like this off of ufuncs is likely to be the way to go to get decent performance. Plus, that's the traditional way, in numpy,  to deal with methods that are the same except for the operator at the core of them.
<br><br>I'm not in love with the name in 'inplace' necessarily, but I don't think accumulate will really fly either, accumulate already has a different meaning that is close enough to be confusing, but far enough apart that I don't see a way to shoehorn them together.
<br> </div>[SNIP]<br></div><br clear="all"><br>-- <br>//=||=\\