strange multiplication behavior with numpy.float64 and ndarray subclass
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray: mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1) but this one returns a np.float64 instance? print type(np.float64(1)*mine) Here is the full script: import numpy as np class MyArray(np.ndarray): __array_priority__ = 20 def __new__(cls): return np.asarray(1).view(cls).copy() def __repr__(self): return 'my_array' __str__ = __repr__ def __mul__(self, other): return super(MyArray, self).__mul__(other) def __rmul__(self, other): return super(MyArray, self).__rmul__(other) mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1) print type(np.float64(1)*mine) Thanks, Darren
![](https://secure.gravatar.com/avatar/56b215661867f3b4f4a3b28077de66b3.jpg?s=120&d=mm&r=g)
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Wed, Jan 21, 2009 at 11:43 AM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
I dont understand why __array_priority__ is not being respected here. Ticket 826 lists the component as numpy.ma, it seems the problem is in numpy.core. I think the severity of the ticket should be increased. But I wasnt able to view the ticket, I keep getting an "internal server error".
![](https://secure.gravatar.com/avatar/56b215661867f3b4f4a3b28077de66b3.jpg?s=120&d=mm&r=g)
I dont understand why __array_priority__ is not being respected here. Ticket 826 lists the component as numpy.ma, it seems the problem is in numpy.core. I think the severity of the ticket should be increased. But I wasnt able to view the ticket, I keep getting an "internal server error".
Ticket #826 bumped.
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Wed, Jan 21, 2009 at 12:26 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
I dont understand why __array_priority__ is not being respected here. Ticket 826 lists the component as numpy.ma, it seems the problem is in numpy.core. I think the severity of the ticket should be increased. But I wasnt able to view the ticket, I keep getting an "internal server error".
Ticket #826 bumped.
Just an additional bit of context. I'm working on a subclass that handles physical quantities, and issue 826 causes a quantity to be converted to a dimensionless magnitude.
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Wed, Jan 21, 2009 at 1:07 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Wed, Jan 21, 2009 at 12:26 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
I dont understand why __array_priority__ is not being respected here. Ticket 826 lists the component as numpy.ma, it seems the problem is in numpy.core. I think the severity of the ticket should be increased. But I wasnt able to view the ticket, I keep getting an "internal server error".
Ticket #826 bumped.
Just an additional bit of context. I'm working on a subclass that handles physical quantities, and issue 826 causes a quantity to be converted to a dimensionless magnitude.
I wonder if this issue is appearing in other places as well. Many of the ndarray methods work without modification on my Quantity subclass, but the methods that produce scalars do not. For instance, __getitem__ yields a dimensionless number when called with an integer index, but it yields another Quantity if called with a range, so I have to reimplement __getitem__ so it yields a quantity for single indices. tolist, min, max, mean, are the same way. Is there an ndarray attribute I should be using to tell the superclass what is the desired type (aside from __array_priority__)? Thanks, Darren
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Wed, Jan 21, 2009 at 12:43 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
I believe ticket #826 can be solved with the application of this patch: $ svn diff scalarmathmodule.c.src Index: scalarmathmodule.c.src =================================================================== --- scalarmathmodule.c.src (revision 6566) +++ scalarmathmodule.c.src (working copy) @@ -566,6 +566,10 @@ Py_DECREF(descr1); return ret; } + else if (PyArray_GetPriority(a, PyArray_SUBTYPE_PRIORITY) > \ + PyArray_SUBTYPE_PRIORITY) { + return -2; + } else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { int retval; retval = _@name@_convert_to_ctype(temp, arg1); I've run the unit tests and get the same results with and without the patch applied, but it solves the problem in my script and also the problem with masked arrays. Darren
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Sun, Mar 8, 2009 at 12:31 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Wed, Jan 21, 2009 at 12:43 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
I believe ticket #826 can be solved with the application of this patch:
$ svn diff scalarmathmodule.c.src Index: scalarmathmodule.c.src =================================================================== --- scalarmathmodule.c.src (revision 6566) +++ scalarmathmodule.c.src (working copy) @@ -566,6 +566,10 @@ Py_DECREF(descr1); return ret; } + else if (PyArray_GetPriority(a, PyArray_SUBTYPE_PRIORITY) > \ + PyArray_SUBTYPE_PRIORITY) { + return -2; + } else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { int retval; retval = _@name@_convert_to_ctype(temp, arg1);
I've run the unit tests and get the same results with and without the patch applied, but it solves the problem in my script and also the problem with masked arrays.
Here is a test for this patch, maybe issue #826 can be closed. Index: numpy/core/tests/test_umath.py =================================================================== --- numpy/core/tests/test_umath.py (revision 6575) +++ numpy/core/tests/test_umath.py (working copy) @@ -253,6 +253,17 @@ self.failUnless(isinstance(x, with_wrap)) assert_array_equal(x, np.array((1, 2, 3))) + def test_priority_with_scalar(self): + # test fix for bug #826: + class A(np.ndarray): + __array_priority__ = 10 + def __new__(cls): + return np.asarray(1.0, 'float64').view(cls).copy() + a = A() + x = np.float64(1)*a + self.failUnless(isinstance(x, A)) + assert_array_equal(x, np.array(1)) + def test_old_wrap(self): class with_wrap(object): def __array__(self):
![](https://secure.gravatar.com/avatar/96dd777e397ab128fedab46af97a3a4a.jpg?s=120&d=mm&r=g)
On Sun, Mar 8, 2009 at 4:42 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Sun, Mar 8, 2009 at 12:31 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Wed, Jan 21, 2009 at 12:43 PM, Pierre GM <pgmdevlist@gmail.com> wrote:
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
I believe ticket #826 can be solved with the application of this patch:
$ svn diff scalarmathmodule.c.src Index: scalarmathmodule.c.src =================================================================== --- scalarmathmodule.c.src (revision 6566) +++ scalarmathmodule.c.src (working copy) @@ -566,6 +566,10 @@ Py_DECREF(descr1); return ret; } + else if (PyArray_GetPriority(a, PyArray_SUBTYPE_PRIORITY) > \ + PyArray_SUBTYPE_PRIORITY) { + return -2; + } else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { int retval; retval = _@name@_convert_to_ctype(temp, arg1);
I've run the unit tests and get the same results with and without the patch applied, but it solves the problem in my script and also the problem with masked arrays.
Here is a test for this patch, maybe issue #826 can be closed.
Index: numpy/core/tests/test_umath.py =================================================================== --- numpy/core/tests/test_umath.py (revision 6575) +++ numpy/core/tests/test_umath.py (working copy) @@ -253,6 +253,17 @@ self.failUnless(isinstance(x, with_wrap)) assert_array_equal(x, np.array((1, 2, 3)))
+ def test_priority_with_scalar(self): + # test fix for bug #826: + class A(np.ndarray): + __array_priority__ = 10 + def __new__(cls): + return np.asarray(1.0, 'float64').view(cls).copy() + a = A() + x = np.float64(1)*a + self.failUnless(isinstance(x, A)) + assert_array_equal(x, np.array(1)) + def test_old_wrap(self): class with_wrap(object): def __array__(self):
__
Added in r6578... Chuck
![](https://secure.gravatar.com/avatar/4a8dabe7a7bd48e8106fea1c56c46117.jpg?s=120&d=mm&r=g)
On Sun, Mar 8, 2009 at 7:00 PM, Charles R Harris <charlesr.harris@gmail.com>wrote:
On Sun, Mar 8, 2009 at 4:42 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Sun, Mar 8, 2009 at 12:31 PM, Darren Dale <dsdale24@gmail.com> wrote:
On Wed, Jan 21, 2009 at 12:43 PM, Pierre GM <pgmdevlist@gmail.com>wrote:
On Jan 21, 2009, at 11:34 AM, Darren Dale wrote:
I have a simple test script here that multiplies an ndarray subclass with another number. Can anyone help me understand why each of these combinations returns a new instance of MyArray:
mine = MyArray() print type(np.float32(1)*mine) print type(mine*np.float32(1)) print type(mine*np.float64(1)) print type(1*mine) print type(mine*1)
but this one returns a np.float64 instance?
FYI, that's the same behavior as observed in ticket #826. A first thread addressed that issue http://www.mail-archive.com/numpy-discussion@scipy.org/msg13235.html But so far, no answer has been suggested. Any help welcome.
I believe ticket #826 can be solved with the application of this patch:
$ svn diff scalarmathmodule.c.src Index: scalarmathmodule.c.src =================================================================== --- scalarmathmodule.c.src (revision 6566) +++ scalarmathmodule.c.src (working copy) @@ -566,6 +566,10 @@ Py_DECREF(descr1); return ret; } + else if (PyArray_GetPriority(a, PyArray_SUBTYPE_PRIORITY) > \ + PyArray_SUBTYPE_PRIORITY) { + return -2; + } else if ((temp = PyArray_ScalarFromObject(a)) != NULL) { int retval; retval = _@name@_convert_to_ctype(temp, arg1);
I've run the unit tests and get the same results with and without the patch applied, but it solves the problem in my script and also the problem with masked arrays.
Here is a test for this patch, maybe issue #826 can be closed.
Index: numpy/core/tests/test_umath.py =================================================================== --- numpy/core/tests/test_umath.py (revision 6575) +++ numpy/core/tests/test_umath.py (working copy) @@ -253,6 +253,17 @@ self.failUnless(isinstance(x, with_wrap)) assert_array_equal(x, np.array((1, 2, 3)))
+ def test_priority_with_scalar(self): + # test fix for bug #826: + class A(np.ndarray): + __array_priority__ = 10 + def __new__(cls): + return np.asarray(1.0, 'float64').view(cls).copy() + a = A() + x = np.float64(1)*a + self.failUnless(isinstance(x, A)) + assert_array_equal(x, np.array(1)) + def test_old_wrap(self): class with_wrap(object): def __array__(self):
__
Added in r6578... Chuck
Thank you very much.
participants (3)
-
Charles R Harris
-
Darren Dale
-
Pierre GM