Skip to content

BUG: np.asarray does not create new array view when different but compatible type code is passed in the dtype argument (Trac #870) #1468

@numpy-gitbot

Description

@numpy-gitbot

Original ticket http://projects.scipy.org/numpy/ticket/870 on 2008-08-01 by trac user damian.eads, assigned to @stefanv.

Examining ndarray type codes is common in C extensions before passing array contents to functions expecting int* or long*. The type codes are ideal ensure the contents can be safely casted to int* or long* on the host machine. In some cases, the int and long types are of the same size but their type codes are different. np.asarray(..., dtype='i') should be used to create a new array view with the type code the C type code expected by the C extension; however, it does not appear to work when using it for this purpose.

Problem
I construct X as a C-long array and then I cast it to a C-int array Y (using np.asarray) but the type code does not change. However, when constructing the array from scratch as a C-int (using np.zeros), I get the right type code (ie 5).

Expectation of Behavior
I assumed that when X gets casted to a C-int, no copying should occur but a new array view should be constructed with the C-int type code.

Workaround
Casting from a C-long (type code 7) to a double to a C-int returns an array with the right type code but an ugly double copy occurs.

Recreation

# Construct X as a C-long.

In [16]: X=numpy.zeros((10,10),dtype='l')

# Now cast X to a C-int.

In [17]: Y=numpy.asarray(X, dtype='i')

# Check X and Y's data type; they are the same.

In [18]: X.dtype
Out[18]: dtype('int32')

In [19]: Y.dtype
Out[19]: dtype('int32')

# Their type codes are the same.

In [20]: X.dtype.num
Out[20]: 7

In [21]: Y.dtype.num
Out[21]: 7

# Constructing with dtype='i', gives the right type code.

In [22]: Z=numpy.zeros((10,10),dtype='i')

In [23]: Z.dtype
Out[23]: dtype('int32')

In [24]: Z.dtype.num
Out[24]: 5

Stefan van der Walt observes that the dtype objects are compared for equality but not the type codes. This explains why the asarray function does not create a new view.

In [4]: np.dtype('i') == np.dtype('l')
Out[4]: True

In [5]: np.dtype('i').num == np.dtype('l').num
Out[5]: False

Fix

Check the type codes for equality, not the dtype objects, to decide whether to create a new array view in np.asarray.


summary @seberg:

This is still true, the array fast-paths to do the no-copy behaviour is correct to not copy, but apparently not aggressive enough with creating views, on 64bit linux:

arr = np.array([1, 2, 3, 4], "q")
np.asarray(arr, dtype="l") is arr  # True
np.dtype("l").num == np.dtype("q").num  # not True

The good news: This really should be a simple fix!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions