<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2">
<p style="margin:1em 0px">Nathaniel:</p><span class="">
<blockquote style="margin:1em 0px;border-left:4px solid rgb(221,221,221);padding:0px 1em;color:rgb(119,119,119);quotes:none">
<p style="margin:1em 0px">Output shape feels very similar to<br>output dtype to me, so maybe the general way to handle this would be<br>to make the first callback take the input shapes+dtypes and return the<br>desired output shapes+dtypes? </p>
</blockquote>
</span><p style="margin:1em 0px">This hits on an interesting alternative to frozen dimensions - <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">np.cross</code> could just become a regular ufunc with signature <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">np.dtype((float64, 3)), np.dtype((float64, 3)) &rarr; np.dtype((float64, 3))</code></p></div></div></blockquote><div>As you note further down, the present proposal of just using numbers has the advantage of being clear and easy. Another (small?) advantage is that I can use `axis` to tell where my three coordinates are, rather than be stuck with having them as the last dimension.<br><br></div><div>Indeed, in my trials for wrapping the Standards Of Fundamental Astronomy routines, I started with just making every 3-vector and 3x3-matrix structured arrays with the relevant single sub-array entry. That worked, but I ended up disliking the casting to and fro.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2">
<blockquote style="margin:1em 0px;border-left:4px solid rgb(221,221,221);padding:0px 1em;color:rgb(119,119,119);quotes:none">
<p style="margin:1em 0px">Furthermore, the expansion quickly becomes cumbersome.  For instance, for the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">all_equal</code> signature of <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">(n|1),(n|1)->()</code> …</p>
</blockquote>
<p style="margin:1em 0px">I think this is only a good argument when used in conjunction with the broadcasting syntax. I don’t think it’s a reason for matmul not to have multiple signatures. Having multiple signatures is an disincentive to introduced too many overloads of the same function, which seems like a good thing to me</p></div></div></blockquote><div>But implementation for matmul is actually considerably trickier, since the internal loop now has to check the number of distinct dimensions.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2">
<p style="margin:1em 0px">Summarizing my overall opinions:</p>
<ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">I’m +0.5 on frozen dimensions. The use-cases seem reasonable, and it seems like an easy-ish way to get them. Allowing ufuncs to natively support subarray types might be a tidier solution, but that could come down the road</li></ul></div></div></blockquote><div>Indeed, they are not mutually exclusive. My guess would be that the use cases would be somewhat different.<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="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">I’m -1 on optional dimensions: they seem to legitimize creating many overloads of gufuncs. I’m already not a fan of how matmul has special cases for lower dimensions that don’t generalize well. To me, the best way to handle <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">matmul</code> would be to use the proposed <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">__array_function__</code> to handle the shape-based special-case dispatching, either by:<ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">Inserting dimensions, and calling the true gufunc <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">np.linalg.matmul_2d</code> (which is a function I’d like direct access to anyway).</li>
<li style="margin:1em 0px">Dispatching to one of four ufuncs</li></ul></li></ul></div></div></blockquote><div>I must admit I wish that `@` was just pure matrix multiplication...  But otherwise agree with Stephan as optional dimensions being the least-bad solution.<br></div><div> <br></div><div>Aside: do agree we should think about how to expose the `linalg` gufuncs.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><ul style="padding-left:2em;margin:1em 0px"><li style="margin:1em 0px">Broadcasting dimensions:<ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">I know you’re not suggesting this but: enabling broadcasting  unconditionally for all gufuncs would be a bad idea, masking linalg bugs. (although einsum does support broadcasting…)</li></ul></li></ul></div></div></blockquote><div>Indeed, definitely *not* suggesting that!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><ul style="padding-left:2em;margin:1em 0px"><li style="margin:1em 0px"><ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">Does it really need a per-dimension flag, rather than a global one? Can you give a case where that’s useful?</li></ul></li></ul></div></div></blockquote><div>Mostly simply that the implementation is easier given the optional dimensions... Also, it has the benefit of being clear what the function can handle by inspection of the signature, i.e., it self-documents better (one of my main arguments in favour of frozen dimensions...).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><ul style="padding-left:2em;margin:1em 0px"><li style="margin:1em 0px"><ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">If we’d already made <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">all_equal</code> a gufunc, I’d be +1 on adding broadcasting support to it  </li>
<li style="margin:1em 0px">I’m -0.5 on the all_equal path in the first place. I think we either should have a more generic approach to combined ufuncs, or just declare them <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">numba</code>s job.</li></ul></li></ul></div></div></blockquote><div>I am working on and off on a way to generically chain ufuncs (goal would be to auto-create an inner loop that calls all the chained ufuncs loops in turn). Not sure that short-circuiting will be all that easy.<br></div><div><br></div><div>I actually quite like the all_equal ufunc, but it is in part because I remember discovering how painfully slow (a==b).all() was (and still have a place where I would use it if it existed). And it does fit in the (admittedly vague) plans to try to make `.reduce` a gufunc. <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="m_7560650544387476134markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><ul style="padding-left:2em;margin:1em 0px"><li style="margin:1em 0px"><ul style="padding-left:2em;margin:1em 0px">
<li style="margin:1em 0px">Can you come up with a broadcasting use-case that isn’t just chaining a reduction with a  broadcasting ufunc?</li></ul></li></ul></div></div></blockquote><div>Perhaps the use is that it allows people to write gufuncs that are like such functions... Absent a mechanism to chain ufuncs, more complicated gufuncs are currently the easiest way to get fast more complicated algebra.<br><br></div><div>But perhaps a putative <br><br>weighted_mean(y, sigma) -> mean, sigma_mean<br><br>is a decent example? Its signature would be<br><br></div><div>(n),(n)->(),()<br></div><div><br>but then you're forced to give individual sigmas for each point. With<br></div><div><br>(n|1),(n|1)->(),()<br></div><div><br>you are no longer forced to do that (though the case of all y being the same is less than useful here... I did at some point have an implementation that worked by core dimension of each argument, but ended up feeling it was not worth the extra complication)<br><br></div><div>-- Marten<br></div></div></div></div>