Preliminary thoughts on implementing __matmul__

Hi All, I've been looking to implement the "@" operator from Python 3.5. Looking at the current implementation of the dot function, it only uses a vector inner product, which is either that defined in arraytypes.c.src or a version using cblas defined in _dotblas for the float, cfloat, double, cdouble types. I note that the versions defined in arraytypes.c.src include all the numeric types plus boolean, datetime, timedelta, and object. I'm not clear why datetime and timedelta should have dot products, except perhaps for scalar multiplication. The boolean version has the advantage that it can short circuit. I also note that all the operations proposed for "@" can easily be done with einsum except for objects. So I'm wondering if one easy way to implement the functions is to extend einsum to work with objects and make it use blas when available. Another thing that may be worth looking into would be some way to multiply by the complex conjugate, as that is easy to implement at the low level. I'd welcome any thoughts as to how that might be done. Anyway, I'm just looking for a discussion and ideas here. Any input is welcome. Chuck

On Wed, Aug 6, 2014 at 2:19 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Hi All,
I've been looking to implement the "@" operator from Python 3.5. Looking at the current implementation of the dot function, it only uses a vector inner product, which is either that defined in arraytypes.c.src or a version using cblas defined in _dotblas for the float, cfloat, double, cdouble types. I note that the versions defined in arraytypes.c.src include all the numeric types plus boolean, datetime, timedelta, and object. I'm not clear why datetime and timedelta should have dot products, except perhaps for scalar multiplication.
I guess numeric @ timedelta is at least well-defined, but dot products on datetime make no sense -- datetimes do not support +! One thing we should keep in mind as well is how to allow user-defined dtypes to provide efficient matmul implementations.
The boolean version has the advantage that it can short circuit. I also note that all the operations proposed for "@" can easily be done with einsum except for objects. So I'm wondering if one easy way to implement the functions is to extend einsum to work with objects and make it use blas when available.
Those do seem like nice features regardless of what we do for @ :-). I think the other obvious strategy to consider, is defining a 'dot' gufunc, with semantics identical to @. (This would be useful for backcompat as well: adding/dropping compatibility with older python versions would be as simple as mechanically replacing a @ b with newdot(a, b) or vice-versa.) This would require one new feature in the gufunc machinery: support for "optional core axes", to get the right semantics for 1d arrays. OTOH this would also be useful in general because there are other gufuncs that want to handle 1d arrays the same way @ does -- e.g., 'solve' variants. This would automatically solve both the user-defined dtype problem (ufuncs already allow for new loops to be registered) and the third-party array type problem (via __numpy_ufunc__).
Another thing that may be worth looking into would be some way to multiply by the complex conjugate, as that is easy to implement at the low level. I'd welcome any thoughts as to how that might be done.
One idea that's come up before was to define a complex-conjugate dtype, which would allow .H to be a view on the original array. A simpler solution would be to define a specialized conjdot gufunc. -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org

On Wed, Aug 6, 2014 at 5:31 AM, Nathaniel Smith <njs@pobox.com> wrote:
I think the other obvious strategy to consider, is defining a 'dot' gufunc, with semantics identical to @. (This would be useful for backcompat as well: adding/dropping compatibility with older python versions would be as simple as mechanically replacing a @ b with newdot(a, b) or vice-versa.) This would require one new feature in the gufunc machinery: support for "optional core axes", to get the right semantics for 1d arrays.
Can you elaborate on what those optional core axes would look like? If I am understanding you correctly, this is what now is solved by having more than one gufunc defined, and choosing which one to use based on the input's shapes in a thin Python wrapper. There are several examples in the linalg module you are certainly well aware of. Say you could define the matmul signature as "(i)j,j(k)->(ik)", with dimensions in parenthesis being "optional." Say we modified the gufunc machinery to detect which optional core axes are present and which not. It seems to me that you would then still need to write 4 traditional gufuncs (ij,jk->ik, j,jk->k, ij,j->i, j,j->) and dispatch to one of them. I haven't thought it through, but are there really a set of universal dispatch rules that will apply to any optional core axes problem? Would we not be losing flexibility in doing so? When I looked into gufuncs several months ago, what I missed was a way of defining signatures like n,m->n*(n-1), which would come in very handy if computing all pairwise distances. You can work around this by making the signature n,m->p and always calling the gufunc from a Python wrapper that passes in an out parameter of the right shape. But if someone gets a hold of the gufunc handle and calls it directly without an out parameter, the p defaults to 1 and you are probably in for a big crash. So it would be nice if you could provide a pointer to a function to produce the output shape based on the inputs'. On my wish list for gufunc signatures there is also frozen dimensions, e.g. a gufunc to compute greater circle distances on a sphere can be defined as m,m->, but m has to be 2, and since you don't typically want to be raising errors in the kernel, a Python wrapper is once more necessary. And again an unwrapped call to the gufunc is potentially catastrophic. Sorry for hijacking the thread, but I wouldn't mind spending some time working on expanding this functionality to include the optional axes and my wish-list, if the whole thing makes sense. Jaime

