thouis / numpy-trac-migration

numpy Trac to github issues migration
2 stars 3 forks source link

np.random.binomial() fails with int64 'n' argument on x86/32-bit (migrated from Trac #1413) #2966

Open thouis opened 12 years ago

thouis commented 12 years ago

Original ticket http://projects.scipy.org/numpy/ticket/1413 Reported 2010-02-26 by atmention:dwf, assigned to unknown.

Reported to the list by James Bergstra, confirmed by me:

>>> numpy.random.binomial(n=numpy.asarray([2,3,4], dtype='int64'),
p=numpy.asarray([.1, .2, .3], dtype='float64'))

produces:

TypeError: array cannot be safely cast to required type

It seems to be not only 32-bit specific but x86-specific. On a ppc
machine, 32-bit mode, it behaves as expected:

dwfatmention:morrislab:~$ python-32
Python 2.6.4 (r264:75706, Feb 16 2010, 21:03:46)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
import numpy
numpy.__version__
'1.3.0'
numpy.random.binomial(n=numpy.asarray([2,3,4], dtype='int64'),  
p=numpy.asarray([.1,.2,.3], dtype='float64'))
array([1, 1, 2])

So it smells a bit like an endianness bug/problem with the definition of NPY_LONG.

I can confirm the bug on OS X/Intel 32-bit, and Linux x86-32 (both
1.3.0 and most recent svn trunk), as well as its absence on Linux
x86-64. The problem seems to be with this line in [source:trunk/numpy/random/mtrand/mtrand.pyx mtrand.pyx], line
3306 in the trunk:

on = <ndarray>PyArray_FROM_OTF(n, NPY_LONG, NPY_ALIGNED)
thouis commented 12 years ago

Comment in Trac by atmention:dwf, 2010-02-26

thouis commented 12 years ago

Comment in Trac by atmention:pv, 2010-02-26

I think this is a casting issue: the function is defined to accept only int32 (= NPY_LONG on 32-bit), but int64 (= NPY_LONG_LONG) is for some reason not automatically cast to the smaller integer.

In other contexts, Numpy does downcast automatically without warnings,

x = numpy.array([1,2,3,], dtype='int32') x[:] = numpy.asarray([212312312333,3,4], dtype='int64') x array([1858914829, 3, 4]) so probably it should do it also here.

Another related issue is that on 64-bit, if you define ufunc to accept only NPY_INT, it won't accept NPY_LONG but fails instead with a similar error.

thouis commented 12 years ago

Comment in Trac by atmention:dwf, 2010-02-26

I see. What is the preferred way to cast to the native NPYLONG type? Using np.int / np.int0? And is there an intrinsic reason why 32-bit machines should only accept 32-bit integers as the 'n' argument here?

thouis commented 12 years ago

Comment in Trac by atmention:pv, 2010-02-26

Using flags NPY_ALIGNED|NPY_FORCECAST in PyArray_FROM_OTF should do it.