[Numpy-discussion] Bringing order to higher dimensional operations

Nathaniel Smith njs at pobox.com
Fri Jul 19 11:31:31 EDT 2013

On Thu, Jul 18, 2013 at 2:23 PM, Sebastian Berg
<sebastian at sipsolutions.net> wrote:
> It is so difficult because of the fact that dot is basically a
> combination of many functions:
>   o vector * vector -> vector
>   o vector * matrix -> matrix (add dimensions to vector on right)
>   o matrix * vector -> matrix (add dimensions to vector on left)
>   o matrix * matrix -> matrix
> plus scalar cases.

Though, just throwing this out there for the archives since I was
thinking about it...

I think we *could* consolidate all dot's functionality into a single
gufunc, with a few small changes:

1) Deprecate and get rid of the scalar special cases. (For those
following along: right now, np.dot(10, array) does scalar
multiplication, but this doesn't make much sense conceptually, it's
not documented, and I don't think anyone uses it. Except maybe
np.matrix.__mul__, but that could be fixed.)

2) Deprecate the strange "broadcasting" behaviour for high-dimensional
inputs, in favor of the gufunc version suggested in the previous

That leaves the vector * vector, vector * matrix, matrix * vector,
matrix * matrix cases. To handle these:

3) Extend the gufunc machinery to understand the idea that some core
dimensions are allowed to take on a special "nonexistent" size. So the
signature for dot would be:
  (m*,k) x (k, n*) -> (m*, n*)
where '*' denotes dimensions who are allowed to take on the
"nonexistent" size if necessary. So dot(ones((2, 3)), ones((3, 4)))
would have
  m = 2
  k = 3
  n = 4
and produce an output with shape (m, n) = (2, 4). But dot(ones((2,
3)), ones((3,))) would have
  m = 2
  k = 3
  n = <nothing>
and produce an output with shape (m, n) = (2, <nothing>) = (2,). And
dot(ones((3,)), ones((3,))) would have
  m = <nothing>
  k = 3
  n = <nothing>
and produce an output with shape (m, n) = (<nothing>, <nothing>) = (),
i.e., dot(vector, vector) would return a scalar.

I'm not sure if there are any other cases where this would be useful,
but even if it were just for 'dot', that's still a pretty important
case that might justify the mechanism all on its own.


More information about the NumPy-Discussion mailing list