On Wed, Aug 6, 2014 at 8:32 AM, Jaime Fernández del Río < jaime.frio@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:31 AM, Nathaniel Smith <njs@pobox.com> wrote:
I think the other obvious strategy to consider, is defining a 'dot' gufunc, with semantics identical to @. (This would be useful for backcompat as well: adding/dropping compatibility with older python versions would be as simple as mechanically replacing a @ b with newdot(a, b) or vice-versa.) This would require one new feature in the gufunc machinery: support for "optional core axes", to get the right semantics for 1d arrays.
Can you elaborate on what those optional core axes would look like? If I am understanding you correctly, this is what now is solved by having more than one gufunc defined, and choosing which one to use based on the input's shapes in a thin Python wrapper. There are several examples in the linalg module you are certainly well aware of.
Say you could define the matmul signature as "(i)j,j(k)->(ik)", with dimensions in parenthesis being "optional." Say we modified the gufunc machinery to detect which optional core axes are present and which not. It seems to me that you would then still need to write 4 traditional gufuncs (ij,jk->ik, j,jk->k, ij,j->i, j,j->) and dispatch to one of them. I haven't thought it through, but are there really a set of universal dispatch rules that will apply to any optional core axes problem? Would we not be losing flexibility in doing so?
When I looked into gufuncs several months ago, what I missed was a way of defining signatures like n,m->n*(n-1), which would come in very handy if computing all pairwise distances. You can work around this by making the signature n,m->p and always calling the gufunc from a Python wrapper that passes in an out parameter of the right shape. But if someone gets a hold of the gufunc handle and calls it directly without an out parameter, the p defaults to 1 and you are probably in for a big crash. So it would be nice if you could provide a pointer to a function to produce the output shape based on the inputs'.
On my wish list for gufunc signatures there is also frozen dimensions, e.g. a gufunc to compute greater circle distances on a sphere can be defined as m,m->, but m has to be 2, and since you don't typically want to be raising errors in the kernel, a Python wrapper is once more necessary. And again an unwrapped call to the gufunc is potentially catastrophic.
Sorry for hijacking the thread, but I wouldn't mind spending some time working on expanding this functionality to include the optional axes and my wish-list, if the whole thing makes sense.
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array. Note that adding dummy dimensions can lead to '[[...]]' scalars. Working with stacked vectors isn't part of the '@' PEP. Chuck

