[Numpy-discussion] __array_wrap__ and dot

Aronne Merrelli aronne.merrelli@gmail....
Wed Aug 22 09:17:46 CDT 2012


Hello list,

I posted an issue many months ago [1] about confusing __array_wrap__
behavior in a subclass of np.matrix.
Since that time I wasn't really using the code that used the matrix
subclass, but lately I have starting using the code so I've run into
the issue again. Looking into a little more detail, I think the root
of the problem is how __array_wrap__ interacts with the dot functions.
Operations like M*2 will be processed differently depending on whether
M is a ndarray or matrix subclass; it appears that a matrix will
always call np.dot for that operation, while an ndarray will go
through np.multiply. Since dot acts differently than multiply here,
you get different results between the two subclasses.

I updated the gist to show the problem [2]. The output I get on my
system is pasted at the bottom. It looks like __array_wrap__ gets
called sometimes, depending on the type of one of the arguments. I'm
not seeing any logical pattern to it, which makes it confusing.  My
expectation (perhaps incorrect) is that __array_wrap__ should be
invoked any time dot is called. I guess that depends on whether dot
should be considered a ufunc - I don't know the answer to that
question.

If someone with more knowledge of the internals could take a look at
this, that would be great - I think this is a bug, but I'm not really
sure what is the expected behavior here.

Thanks,
Aronne

[1] http://mail.scipy.org/pipermail/numpy-discussion/2011-December/059665.html
[2] https://gist.github.com/1511354



Output from run_test (see the gist code) using ipython:


In [1]: import matrix_array_wrap_test as mtest; import numpy as np

In [2]: np.__version__
Out[2]: '1.6.1'

In [3]: np.dot
Out[3]: <function numpy.core._dotblas.dot>

In [4]: mtest.run_test()
aw called? |  creation                       |  use

Yes        |  o=ArrSubClass(2)               |  o2 = o + 2
Yes        |  o=ArrSubClass(2)               |  o2 = o + 2.0
Yes        |  o=ArrSubClass(2)               |  o2 = o * 2
Yes        |  o=ArrSubClass(2)               |  o2 = o * 2.0
Yes        |  o=ArrSubClass(2)               |  o2 = o * o.T
No         |  o=ArrSubClass(2)               |  o2 = np.dot(o,2)
No         |  o=ArrSubClass(2)               |  o2 = np.dot(o,2.0)
No         |  o=ArrSubClass(2)               |  o2 = np.dot(o,o.T)
Yes        |  o=ArrSubClass(2)               |  o2 = np.core.multiarray.dot(o,2)
Yes        |  o=ArrSubClass(2)               |  o2 =
np.core.multiarray.dot(o,2.0)
No         |  o=ArrSubClass(2)               |  o2 =
np.core.multiarray.dot(o,o.T)

Yes        |  o=MatSubClass([1, 1])          |  o2 = o + 2
Yes        |  o=MatSubClass([1, 1])          |  o2 = o + 2.0
Yes        |  o=MatSubClass([1, 1])          |  o2 = o * 2
No         |  o=MatSubClass([1, 1])          |  o2 = o * 2.0
No         |  o=MatSubClass([1, 1])          |  o2 = o * o.T
Yes        |  o=MatSubClass([1, 1])          |  o2 = np.dot(o,2)
No         |  o=MatSubClass([1, 1])          |  o2 = np.dot(o,2.0)
No         |  o=MatSubClass([1, 1])          |  o2 = np.dot(o,o.T)
Yes        |  o=MatSubClass([1, 1])          |  o2 = np.core.multiarray.dot(o,2)
Yes        |  o=MatSubClass([1, 1])          |  o2 =
np.core.multiarray.dot(o,2.0)
No         |  o=MatSubClass([1, 1])          |  o2 =
np.core.multiarray.dot(o,o.T)

Yes        |  o=MatSubClass([1.0, 1.0])      |  o2 = o + 2
Yes        |  o=MatSubClass([1.0, 1.0])      |  o2 = o + 2.0
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = o * 2
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = o * 2.0
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = o * o.T
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = np.dot(o,2)
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = np.dot(o,2.0)
No         |  o=MatSubClass([1.0, 1.0])      |  o2 = np.dot(o,o.T)
Yes        |  o=MatSubClass([1.0, 1.0])      |  o2 = np.core.multiarray.dot(o,2)
Yes        |  o=MatSubClass([1.0, 1.0])      |  o2 =
np.core.multiarray.dot(o,2.0)
No         |  o=MatSubClass([1.0, 1.0])      |  o2 =
np.core.multiarray.dot(o,o.T)


More information about the NumPy-Discussion mailing list