On Wed, Aug 6, 2014 at 9:32 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 8:32 AM, Jaime Fernández del Río < jaime.frio@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:31 AM, Nathaniel Smith <njs@pobox.com> wrote:
I think the other obvious strategy to consider, is defining a 'dot' gufunc, with semantics identical to @. (This would be useful for backcompat as well: adding/dropping compatibility with older python versions would be as simple as mechanically replacing a @ b with newdot(a, b) or vice-versa.) This would require one new feature in the gufunc machinery: support for "optional core axes", to get the right semantics for 1d arrays.
Can you elaborate on what those optional core axes would look like? If I am understanding you correctly, this is what now is solved by having more than one gufunc defined, and choosing which one to use based on the input's shapes in a thin Python wrapper. There are several examples in the linalg module you are certainly well aware of.
Say you could define the matmul signature as "(i)j,j(k)->(ik)", with dimensions in parenthesis being "optional." Say we modified the gufunc machinery to detect which optional core axes are present and which not. It seems to me that you would then still need to write 4 traditional gufuncs (ij,jk->ik, j,jk->k, ij,j->i, j,j->) and dispatch to one of them. I haven't thought it through, but are there really a set of universal dispatch rules that will apply to any optional core axes problem? Would we not be losing flexibility in doing so?
When I looked into gufuncs several months ago, what I missed was a way of defining signatures like n,m->n*(n-1), which would come in very handy if computing all pairwise distances. You can work around this by making the signature n,m->p and always calling the gufunc from a Python wrapper that passes in an out parameter of the right shape. But if someone gets a hold of the gufunc handle and calls it directly without an out parameter, the p defaults to 1 and you are probably in for a big crash. So it would be nice if you could provide a pointer to a function to produce the output shape based on the inputs'.
On my wish list for gufunc signatures there is also frozen dimensions, e.g. a gufunc to compute greater circle distances on a sphere can be defined as m,m->, but m has to be 2, and since you don't typically want to be raising errors in the kernel, a Python wrapper is once more necessary. And again an unwrapped call to the gufunc is potentially catastrophic.
Sorry for hijacking the thread, but I wouldn't mind spending some time working on expanding this functionality to include the optional axes and my wish-list, if the whole thing makes sense.
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array. Note that adding dummy dimensions can lead to '[[...]]' scalars. Working with stacked vectors isn't part of the '@' PEP.
Transpose doesn't work with stacked arrays, so it would also be useful to have a function for that. Chuck

On Wed, Aug 6, 2014 at 8:32 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately.
I've thought for ages that if you want to naturally do linear algebra, you need to capture the concept of a row and column vector as distinct from each-other and from (1,n) and (n,1) shape arrays. So: +1 -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On Wed, Aug 6, 2014 at 8:32 AM, Charles R Harris wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately.
On 8/6/2014 5:05 PM, Chris Barker wrote:
I've thought for ages that if you want to naturally do linear algebra, you need to capture the concept of a row and column vector as distinct from each-other and from (1,n) and (n,1) shape arrays. So:
It seems to me that although this it may sound trivial to "add two flags", this is a fundamental conceptual change, and I hope it will not go forward without extensive discussion. To aid users like me who might want to think about this, can you please suggest for exploration a language that has adopted this approach. (Ideally, where the decision is considered a good one.) Thank you, Alan Isaac

On Mi, 2014-08-06 at 14:05 -0700, Chris Barker wrote:
On Wed, Aug 6, 2014 at 8:32 AM, Charles R Harris <charlesr.harris@gmail.com> wrote: Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately.
I've thought for ages that if you want to naturally do linear algebra, you need to capture the concept of a row and column vector as distinct from each-other and from (1,n) and (n,1) shape arrays. So:
As a first thought I am against flags. We have dot, and vdot, which ideally would at some point do stacked matrix-matrix and stacked vector-vector (albeit vdot does complex conjugation). vector-matrix and matrix-vector would require the user to use (1, n) or (n, 1) matrices. If someone can convince me that this is a big deal, flags might be the only option, though... - Sebastian
+1
-Chris
--
Christopher Barker, Ph.D. Oceanographer
Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker@noaa.gov _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion

On 07/08/2014 5:40 AM, Sebastian Berg wrote:
On Mi, 2014-08-06 at 14:05 -0700, Chris Barker wrote:
On Wed, Aug 6, 2014 at 8:32 AM, Charles R Harris <charlesr.harris@gmail.com> wrote: Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately.
I've thought for ages that if you want to naturally do linear algebra, you need to capture the concept of a row and column vector as distinct from each-other and from (1,n) and (n,1) shape arrays. So: It's a pity that these ideas weren't incorporatated into the Numarray implementation.
The treatment of the scalar was also questionable. There's time to fix these things.
As a first thought I am against flags. We have dot, and vdot, which ideally would at some point do stacked matrix-matrix and stacked vector-vector (albeit vdot does complex conjugation). vector-matrix and matrix-vector would require the user to use (1, n) or (n, 1) matrices. If someone can convince me that this is a big deal, flags might be the only option, though... That's a basic question: Is dot a big deal? Unfortunately, this wasn't examined carefully enough last Spring.
- Sebastian Colin W.
+1
-Chris
--
Christopher Barker, Ph.D. Oceanographer
Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker@noaa.gov _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion

On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors. -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org

On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with the '@' operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were preserved. Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a possible new transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything. Chuck

On Wed, Aug 6, 2014 at 5:24 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with the '@' operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were preserved. Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a possible new transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything.
Note that the '@' PEP is not compatible with current 'dot' for arrays with more than two dimensions and for scalars. Chuck

On Thu, Aug 7, 2014 at 12:24 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on stacked vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with the '@' operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were preserved. Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a possible new transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything.
It's possible you could convince me that this is a good idea, but I'm starting at like -0.95 :-). Wouldn't it be vastly simpler to just have np.linalg.matvec, matmat, vecvec or something (each of which are single-liners in terms of @), rather than deal with two different ways of representing row/column vectors everywhere? -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org

On Wed, Aug 6, 2014 at 5:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Thu, Aug 7, 2014 at 12:24 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on
vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with the '@' operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were
stacked preserved.
Another option, already supported to a large extent, is to have row and
col > classes inheriting from ndarray that add nothing, except for a possible new > transpose type function/method. I did mock up such a class just for fun, and > also added a 'dyad' function. If we really don't care to support stacked > vectors we can get by without adding anything.
It's possible you could convince me that this is a good idea, but I'm starting at like -0.95 :-). Wouldn't it be vastly simpler to just have np.linalg.matvec, matmat, vecvec or something (each of which are single-liners in terms of @), rather than deal with two different ways of representing row/column vectors everywhere?
Sure, but matvec and vecvec would not be supported by '@' except when vec was 1d because there is no way to distinguish a stack of vectors from a matrix or a stack of matrices. Chuck

On 7 Aug 2014 00:41, "Charles R Harris" <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Thu, Aug 7, 2014 at 12:24 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on
vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with
operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were
Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a
stacked the '@' preserved. possible new
transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything.
It's possible you could convince me that this is a good idea, but I'm starting at like -0.95 :-). Wouldn't it be vastly simpler to just have np.linalg.matvec, matmat, vecvec or something (each of which are single-liners in terms of @), rather than deal with two different ways of representing row/column vectors everywhere?
Sure, but matvec and vecvec would not be supported by '@' except when vec was 1d because there is no way to distinguish a stack of vectors from a matrix or a stack of matrices.
Yes. But @ can never be magic - either people will have to write something extra to flip these flags on their array objects, or they'll have to write something extra to describe which operation they want. @ was never intended to cover every case, just the simple-but-super-common ones that dot covers, plus a few more (simple broadcasting). We have np.add even though + exists too... -n

On Wed, Aug 6, 2014 at 5:51 PM, Nathaniel Smith <njs@pobox.com> wrote:
On 7 Aug 2014 00:41, "Charles R Harris" <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Thu, Aug 7, 2014 at 12:24 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com>
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Should also mention that we don't have the ability to operate on
stacked
vectors because they can't be identified by dimension info. One workaround is to add dummy dimensions where needed, another is to add two flags, row and col, and set them appropriately. Two flags are needed for backward compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with
operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were
Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a
wrote: the '@' preserved. possible new
transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything.
It's possible you could convince me that this is a good idea, but I'm starting at like -0.95 :-). Wouldn't it be vastly simpler to just have np.linalg.matvec, matmat, vecvec or something (each of which are single-liners in terms of @), rather than deal with two different ways of representing row/column vectors everywhere?
Sure, but matvec and vecvec would not be supported by '@' except when vec was 1d because there is no way to distinguish a stack of vectors from a matrix or a stack of matrices.
Yes. But @ can never be magic - either people will have to write something extra to flip these flags on their array objects, or they'll have to write something extra to describe which operation they want. @ was never intended to cover every case, just the simple-but-super-common ones that dot covers, plus a few more (simple broadcasting). We have np.add even though + exists too...
I don't expect stacked matrices/vectors to be used often, although there are some areas that might make heavy use of them, so I think we could live with the simple implementation, it's just a bit of a wart when there is broadcasting of arrays. Just to be clear, the '@' broadcasting differs from the dot broadcasting, agreed? Chuck

On Thu, Aug 7, 2014 at 1:00 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
Just to be clear, the '@' broadcasting differs from the dot broadcasting, agreed?
Right, np.dot does the equivalent of ufunc.outer (i.e., not broadcasting at all), while @ broadcasts. -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org

I don't expect stacked matrices/vectors to be used often, although there are some areas that might make heavy use of them, so I think we could live with the simple implementation, it's just a bit of a wart when there is broadcasting of arrays. Just to be clear, the '@' broadcasting differs from the dot broadcasting, agreed? This lack of elegance and unity combined with frankly; a lack of utility, made me plead @ is a bad idea in the first place; but I guess I lost that debate... On Thu, Aug 7, 2014 at 2:00 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:51 PM, Nathaniel Smith <njs@pobox.com> wrote:
On 7 Aug 2014 00:41, "Charles R Harris" <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 5:33 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Thu, Aug 7, 2014 at 12:24 AM, Charles R Harris <charlesr.harris@gmail.com> wrote:
On Wed, Aug 6, 2014 at 4:57 PM, Nathaniel Smith <njs@pobox.com>
On Wed, Aug 6, 2014 at 4:32 PM, Charles R Harris <charlesr.harris@gmail.com> wrote: > Should also mention that we don't have the ability to operate on
stacked
> vectors because they can't be identified by dimension info. One > workaround > is to add dummy dimensions where needed, another is to add two flags, > row > and col, and set them appropriately. Two flags are needed for backward > compatibility, i.e., both false is a traditional array.
It's possible I could be convinced to like this, but it would take a substantial amount of convincing :-). It seems like a pretty big violation of orthogonality/"one obvious way"/etc. to have two totally different ways of representing row/column vectors.
The '@' operator supports matrix stacks, so it would seem we also need to support vector stacks. The new addition would only be effective with
operator. The main problem I see with flags is that adding them would require an extensive audit of the C code to make sure they were
Another option, already supported to a large extent, is to have row and col classes inheriting from ndarray that add nothing, except for a
wrote: the '@' preserved. possible new
transpose type function/method. I did mock up such a class just for fun, and also added a 'dyad' function. If we really don't care to support stacked vectors we can get by without adding anything.
It's possible you could convince me that this is a good idea, but I'm starting at like -0.95 :-). Wouldn't it be vastly simpler to just have np.linalg.matvec, matmat, vecvec or something (each of which are single-liners in terms of @), rather than deal with two different ways of representing row/column vectors everywhere?
Sure, but matvec and vecvec would not be supported by '@' except when vec was 1d because there is no way to distinguish a stack of vectors from a matrix or a stack of matrices.
Yes. But @ can never be magic - either people will have to write something extra to flip these flags on their array objects, or they'll have to write something extra to describe which operation they want. @ was never intended to cover every case, just the simple-but-super-common ones that dot covers, plus a few more (simple broadcasting). We have np.add even though + exists too...
I don't expect stacked matrices/vectors to be used often, although there are some areas that might make heavy use of them, so I think we could live with the simple implementation, it's just a bit of a wart when there is broadcasting of arrays. Just to be clear, the '@' broadcasting differs from the dot broadcasting, agreed?
Chuck
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
participants (8)
-
Alan G Isaac
-
Charles R Harris
-
Chris Barker
-
cjw
-
Eelco Hoogendoorn
-
Jaime Fernández del Río
-
Nathaniel Smith
-
Sebastian Berg